- Updated PHP headers for all kernel files to use the new
[tinyz:tinyz.git] / kernel / class / edit.php
1 <?php
2 //
3 // Created on: <16-Apr-2002 11:00:12 amos>
4 //
5 // Copyright (C) 1999-2004 eZ systems as. All rights reserved.
6 //
7 // This source file is part of the eZ publish (tm) Open Source Content
8 // Management System.
9 //
10 // This file may be distributed and/or modified under the terms of the
11 // "GNU General Public License" version 2 as published by the Free
12 // Software Foundation and appearing in the file LICENSE included in
13 // the packaging of this file.
14 //
15 // Licencees holding a valid "eZ publish professional licence" version 2
16 // may use this file in accordance with the "eZ publish professional licence"
17 // version 2 Agreement provided with the Software.
18 //
19 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
20 // THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 // PURPOSE.
22 //
23 // The "eZ publish professional licence" version 2 is available at
24 // http://ez.no/ez_publish/licences/professional/ and in the file
25 // PROFESSIONAL_LICENCE included in the packaging of this file.
26 // For pricing of this licence please contact us via e-mail to licence@ez.no.
27 // Further contact information is available at http://ez.no/company/contact/.
28 //
29 // The "GNU General Public License" (GPL) is available at
30 // http://www.gnu.org/copyleft/gpl.html.
31 //
32 // Contact licence@ez.no if any conditions of this licencing isn't clear to
33 // you.
34 //
35
36 include_once( 'kernel/classes/ezcontentclass.php' );
37 include_once( 'kernel/classes/ezcontentclassattribute.php' );
38 include_once( 'kernel/classes/ezcontentclassclassgroup.php' );
39 include_once( 'lib/ezutils/classes/ezhttptool.php' );
40 include_once( 'lib/ezutils/classes/ezhttppersistence.php' );
41
42 $Module =& $Params['Module'];
43 $ClassID = null;
44 if ( isset( $Params['ClassID'] ) )
45     $ClassID = $Params['ClassID'];
46 $GroupID = null;
47 if ( isset( $Params['GroupID'] ) )
48     $GroupID = $Params['GroupID'];
49 $GroupName = null;
50 if ( isset( $Params['GroupName'] ) )
51     $GroupName = $Params['GroupName'];
52 $ClassVersion = null;
53 switch ( $Params['FunctionName'] )
54 {
55     case 'edit':
56     {
57     } break;
58     default:
59     {
60         eZDebug::writeError( 'Undefined function: ' . $params['Function'] );
61         $Module->setExitStatus( EZ_MODULE_STATUS_FAILED );
62         return;
63     };
64 }
65
66 if ( is_numeric( $ClassID ) )
67 {
68     $class =& eZContentClass::fetch( $ClassID, true, EZ_CLASS_VERSION_STATUS_TEMPORARY );
69
70     // If temporary version does not exist fetch the current and add temperory class to corresponding group
71     if ( $class->attribute( 'id' ) == null )
72     {
73         $class =& eZContentClass::fetch( $ClassID, true, EZ_CLASS_VERSION_STATUS_DEFINED );
74         $classGroups=& eZContentClassClassGroup::fetchGroupList( $ClassID, EZ_CLASS_VERSION_STATUS_DEFINED );
75         foreach ( $classGroups as $classGroup )
76         {
77             $groupID = $classGroup->attribute( 'group_id' );
78             $groupName = $classGroup->attribute( 'group_name' );
79             $ingroup =& eZContentClassClassGroup::create( $ClassID, EZ_CLASS_VERSION_STATUS_TEMPORARY, $groupID, $groupName );
80             $ingroup->store();
81         }
82     }
83     else
84     {
85         include_once( 'lib/ezlocale/classes/ezdatetime.php' );
86         $user =& eZUser::currentUser();
87         $contentIni =& eZIni::instance( 'content.ini' );
88         $timeOut =& $contentIni->variable( 'ClassSettings', 'DraftTimeout' );
89
90         if ( $class->attribute( 'modifier_id' ) != $user->attribute( 'contentobject_id' ) &&
91              $class->attribute( 'modified' ) + $timeOut > time() )
92         {
93             include_once( 'kernel/common/template.php' );
94             $tpl =& templateInit();
95
96             $res =& eZTemplateDesignResource::instance();
97             $res->setKeys( array( array( 'class', $class->attribute( 'id' ) ) ) ); // Class ID
98             $tpl->setVariable( 'class', $class );
99             $tpl->setVariable( 'lock_timeout', $timeOut );
100
101             $Result = array();
102             $Result['content'] =& $tpl->fetch( 'design:class/edit_denied.tpl' );
103             $Result['path'] = array( array( 'url' => '/class/grouplist/',
104                                             'text' => ezi18n( 'kernel/class', 'Class list' ) ) );
105             return $Result;
106         }
107     }
108 }
109 else
110 {
111     include_once( 'kernel/classes/datatypes/ezuser/ezuser.php' );
112     $user =& eZUser::currentUser();
113     $user_id = $user->attribute( 'contentobject_id' );
114     $class =& eZContentClass::create( $user_id );
115     $class->setAttribute( 'name', 'New Class' );
116     $class->store();
117     $ClassID = $class->attribute( 'id' );
118     $ClassVersion = $class->attribute( 'version' );
119     $ingroup =& eZContentClassClassGroup::create( $ClassID, $ClassVersion, $GroupID, $GroupName );
120     $ingroup->store();
121     $Module->redirectTo( $Module->functionURI( 'edit' ) . '/' . $ClassID );
122     return;
123 }
124 $http =& eZHttpTool::instance();
125 $contentClassHasInput = true;
126 if ( $http->hasPostVariable( 'ContentClassHasInput' ) )
127     $contentClassHasInput = $http->postVariable( 'ContentClassHasInput' );
128
129 // Find out the group where class is created or edited from.
130 if ( $http->hasSessionVariable( 'FromGroupID' ) )
131 {
132      $fromGroupID = $http->sessionVariable( 'FromGroupID' );
133 }
134 $ClassID = $class->attribute( 'id' );
135 $ClassVersion = $class->attribute( 'version' );
136 if ( $http->hasPostVariable( 'DiscardButton' ) )
137 {
138     eZSessionDestroy( $http->sessionVariable( 'CanStoreTicket' ) );
139     $http->removeSessionVariable( 'CanStoreTicket' );
140     $class->setVersion( EZ_CLASS_VERSION_STATUS_TEMPORARY );
141     $class->remove( true, $ClassVersion );
142     eZContentClassClassGroup::removeClassMembers( $ClassID, $ClassVersion );
143     if ( $fromGroupID === false )
144     {
145         $Module->redirectToView( 'grouplist' );
146     }
147     else
148     {
149         $Module->redirectTo( $Module->functionURI( 'classlist' ) . '/' . $fromGroupID . '/' );
150     }
151     return;
152 }
153
154 if ( $http->hasPostVariable( 'AddGroupButton' ) )
155 {
156     if ( $http->hasPostVariable( 'ContentClass_group') )
157     {
158         $selectedGroup = $http->postVariable( 'ContentClass_group' );
159         list ( $groupID, $groupName ) = split( '/', $selectedGroup );
160         $ingroup =& eZContentClassClassGroup::create( $ClassID, $ClassVersion, $groupID, $groupName );
161         $ingroup->store();
162     }
163 }
164
165 if ( $http->hasPostVariable( 'RemoveGroupButton' ) )
166 {
167     if ( $http->hasPostVariable( 'group_id_checked') )
168     {
169         $selectedGroup = $http->postVariable( 'group_id_checked' );
170         foreach(  $selectedGroup as $group_id )
171         {
172             eZContentClassClassGroup::remove( $ClassID, $ClassVersion, $group_id );
173         }
174     }
175 }
176
177 // Fetch attributes and definitions
178 $attributes =& $class->fetchAttributes();
179 include_once( 'kernel/classes/ezdatatype.php' );
180 eZDataType::loadAndRegisterAllTypes();
181 $datatypes =& eZDataType::registeredDataTypes();
182
183 $customAction = false;
184 $customActionAttributeID = null;
185 // Check for custom actions
186 if ( $http->hasPostVariable( 'CustomActionButton' ) )
187 {
188     $customActionArray = $http->postVariable( 'CustomActionButton' );
189     $customActionString = key( $customActionArray );
190
191     $customActionAttributeID = preg_match( "#^([0-9]+)_(.*)$#", $customActionString, $matchArray );
192
193     $customActionAttributeID = $matchArray[1];
194     $customAction = $matchArray[2];
195 }
196 // Validate input
197 $validation = array( 'processed' => false,
198                      'attributes' => array() );
199 $unvalidatedAttributes = array();
200
201 $storeActions = array( 'MoveUp',
202                        'MoveDown',
203                        'StoreButton',
204                        'ApplyButton',
205                        'NewButton',
206                        'CustomActionButton');
207 $validationRequired = false;
208 foreach( $storeActions as $storeAction )
209 {
210     if ( $http->hasPostVariable( $storeAction ) )
211     {
212         $validationRequired = true;
213         break;
214     }
215 }
216 include_once( 'lib/ezutils/classes/ezinputvalidator.php' );
217 $canStore = true;
218 $requireFixup = false;
219 if ( $contentClassHasInput )
220 {
221     if ( $validationRequired )
222     {
223         foreach ( array_keys( $attributes ) as $key )
224         {
225             $attribute =& $attributes[$key];
226             $dataType =& $attribute->dataType();
227             $status = $dataType->validateClassAttributeHTTPInput( $http, 'ContentClass', $attribute );
228             if ( $status == EZ_INPUT_VALIDATOR_STATE_INTERMEDIATE )
229                 $requireFixup = true;
230             else if ( $status == EZ_INPUT_VALIDATOR_STATE_INVALID )
231             {
232                 $canStore = false;
233                 $attributeName = $dataType->attribute( 'information' );
234                 $attributeName = $attributeName['name'];
235                 $unvalidatedAttributes[] = array( 'id' => $attribute->attribute( 'id' ),
236                                                   'identifier' => $attribute->attribute( 'identifier' ),
237                                                   'name' => $attributeName );
238             }
239         }
240         $validation['processed'] = true;
241         $validation['attributes'] = $unvalidatedAttributes;
242         $requireVariable = 'ContentAttribute_is_required_checked';
243         $searchableVariable = 'ContentAttribute_is_searchable_checked';
244         $informationCollectorVariable = 'ContentAttribute_is_information_collector_checked';
245         $canTranslateVariable = 'ContentAttribute_can_translate_checked';
246         $requireCheckedArray = array();
247         $searchableCheckedArray = array();
248         $informationCollectorCheckedArray = array();
249         $canTranslateCheckedArray = array();
250         if ( $http->hasPostVariable( $requireVariable ) )
251             $requireCheckedArray = $http->postVariable( $requireVariable );
252         if ( $http->hasPostVariable( $searchableVariable ) )
253             $searchableCheckedArray = $http->postVariable( $searchableVariable );
254         if ( $http->hasPostVariable( $informationCollectorVariable ) )
255             $informationCollectorCheckedArray = $http->postVariable( $informationCollectorVariable );
256         if ( $http->hasPostVariable( $canTranslateVariable ) )
257             $canTranslateCheckedArray = $http->postVariable( $canTranslateVariable );
258         foreach ( array_keys( $attributes ) as $key )
259         {
260             $attribute =& $attributes[$key];
261             $attributeID = $attribute->attribute( 'id' );
262             $attribute->setAttribute( 'is_required', in_array( $attributeID, $requireCheckedArray ) );
263             $attribute->setAttribute( 'is_searchable', in_array( $attributeID, $searchableCheckedArray ) );
264             $attribute->setAttribute( 'is_information_collector', in_array( $attributeID, $informationCollectorCheckedArray ) );
265             // Set can_translate to 0 if user has clicked Disable translation in GUI
266             $attribute->setAttribute( 'can_translate', !in_array( $attributeID, $canTranslateCheckedArray ) );
267         }
268     }
269 }
270
271 // Fixup input
272 if ( $requireFixup )
273 {
274     foreach( array_keys( $attributes ) as $key )
275     {
276         $attribute =& $attributes[$key];
277         $dataType =& $attribute->dataType();
278         $status = $dataType->fixupClassAttributeHTTPInput( $http, 'ContentClass', $attribute );
279     }
280 }
281
282 $cur_datatype = 0;
283 // Apply HTTP POST variables
284 if ( $contentClassHasInput )
285 {
286     eZHTTPPersistence::fetch( 'ContentAttribute', eZContentClassAttribute::definition(),
287                               $attributes, $http, true );
288     eZHttpPersistence::fetch( 'ContentClass', eZContentClass::definition(),
289                               $class, $http, false );
290     if ( $http->hasPostVariable( 'DataTypeString' ) )
291         $cur_datatype = $http->postVariable( 'DataTypeString' );
292 }
293
294 $class->setAttribute( 'version', EZ_CLASS_VERSION_STATUS_TEMPORARY );
295
296 // Fixed identifiers to only contain a-z0-9_
297 foreach( array_keys( $attributes ) as $key )
298 {
299     $attribute =& $attributes[$key];
300     $attribute->setAttribute( 'version', EZ_CLASS_VERSION_STATUS_TEMPORARY );
301     $identifier = $attribute->attribute( 'identifier' );
302     if ( $identifier == '' )
303         $identifier = $attribute->attribute( 'name' );
304     $identifier = strtolower( $identifier );
305     $identifier = preg_replace( array( "/[^a-z0-9_ ]/" ,
306                                        "/ /",
307                                        "/__+/" ),
308                                 array( "",
309                                        "_",
310                                        "_" ),
311                                 $identifier );
312     $attribute->setAttribute( 'identifier', $identifier );
313     $dataType =& $attribute->dataType();
314     $dataType->initializeClassAttribute( $attribute );
315 }
316
317 // Fixed class identifier to only contain a-z0-9_
318 $identifier = $class->attribute( 'identifier' );
319 if ( $identifier == '' )
320     $identifier = $class->attribute( 'name' );
321 $identifier = strtolower( $identifier );
322 $identifier = preg_replace( array( "/[^a-z0-9_ ]/" ,
323                                    "/ /",
324                                    "/__+/" ),
325                             array( "",
326                                    "_",
327                                    "_" ),
328                             $identifier );
329 $class->setAttribute( 'identifier', $identifier );
330
331 // Run custom actions if any
332 if ( $customAction )
333 {
334     foreach( array_keys( $attributes ) as $key )
335     {
336         $attribute =& $attributes[$key];
337         if ( $customActionAttributeID == $attribute->attribute( 'id' ) )
338         {
339             $attribute->customHTTPAction( $Module, $http, $customAction );
340         }
341     }
342 }
343
344 // Set new modification date
345 $date_time = time();
346 $class->setAttribute( 'modified', $date_time );
347 include_once( 'kernel/classes/datatypes/ezuser/ezuser.php' );
348 $user =& eZUser::currentUser();
349 $user_id = $user->attribute( 'contentobject_id' );
350 $class->setAttribute( 'modifier_id', $user_id );
351
352 // Remove attributes which are to be deleted
353 if ( $http->hasPostVariable( 'RemoveButton' ) )
354 {
355     if ( eZHttpPersistence::splitSelected( 'ContentAttribute', $attributes,
356                                            $http, 'id',
357                                            $keepers, $rejects ) )
358     {
359         $attributes = $keepers;
360         foreach ( $rejects as $reject )
361         {
362             $reject->remove();
363         }
364     }
365 }
366
367 // Fetch HTTP input
368 if ( $contentClassHasInput )
369 {
370     foreach( array_keys( $attributes ) as $key )
371     {
372         $attribute =& $attributes[$key];
373         $dataType =& $attribute->dataType();
374         $dataType->fetchClassAttributeHTTPInput( $http, 'ContentClass', $attribute );
375     }
376 }
377
378 // Store version 0 and discard version 1
379 if ( $http->hasPostVariable( 'StoreButton' ) && $canStore )
380 {
381     $firstStoreAttemt =& eZSessionRead( $http->sessionVariable( 'CanStoreTicket' ) );
382     if ( !$firstStoreAttemt )
383     {
384         if ( $fromGroupID === false )
385         {
386             $Module->redirectToView( 'grouplist' );
387         }
388         else
389         {
390             $Module->redirectTo( $Module->functionURI( 'classlist' ) . '/' . $fromGroupID . '/' );
391         }
392         return;
393     }
394     eZSessionDestroy( $http->sessionVariable( 'CanStoreTicket' ) );
395
396     // Class cleanup, update existing class objects according to new changes
397     include_once( 'kernel/classes/ezcontentobject.php' );
398     $id = $class->attribute( 'id' );
399     $oldClassAttributes = $class->fetchAttributes( $id, true, EZ_CLASS_VERSION_STATUS_DEFINED );
400     $newClassAttributes = $class->fetchAttributes( );
401     $objects = null;
402     $objectCount =& eZContentObject::fetchSameClassListCount( $ClassID );
403     if ( $objectCount > 0 )
404     {
405         // Delete object attributes which have been removed.
406         foreach ( $oldClassAttributes as $oldClassAttribute )
407         {
408             $attributeExist = false;
409             $oldClassAttributeID = $oldClassAttribute->attribute( 'id' );
410             foreach ( $newClassAttributes as $newClassAttribute )
411             {
412                 $newClassAttributeID = $newClassAttribute->attribute( 'id' );
413                 if ( $oldClassAttributeID == $newClassAttributeID )
414                     $attributeExist = true;
415             }
416             if ( !$attributeExist )
417             {
418                 $objectAttributes =& eZContentObjectAttribute::fetchSameClassAttributeIDList( $oldClassAttributeID );
419                 foreach ( $objectAttributes as $objectAttribute )
420                 {
421                     $objectAttributeID = $objectAttribute->attribute( 'id' );
422                     $objectAttribute->remove( $objectAttributeID );
423                 }
424             }
425         }
426         $class->storeDefined( $attributes );
427
428         // Add object attributes which have been added.
429         foreach ( $newClassAttributes as $newClassAttribute )
430         {
431             $attributeExist = false;
432             $newClassAttributeID = $newClassAttribute->attribute( 'id' );
433             foreach ( $oldClassAttributes as $oldClassAttribute )
434             {
435                 $oldClassAttributeID = $oldClassAttribute->attribute( 'id' );
436                 if ( $oldClassAttributeID == $newClassAttributeID )
437                     $attributeExist = true;
438             }
439             if ( !$attributeExist )
440             {
441                 if ( $objects == null )
442                 {
443                     $objects =& eZContentObject::fetchSameClassList( $ClassID );
444                 }
445                 foreach ( $objects as $object )
446                 {
447                     $contentobjectID = $object->attribute( 'id' );
448                     $objectVersions =& $object->versions();
449                     foreach ( $objectVersions as $objectVersion )
450                     {
451                         $translations = $objectVersion->translations( false );
452                         $version = $objectVersion->attribute( 'version' );
453                         foreach ( $translations as $translation )
454                         {
455                             $objectAttribute =& eZContentObjectAttribute::create( $newClassAttributeID, $contentobjectID, $version );
456                             $objectAttribute->setAttribute( 'language_code', $translation );
457                             $objectAttribute->initialize();
458                             $objectAttribute->store();
459                         }
460                     }
461                 }
462             }
463         }
464     }
465     else
466     {
467         $class->storeDefined( $attributes );
468     }
469
470     // Set the object name to the first attribute, if not set
471     $classAttributes = $class->fetchAttributes();
472
473     // Fetch the first attribute
474     if ( count( $classAttributes ) > 0 )
475     {
476         $identifier = $classAttributes[0]->attribute( 'identifier' );
477         $identifier = '<' . $identifier . '>';
478         if ( trim( $class->attribute( 'contentobject_name' ) ) == '' )
479         {
480             $class->setAttribute( 'contentobject_name', $identifier );
481             $class->store();
482         }
483     }
484
485     // Remove old version 0 first
486     eZContentClassClassGroup::removeClassMembers( $ClassID, EZ_CLASS_VERSION_STATUS_DEFINED );
487
488     $classgroups =& eZContentClassClassGroup::fetchGroupList( $ClassID, EZ_CLASS_VERSION_STATUS_TEMPORARY );
489         for ( $i=0;$i<count(  $classgroups );$i++ )
490     {
491         $classgroup =& $classgroups[$i];
492         $classgroup->setAttribute('contentclass_version', EZ_CLASS_VERSION_STATUS_DEFINED );
493         $classgroup->store();
494     }
495 //     eZContentClass::removeAttributes( false, $ClassID, EZ_CLASS_VERSION_STATUS_DEFINED );
496 //     $class->remove( true );
497 //     $class->setVersion( EZ_CLASS_VERSION_STATUS_DEFINED, $attributes );
498 //     include_once( 'kernel/classes/datatypes/ezuser/ezuser.php' );
499 //     $user =& eZUser::currentUser();
500 //     $user_id = $user->attribute( 'contentobject_id' );
501 //     $class->setAttribute( 'modifier_id', $user_id );
502 //     $class->setAttribute( 'modified', time() );
503 //     $class->adjustAttributePlacements( $attributes );
504 //     $class->store( $attributes );
505
506     // Remove version 1
507     eZContentClassClassGroup::removeClassMembers( $ClassID, EZ_CLASS_VERSION_STATUS_TEMPORARY );
508
509     $http->removeSessionVariable( 'CanStoreTicket' );
510
511     if ( $fromGroupID === false )
512     {
513         $Module->redirectToView( 'grouplist' );
514     }
515     else
516     {
517         $Module->redirectTo( $Module->functionURI( 'classlist' ) . '/' . $fromGroupID . '/' );
518     }
519     return;
520 }
521
522 // Store changes
523 if ( $canStore )
524     $class->store( $attributes );
525
526 if ( $http->hasPostVariable( 'NewButton' ) )
527 {
528     $new_attribute =& eZContentClassAttribute::create( $ClassID, $cur_datatype );
529     $attrcnt = count( $attributes ) + 1;
530     $new_attribute->setAttribute( 'name', 'new attribute'. $attrcnt );
531     $dataType = $new_attribute->dataType();
532     $dataType->initializeClassAttribute( $new_attribute );
533     $new_attribute->store();
534     $attributes[] =& $new_attribute;
535 }
536 else if ( $http->hasPostVariable( 'MoveUp' ) )
537 {
538     $attribute =& eZContentClassAttribute::fetch( $http->postVariable( 'MoveUp' ), true, EZ_CLASS_VERSION_STATUS_TEMPORARY,
539                                                   array( 'contentclass_id', 'version', 'placement' ) );
540     $attribute->move( false );
541     $Module->redirectTo( $Module->functionURI( 'edit' ) . '/' . $ClassID );
542     return;
543 }
544 else if ( $http->hasPostVariable( 'MoveDown' ) )
545 {
546     $attribute =& eZContentClassAttribute::fetch( $http->postVariable( 'MoveDown' ), true, EZ_CLASS_VERSION_STATUS_TEMPORARY,
547                                                   array( 'contentclass_id', 'version', 'placement' ) );
548     $attribute->move( true );
549     $Module->redirectTo( $Module->functionURI( 'edit' ) . '/' . $ClassID );
550     return;
551 }
552
553 $Module->setTitle( 'Edit class ' . $class->attribute( 'name' ) );
554 if ( !$http->hasSessionVariable( 'CanStoreTicket' ) )
555 {
556     $http->setSessionVariable( 'CanStoreTicket', md5( (string)rand() ) );
557     eZSessionWrite( $http->sessionVariable( 'CanStoreTicket' ), 1 );
558 }
559
560 // Template handling
561 include_once( 'kernel/common/template.php' );
562 $tpl =& templateInit();
563 $res =& eZTemplateDesignResource::instance();
564 $res->setKeys( array( array( 'class', $class->attribute( 'id' ) ) ) ); // Class ID
565 $tpl->setVariable( 'http', $http );
566 $tpl->setVariable( 'validation', $validation );
567 $tpl->setVariable( 'can_store', $canStore );
568 $tpl->setVariable( 'require_fixup', $requireFixup );
569 $tpl->setVariable( 'module', $Module );
570 $tpl->setVariable( 'class', $class );
571 $tpl->setVariable( 'attributes', $attributes );
572 $tpl->setVariable( 'datatypes', $datatypes );
573 $tpl->setVariable( 'datatype', $cur_datatype );
574
575 $Result = array();
576 $Result['content'] =& $tpl->fetch( 'design:class/edit.tpl' );
577 $Result['path'] = array( array( 'url' => '/class/edit/',
578                                 'text' => ezi18n( 'kernel/class', 'Class edit' ) ) );
579
580 ?>