1 # -*- coding: utf-8 -*-
2 # (c) 2003 Centre de Recherche en Informatique ENSMP Fontainebleau <http://cri.ensmp.fr>
3 # (c) 2003 Benoît PIN <mailto:pin@cri.ensmp.fr>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License version 2 as published
7 # by the Free Software Foundation.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 from OFS
.ObjectManager
import ObjectManager
22 from OFS
.SimpleItem
import SimpleItem
23 from OFS
.PropertyManager
import PropertyManager
24 from Globals
import InitializeClass
, DTMLFile
25 from Products
.CMFCore
.TypesTool
import FactoryTypeInformation
26 from Products
.CMFCore
.utils
import getToolByName
27 from types
import InstanceType
30 from AccessControl
import ClassSecurityInfo
, Unauthorized
31 from Products
.CMFCore
.permissions
import View
, ModifyPortalContent
, \
35 class RuleError(Exception) :
36 def __init__(self
, errorMessage
) :
37 self
.errorMessage
= errorMessage
40 return self
.errorMessage
42 addMosaicBlockInformationForm
= DTMLFile('dtml/addMosaicBlockForm', globals())
44 def addMosaicBlockInformation(self
, id=None, blockType
= '', metaFti
= None, REQUEST
=None) :
45 """Add a MosaicBlock"""
47 metaFtis
= config
.getDefaultBlockMetaFtis()
48 if not metaFtis
.has_key(blockType
) :
49 raise ValueError, "Unknown block type : %s" % blockType
51 blockFti
= metaFtis
[blockType
]
53 blockFti
= metaFti
.copy()
55 raise AttributeError, """
56 You must specify a default block type or a meta factory type information
63 mb
= MosaicBlockInformation(blockFti
)
64 self
._setObject
(id, mb
)
66 if REQUEST
is not None:
67 REQUEST
.RESPONSE
.redirect('%s/manage_main' % self
.absolute_url())
71 class MosaicBlockInformation(ObjectManager
, FactoryTypeInformation
) :
74 meta_type
= "Mosaic Block Information"
76 isPrincipiaFolderish
= 0
78 security
= ClassSecurityInfo()
80 _fti_properties
= FactoryTypeInformation
._properties
82 _properties
= (_fti_properties
[:5] +
83 ({'id':'template', 'type': 'string', 'mode':'w',
85 {'id':'notify_wf', 'type': 'boolean', 'mode':'w',
86 'label':'Notify Workflow Created'},) +
91 manage_slotsForm
= DTMLFile('dtml/slotsForm', globals())
92 manage_rulesForm
= DTMLFile('dtml/rulesForm', globals())
93 manage_options
= (FactoryTypeInformation
.manage_options
[:1] +
94 ({'label' : 'Slots', 'action' : 'manage_slotsForm'},) +
95 ({'label' : 'Rules', 'action' : 'manage_rulesForm'},) +
96 FactoryTypeInformation
.manage_options
[1:]
100 def __init__(self
, blockFti
) :
101 FactoryTypeInformation
.__init
__(self
, **blockFti
)
103 # init Slots informations
104 for slot
in blockFti
['slots'] :
105 slotInfo
= SlotInfo(slot
['id'], slot
['type'], slotArgs
= slot
['args'])
106 self
._setObject
(slot
['id'], slotInfo
)
108 # init Rules informations
109 for rule
in blockFti
['rules'] :
110 ruleInfo
= RuleInfo(rule
['blockType'], rule
['maxNbInstance'], rule
['allowMove'], rule
['mode'])
111 self
._setObject
(rule
['blockType'], ruleInfo
)
114 security
.declareProtected(ManagePortal
, 'manage_addSlot')
115 def manage_addSlot(self
, id, type, REQUEST
=None) :
116 """Add a slot contruction information"""
117 slotInfo
= SlotInfo(id, type)
118 self
._setObject
(id, slotInfo
)
120 return REQUEST
.RESPONSE
.redirect(REQUEST
['HTTP_REFERER'])
122 security
.declareProtected(ManagePortal
, 'saveSlots')
123 def saveSlots(self
, REQUEST
=None, **kw
) :
124 """Save slots from ZMI form"""
125 # actualy the ':record' casting in an input form create an InstanceType instead of DictType
126 kw
.update(REQUEST
.form
)
127 dicArgsListItems
= [ (argKey
, kw
[argKey
]) for argKey
in kw
.keys() if type(kw
[argKey
]) == InstanceType
]
128 for key
, args
in dicArgsListItems
:
129 slotToEdit
= getattr(self
, key
)
130 if key
!= args
['id'] :
131 self
.manage_renameObject(key
, args
['id'])
132 slotToEdit
.id = args
['id']
133 slotToEdit
.type = args
['type']
134 if REQUEST
is not None:
135 return REQUEST
.RESPONSE
.redirect(REQUEST
['URL1'] + '/manage_slotsForm?manage_tabs_message=Saved changes.')
137 security
.declareProtected(ManagePortal
, 'deleteSlots')
138 def deleteSlots(self
, slotSelection
=None, REQUEST
=None) :
141 self
.manage_delObjects(ids
=slotSelection
)
143 return REQUEST
.RESPONSE
.redirect(REQUEST
['HTTP_REFERER'])
147 security
.declareProtected(ManagePortal
, 'manage_addSlot')
148 def manage_addRule(self
, id, maxNbInstance
, allowMove
, mode
, REQUEST
=None) :
149 """Add a rule information"""
150 ruleInfo
= RuleInfo(id, maxNbInstance
, allowMove
, mode
)
151 self
._setObject
(id, ruleInfo
)
153 return REQUEST
.RESPONSE
.redirect(REQUEST
['HTTP_REFERER'])
155 security
.declareProtected(ManagePortal
, 'saveSlots')
156 def saveRules(self
, REQUEST
=None, **kw
) :
157 """Save rules from ZMI form"""
158 # actualy the ':record' casting in an input form create an InstanceType instead of DictType
159 kw
.update(REQUEST
.form
)
160 dicArgsListItems
= [ (argKey
, kw
[argKey
]) for argKey
in kw
.keys() if type(kw
[argKey
]) == InstanceType
]
161 for key
, kwords
in dicArgsListItems
:
162 ruleToEdit
= getattr(self
, key
)
163 if key
!= kwords
['id'] :
164 self
.manage_renameObject(key
, kwords
['id'])
165 #slotToEdit.id = args['id']
168 for k
in kwords
.keys() : #kwords is an InstanceType not a DictType...
169 kwArgs
[k
] = kwords
[k
]
171 ruleToEdit
.edit(**kwArgs
)
173 if REQUEST
is not None:
174 return REQUEST
.RESPONSE
.redirect(REQUEST
['URL1'] + '/manage_rulesForm?manage_tabs_message=Saved changes.')
176 security
.declareProtected(ManagePortal
, 'deleteSlots')
177 def deleteRules(self
, ruleSelection
=None, REQUEST
=None) :
180 self
.manage_delObjects(ids
=ruleSelection
)
182 return REQUEST
.RESPONSE
.redirect(REQUEST
['HTTP_REFERER'])
185 def _checkConstructionRules(self
, container
) :
187 typesTool
= getToolByName(self
, 'mosaic_tool')
188 container_ti
= typesTool
.getTypeInfo(container
)
189 rules
= container_ti
.objectValues(['Rule Information',])
190 container_subObjs
= container
.objectValues()
192 if self
.getId() in map(lambda x
: x
.getId(), rules
) :
193 maxNbInstance
= container_ti
._getOb
(self
.getId()).maxNbInstance
195 if maxNbInstance
<= len( [sob
for sob
in container_subObjs
if sob
.portal_type
== self
.getId()]) :
196 raise RuleError
, "It's not allowed to add a new '%s', the quota is exceeded in this block" % \
201 return 1 # pas de limitation du nombre d'instance
203 raise RuleError
, "'%s' block type construction is not authorized in '%s'" % \
204 (self
.getId(), container_ti
.getId())
207 security
.declarePublic('isConstructionAllowed')
208 def isConstructionAllowed ( self
, container
):
210 check factory, permissions and rules
212 if FactoryTypeInformation
.isConstructionAllowed ( self
, container
) :
213 typesTool
= getToolByName(self
, 'mosaic_tool')
214 container_ti
= typesTool
.getTypeInfo(container
)
215 if hasattr(container_ti
, '_checkConstructionRules') :
217 return self
._checkConstructionRules
(container
)
225 def _getFactoryMethod(self
, container
, check_security
=1):
226 # pas très beau cette surcharge mais
227 # FactoryTypeInformation ne vérifie pas la
228 # possibilité de création par un appel à isConstructionAllowed.
230 if not check_security
: return FactoryTypeInformation
._getFactoryMethod
(self
, container
)
232 if self
.isConstructionAllowed(container
) :
233 return FactoryTypeInformation
._getFactoryMethod
(self
, container
)
235 raise Unauthorized
, ('Cannot create %s' % self
.getId())
238 security
.declarePrivate('_constructInstance')
239 def _constructInstance(self
, container
, id, *args
, **kw
):
240 ob
= super(MosaicBlockInformation
, self
)._constructInstance
(container
, id, *args
, **kw
)
241 typesTool
= getToolByName(self
, 'portal_types')
243 # Add and init slots in block
244 for si
in self
.objectValues(['Slot Information',]) :
246 for key
, value
in si
.propertyItems() :
249 typesTool
.constructContent(si
.type, ob
, si
.id, **kw
)
253 InitializeClass(MosaicBlockInformation
)
255 def addSlotInfo(dispatcher
, id, type, slotArgs
) :
258 class SlotInfo(SimpleItem
, PropertyManager
) :
259 """Encapsulate slot informations"""
260 meta_type
="Slot Information"
262 property_extensible_schema__
= 1
264 manage_propertiesForm
= DTMLFile('dtml/properties', globals())
265 manage_options
= PropertyManager
.manage_options
+ SimpleItem
.manage_options
267 def __init__(self
, id, type, slotArgs
={}) :
270 for argId
in slotArgs
.keys() :
271 self
.manage_addProperty(argId
, slotArgs
[argId
]['value'], slotArgs
[argId
]['type'])
273 InitializeClass(PropertyManager
)
276 def addRuleInfo(dispatcher
, id, **kw
) :
279 class RuleInfo(SimpleItem
):
280 """Encapsulate block rule informations"""
281 meta_type
= 'Rule Information'
283 def __init__(self
, id, maxNbInstance
,
285 allowMoveUpAndDown
=0,
286 allowMoveRightAndLeft
=0) :
287 self
.id = id # actualy Block Type name info
288 self
.maxNbInstance
= maxNbInstance
290 self
.allowMoveUpAndDown
= 1
291 self
.allowMoveRightAndLeft
= 1
293 self
.allowMoveUpAndDown
= allowMoveUpAndDown
294 self
.allowMoveRightAndLeft
= allowMoveRightAndLeft
295 self
.allowMove
= allowMove
298 security
= ClassSecurityInfo()
300 security
.declareProtected(ManagePortal
, 'edit')
301 def edit(self
, **kw
) :
302 for key
in kw
.keys() :
303 if hasattr(self
, key
) :
304 setattr(self
, key
, kw
[key
])
306 InitializeClass(RuleInfo
)