Copie de MosaicDocument à partir de :
[MosaicDocument.git] / MosaicBlockInformation.py
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>
4 #
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.
8 #
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.
13 #
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
17 # 02111-1307, USA.
18 #
19
20
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
28
29 from AccessControl import ClassSecurityInfo, Unauthorized
30 from Products.CMFCore.permissions import View, ModifyPortalContent, \
31 ManagePortal
32
33
34 class RuleError(Exception) :
35 def __init__(self, errorMessage) :
36 self.errorMessage = errorMessage
37
38 def __str__(self) :
39 return self.errorMessage
40
41 addMosaicBlockInformationForm = DTMLFile('dtml/addMosaicBlockForm', globals())
42
43 def addMosaicBlockInformation(self, id=None, blockType = '', metaFti = None, REQUEST=None) :
44 """Add a MosaicBlock"""
45 mosaicTool = self.mosaic_tool
46 if blockType :
47 metaFtis = mosaicTool.getDefaultBlockMetaFtis()
48 if not metaFtis.has_key(blockType) :
49 raise ValueError, "Unknown block type : %s" % blockType
50 else :
51 blockFti = metaFtis[blockType]
52 elif metaFti :
53 blockFti = metaFti.copy()
54 else :
55 raise AttributeError, """
56 You must specify a default block type or a meta factory type information
57 """
58 if not id :
59 id = blockFti['id']
60 else :
61 blockFti['id'] = id
62
63 mb = MosaicBlockInformation(blockFti)
64 self._setObject(id, mb)
65
66 if REQUEST is not None:
67 REQUEST.RESPONSE.redirect('%s/manage_main' % self.absolute_url())
68 return id
69
70
71 class MosaicBlockInformation(ObjectManager, FactoryTypeInformation) :
72 """Base Block"""
73
74 meta_type = "Mosaic Block Information"
75
76 isPrincipiaFolderish = 0
77
78 security = ClassSecurityInfo()
79
80 _fti_properties = FactoryTypeInformation._properties
81
82 _properties = (_fti_properties[:5] +
83 ({'id':'template', 'type': 'string', 'mode':'w',
84 'label':'Template'},
85 {'id':'notify_wf', 'type': 'boolean', 'mode':'w',
86 'label':'Notify Workflow Created'},) +
87 _fti_properties[5:]
88 )
89
90
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:]
97 )
98
99
100 def __init__(self, blockFti) :
101 FactoryTypeInformation.__init__(self, **blockFti)
102
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)
107
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)
112
113
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)
119 if REQUEST :
120 return REQUEST.RESPONSE.redirect(REQUEST['HTTP_REFERER'])
121
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.')
136
137 security.declareProtected(ManagePortal, 'deleteSlots')
138 def deleteSlots(self, slotSelection=None, REQUEST=None) :
139 """Delete slots"""
140 if slotSelection :
141 self.manage_delObjects(ids=slotSelection)
142 if REQUEST :
143 return REQUEST.RESPONSE.redirect(REQUEST['HTTP_REFERER'])
144
145
146
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)
152 if REQUEST :
153 return REQUEST.RESPONSE.redirect(REQUEST['HTTP_REFERER'])
154
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']
166 kwArgs = {}
167
168 for k in kwords.keys() : #kwords is an InstanceType not a DictType...
169 kwArgs[k] = kwords[k]
170
171 ruleToEdit.edit(**kwArgs)
172
173 if REQUEST is not None:
174 return REQUEST.RESPONSE.redirect(REQUEST['URL1'] + '/manage_rulesForm?manage_tabs_message=Saved changes.')
175
176 security.declareProtected(ManagePortal, 'deleteSlots')
177 def deleteRules(self, ruleSelection=None, REQUEST=None) :
178 """Delete rules"""
179 if ruleSelection :
180 self.manage_delObjects(ids=ruleSelection)
181 if REQUEST :
182 return REQUEST.RESPONSE.redirect(REQUEST['HTTP_REFERER'])
183
184
185 def _checkConstructionRules(self, container) :
186 """Check """
187 typesTool = getToolByName(self, 'mosaic_tool')
188 container_ti = typesTool.getTypeInfo(container)
189 rules = container_ti.objectValues(['Rule Information',])
190 container_subObjs = container.objectValues()
191
192 if self.getId() in map(lambda x : x.getId(), rules) :
193 maxNbInstance = container_ti._getOb(self.getId()).maxNbInstance
194 if 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" % \
197 self.getId()
198 else :
199 return 1
200 else :
201 return 1 # pas de limitation du nombre d'instance
202 else :
203 raise RuleError, "'%s' block type construction is not authorized in '%s'" % \
204 (self.getId(), container_ti.getId())
205
206
207 security.declarePublic('isConstructionAllowed')
208 def isConstructionAllowed ( self, container ):
209 """
210 check factory, permissions and rules
211 """
212 if FactoryTypeInformation.isConstructionAllowed ( self, container ) :
213 typesTool = getToolByName(self, 'mosaic_tool')
214 container_ti = typesTool.getTypeInfo(container)
215 if hasattr(container_ti, '_checkConstructionRules') :
216 try :
217 return self._checkConstructionRules(container)
218 except RuleError :
219 return 0
220 return 1
221 else :
222 return 0
223
224
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.
229
230 if not check_security : return FactoryTypeInformation._getFactoryMethod(self, container)
231
232 if self.isConstructionAllowed(container) :
233 return FactoryTypeInformation._getFactoryMethod(self, container)
234
235 raise Unauthorized, ('Cannot create %s' % self.getId())
236
237
238 security.declarePrivate('_finishConstruction')
239 def _finishConstruction(self, ob) :
240 """Finish the construction of a content block object."""
241 if hasattr(ob, '_setPortalTypeName'):
242 ob._setPortalTypeName(self.getId())
243
244 typesTool = getToolByName(self, 'portal_types')
245
246 # Add and init slots in block
247 for si in self.objectValues(['Slot Information',]) :
248 kw = {}
249 for key, value in si.propertyItems() :
250 kw[key] = value
251
252 typesTool.constructContent(si.type, ob, si.id, **kw)
253
254 if self.notify_wf :
255 ob.notifyWorkflowCreated()
256 return ob
257
258
259 InitializeClass(MosaicBlockInformation)
260
261 def addSlotInfo(dispatcher, id, type, slotArgs) :
262 pass
263
264 class SlotInfo(SimpleItem, PropertyManager) :
265 """Encapsulate slot informations"""
266 meta_type="Slot Information"
267 _properties = ()
268 property_extensible_schema__ = 1
269
270 manage_propertiesForm = DTMLFile('dtml/properties', globals())
271 manage_options = PropertyManager.manage_options + SimpleItem.manage_options
272
273 def __init__(self, id, type, slotArgs={}) :
274 self.id = id
275 self.type = type
276 for argId in slotArgs.keys() :
277 self.manage_addProperty(argId, slotArgs[argId]['value'], slotArgs[argId]['type'])
278
279 InitializeClass(PropertyManager)
280
281
282 def addRuleInfo(dispatcher, id, **kw) :
283 pass
284
285 class RuleInfo(SimpleItem):
286 """Encapsulate block rule informations"""
287 meta_type = 'Rule Information'
288
289 def __init__(self, id, maxNbInstance,
290 allowMove, mode,
291 allowMoveUpAndDown=0,
292 allowMoveRightAndLeft=0) :
293 self.id = id # actualy Block Type name info
294 self.maxNbInstance = maxNbInstance
295 if allowMove :
296 self.allowMoveUpAndDown = 1
297 self.allowMoveRightAndLeft = 1
298 else :
299 self.allowMoveUpAndDown = allowMoveUpAndDown
300 self.allowMoveRightAndLeft = allowMoveRightAndLeft
301 self.allowMove = allowMove
302 self.mode = mode
303
304 security = ClassSecurityInfo()
305
306 security.declareProtected(ManagePortal, 'edit')
307 def edit(self, **kw) :
308 for key in kw.keys() :
309 if hasattr(self, key) :
310 setattr(self, key, kw[key])
311
312 InitializeClass(RuleInfo)