- Implemented: license header update
[tinyz:tinyz.git] / kernel / class / edit.php
1 <?php
2 //
3 // Created on: <16-Apr-2002 11:00:12 amos>
4 //
5 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
6 // SOFTWARE NAME: eZ Publish
7 // SOFTWARE RELEASE: 4.1.x
8 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
9 // SOFTWARE LICENSE: GNU General Public License v2.0
10 // NOTICE: >
11 //   This program is free software; you can redistribute it and/or
12 //   modify it under the terms of version 2.0  of the GNU General
13 //   Public License as published by the Free Software Foundation.
14 //
15 //   This program is distributed in the hope that it will be useful,
16 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
17 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 //   GNU General Public License for more details.
19 //
20 //   You should have received a copy of version 2.0 of the GNU General
21 //   Public License along with this program; if not, write to the Free
22 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 //   MA 02110-1301, USA.
24 //
25 //
26 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
27 //
28
29 //include_once( 'kernel/classes/ezcontentclass.php' );
30 //include_once( 'kernel/classes/ezcontentclassattribute.php' );
31 //include_once( 'kernel/classes/ezcontentclassclassgroup.php' );
32 //include_once( 'lib/ezutils/classes/ezhttptool.php' );
33 //include_once( 'lib/ezutils/classes/ezhttppersistence.php' );
34
35
36 $Module = $Params['Module'];
37 $ClassID = $Params['ClassID'];
38 $GroupID = $Params['GroupID'];
39 $GroupName = $Params['GroupName'];
40 $EditLanguage = $Params['Language'];
41 $FromLanguage = false;
42 $ClassVersion = null;
43
44
45 switch ( $Params['FunctionName'] )
46 {
47     case 'edit':
48     {
49     } break;
50     default:
51     {
52         eZDebug::writeError( 'Undefined function: ' . $params['Function'] );
53         $Module->setExitStatus( eZModule::STATUS_FAILED );
54         return;
55     };
56 }
57
58 $http = eZHTTPTool::instance();
59 if ( $http->hasPostVariable( 'CancelConflictButton' ) )
60 {
61     $Module->redirectToView( 'grouplist' );
62 }
63
64 if ( $http->hasPostVariable( 'EditLanguage' ) )
65 {
66     $EditLanguage = $http->postVariable( 'EditLanguage' );
67 }
68
69 if ( is_numeric( $ClassID ) )
70 {
71     $class = eZContentClass::fetch( $ClassID, true, eZContentClass::VERSION_STATUS_TEMPORARY );
72
73     // If temporary version does not exist fetch the current and add temperory class to corresponding group
74     if ( !is_object( $class ) or $class->attribute( 'id' ) == null )
75     {
76         $class = eZContentClass::fetch( $ClassID, true, eZContentClass::VERSION_STATUS_DEFINED );
77         if( is_null( $class ) ) // Class does not exist
78         {
79             return $Module->handleError( eZError::KERNEL_NOT_AVAILABLE, 'kernel' );
80         }
81         $classGroups= eZContentClassClassGroup::fetchGroupList( $ClassID, eZContentClass::VERSION_STATUS_DEFINED );
82         foreach ( $classGroups as $classGroup )
83         {
84             $groupID = $classGroup->attribute( 'group_id' );
85             $groupName = $classGroup->attribute( 'group_name' );
86             $ingroup = eZContentClassClassGroup::create( $ClassID, eZContentClass::VERSION_STATUS_TEMPORARY, $groupID, $groupName );
87             $ingroup->store();
88         }
89     }
90     else
91     {
92         //include_once( 'lib/ezlocale/classes/ezdatetime.php' );
93         $user = eZUser::currentUser();
94         $contentIni = eZINI::instance( 'content.ini' );
95         $timeOut = $contentIni->variable( 'ClassSettings', 'DraftTimeout' );
96
97         if ( $class->attribute( 'modifier_id' ) != $user->attribute( 'contentobject_id' ) &&
98              $class->attribute( 'modified' ) + $timeOut > time() )
99         {
100             require_once( 'kernel/common/template.php' );
101             $tpl = templateInit();
102
103             $res = eZTemplateDesignResource::instance();
104             $res->setKeys( array( array( 'class', $class->attribute( 'id' ) ) ) ); // Class ID
105             $tpl->setVariable( 'class', $class );
106             $tpl->setVariable( 'lock_timeout', $timeOut );
107
108             $Result = array();
109             $Result['content'] = $tpl->fetch( 'design:class/edit_denied.tpl' );
110             $Result['path'] = array( array( 'url' => '/class/grouplist/',
111                                             'text' => ezi18n( 'kernel/class', 'Class list' ) ) );
112             return $Result;
113         }
114     }
115 }
116 else
117 {
118     //include_once( 'kernel/classes/datatypes/ezuser/ezuser.php' );
119
120     if ( !$EditLanguage )
121     {
122         $language = eZContentLanguage::topPriorityLanguage();
123         if ( $language )
124         {
125             $EditLanguage = $language->attribute( 'locale' );
126         }
127         else
128         {
129             eZDebug::writeError( 'Undefined default language', 'class/edit.php' );
130             $Module->setExitStatus( eZModule::STATUS_FAILED );
131             return;
132         }
133     }
134
135     if ( is_numeric( $GroupID ) and is_string( $GroupName ) and $GroupName != '' )
136     {
137         $user = eZUser::currentUser();
138         $user_id = $user->attribute( 'contentobject_id' );
139         $class = eZContentClass::create( $user_id, array(), $EditLanguage );
140         $class->setName( ezi18n( 'kernel/class/edit', 'New Class' ), $EditLanguage );
141         $class->store();
142         $editLanguageID = eZContentLanguage::idByLocale( $EditLanguage );
143         $class->setAlwaysAvailableLanguageID( $editLanguageID );
144         $ClassID = $class->attribute( 'id' );
145         $ClassVersion = $class->attribute( 'version' );
146         $ingroup = eZContentClassClassGroup::create( $ClassID, $ClassVersion, $GroupID, $GroupName );
147         $ingroup->store();
148         $Module->redirectTo( $Module->functionURI( 'edit' ) . '/' . $ClassID . '/(language)/' . $EditLanguage );
149         return;
150     }
151     else
152     {
153         $errorResponseGroupName = ( $GroupName == '' ) ? '<Empty name>' : $GroupName;
154         $errorResponseGroupID = ( !is_numeric( $GroupID ) ) ? '<Empty ID>' : $GroupID;
155         eZDebug::writeError( "Unknown class group: {$errorResponseGroupName} (ID: {$errorResponseGroupID})", 'Kernel - Class - Edit' );
156         $Module->setExitStatus( eZModule::STATUS_FAILED );
157         return $Module->handleError( eZError::KERNEL_NOT_AVAILABLE, 'kernel' );
158     }
159 }
160
161
162 $contentClassHasInput = true;
163 if ( $http->hasPostVariable( 'ContentClassHasInput' ) )
164     $contentClassHasInput = $http->postVariable( 'ContentClassHasInput' );
165
166 // Find out the group where class is created or edited from.
167 if ( $http->hasSessionVariable( 'FromGroupID' ) )
168 {
169     $fromGroupID = $http->sessionVariable( 'FromGroupID' );
170 }
171 else
172 {
173     $fromGroupID = false;
174 }
175 $ClassID = $class->attribute( 'id' );
176 $ClassVersion = $class->attribute( 'version' );
177
178 $validation = array( 'processed' => false,
179                      'groups' => array(),
180                      'attributes' => array(),
181                      'class_errors' => array() );
182 $unvalidatedAttributes = array();
183
184 if ( $http->hasPostVariable( 'DiscardButton' ) )
185 {
186     eZSessionDestroy( $http->sessionVariable( 'CanStoreTicket' ) );
187     $http->removeSessionVariable( 'CanStoreTicket' );
188     $class->setVersion( eZContentClass::VERSION_STATUS_TEMPORARY );
189     $class->remove( true, eZContentClass::VERSION_STATUS_TEMPORARY );
190     eZContentClassClassGroup::removeClassMembers( $ClassID, eZContentClass::VERSION_STATUS_TEMPORARY );
191     if ( $fromGroupID === false )
192     {
193         $Module->redirectToView( 'grouplist' );
194     }
195     else
196     {
197         $Module->redirectTo( $Module->functionURI( 'classlist' ) . '/' . $fromGroupID . '/' );
198     }
199     return;
200 }
201 if ( $http->hasPostVariable( 'AddGroupButton' ) && $http->hasPostVariable( 'ContentClass_group' ) )
202 {
203     //include_once( "kernel/class/ezclassfunctions.php" );
204     eZClassFunctions::addGroup( $ClassID, $ClassVersion, $http->postVariable( 'ContentClass_group' ) );
205 }
206 if ( $http->hasPostVariable( 'RemoveGroupButton' ) && $http->hasPostVariable( 'group_id_checked' ) )
207 {
208     //include_once( "kernel/class/ezclassfunctions.php" );
209     if ( !eZClassFunctions::removeGroup( $ClassID, $ClassVersion, $http->postVariable( 'group_id_checked' ) ) )
210     {
211         $validation['groups'][] = array( 'text' => ezi18n( 'kernel/class', 'You have to have at least one group that the class belongs to!' ) );
212         $validation['processed'] = true;
213     }
214 }
215
216 // Fetch attributes and definitions
217 $attributes = $class->fetchAttributes();
218
219 if ( $http->hasPostVariable( 'SelectLanguageButton' ) && $http->hasPostVariable( 'EditLanguage' ) )
220 {
221     $EditLanguage = $http->postVariable( 'EditLanguage' );
222
223     $FromLanguage = 'None';
224     if ( $http->hasPostVariable( 'FromLanguage' ) )
225         $FromLanguage = $http->postVariable( 'FromLanguage' );
226
227     foreach ( array_keys( $attributes ) as $key )
228     {
229         $name = '';
230         if ( $FromLanguage != 'None' )
231         {
232             $name = $attributes[$key]->name( $FromLanguage );
233         }
234         $attributes[$key]->setName( $name, $EditLanguage );
235     }
236
237     $name = '';
238     if ( $FromLanguage != 'None' )
239     {
240         $name = $class->name( $FromLanguage );
241     }
242
243     $class->setName( $name, $EditLanguage );
244 }
245
246 // No language was specified in the URL, we need to figure out
247 // the language to use.
248 if ( !$EditLanguage )
249 {
250     // Check number of languages
251     //include_once( 'kernel/classes/ezcontentlanguage.php' );
252     $languages = eZContentLanguage::fetchList();
253     // If there is only one language we choose it for the user.
254     if ( count( $languages ) == 1 )
255     {
256         $language = array_shift( $languages );
257         $EditLanguage = $language->attribute( 'locale' );
258     }
259     else
260     {
261         $canCreateLanguages = $class->attribute( 'can_create_languages' );
262         if ( count( $canCreateLanguages ) == 0)
263         {
264             $EditLanguage = $class->attribute( 'top_priority_language_locale' );
265         }
266         else
267         {
268             require_once( 'kernel/common/template.php' );
269
270             $tpl = templateInit();
271
272             $res = eZTemplateDesignResource::instance();
273             $res->setKeys( array( array( 'class', $class->attribute( 'id' ) ) ) ); // Class ID
274
275             $tpl->setVariable( 'module', $Module );
276             $tpl->setVariable( 'class', $class );
277
278             $Result = array();
279             $Result['content'] = $tpl->fetch( 'design:class/select_language.tpl' );
280             $Result['path'] = array( array( 'url' => '/class/edit/',
281                                             'text' => ezi18n( 'kernel/class', 'Class edit' ) ) );
282             return $Result;
283         }
284     }
285 }
286
287 //include_once( 'kernel/classes/ezdatatype.php' );
288 eZDataType::loadAndRegisterAllTypes();
289 $datatypes = eZDataType::registeredDataTypes();
290
291 $customAction = false;
292 $customActionAttributeID = null;
293 // Check for custom actions
294 if ( $http->hasPostVariable( 'CustomActionButton' ) )
295 {
296     $customActionArray = $http->postVariable( 'CustomActionButton' );
297     $customActionString = key( $customActionArray );
298
299     $customActionAttributeID = preg_match( "#^([0-9]+)_(.*)$#", $customActionString, $matchArray );
300
301     $customActionAttributeID = $matchArray[1];
302     $customAction = $matchArray[2];
303 }
304
305
306 // Validate input
307 $storeActions = array( 'MoveUp',
308                        'MoveDown',
309                        'StoreButton',
310                        'ApplyButton',
311                        'NewButton',
312                        'CustomActionButton');
313 $validationRequired = false;
314 foreach( $storeActions as $storeAction )
315 {
316     if ( $http->hasPostVariable( $storeAction ) )
317     {
318         $validationRequired = true;
319         break;
320     }
321 }
322
323 //include_once( 'lib/ezutils/classes/ezinputvalidator.php' );
324 $canStore = true;
325 $requireFixup = false;
326 if ( $contentClassHasInput )
327 {
328     if ( $validationRequired )
329     {
330         foreach ( $attributes as $attribute )
331         {
332             $dataType = $attribute->dataType();
333             $status = $dataType->validateClassAttributeHTTPInput( $http, 'ContentClass', $attribute );
334             if ( $status == eZInputValidator::STATE_INTERMEDIATE )
335                 $requireFixup = true;
336             else if ( $status == eZInputValidator::STATE_INVALID )
337             {
338                 $canStore = false;
339                 $attributeName = $dataType->attribute( 'information' );
340                 $attributeName = $attributeName['name'];
341                 $unvalidatedAttributes[] = array( 'id' => $attribute->attribute( 'id' ),
342                                                   'identifier' => $attribute->attribute( 'identifier' ) ? $attribute->attribute( 'identifier' ) : $attribute->attribute( 'name' ),
343                                                   'name' => $attributeName );
344             }
345         }
346         $validation['processed'] = true;
347         $validation['attributes'] = $unvalidatedAttributes;
348         $requireVariable = 'ContentAttribute_is_required_checked';
349         $searchableVariable = 'ContentAttribute_is_searchable_checked';
350         $informationCollectorVariable = 'ContentAttribute_is_information_collector_checked';
351         $canTranslateVariable = 'ContentAttribute_can_translate_checked';
352         $requireCheckedArray = array();
353         $searchableCheckedArray = array();
354         $informationCollectorCheckedArray = array();
355         $canTranslateCheckedArray = array();
356         if ( $http->hasPostVariable( $requireVariable ) )
357             $requireCheckedArray = $http->postVariable( $requireVariable );
358         if ( $http->hasPostVariable( $searchableVariable ) )
359             $searchableCheckedArray = $http->postVariable( $searchableVariable );
360         if ( $http->hasPostVariable( $informationCollectorVariable ) )
361             $informationCollectorCheckedArray = $http->postVariable( $informationCollectorVariable );
362         if ( $http->hasPostVariable( $canTranslateVariable ) )
363             $canTranslateCheckedArray = $http->postVariable( $canTranslateVariable );
364
365         if ( $http->hasPostVariable( 'ContentAttribute_priority' ) )
366             $placementArray = $http->postVariable( 'ContentAttribute_priority' );
367
368         foreach ( $attributes as $key => $attribute )
369         {
370             $attributeID = $attribute->attribute( 'id' );
371             $attribute->setAttribute( 'is_required', in_array( $attributeID, $requireCheckedArray ) );
372             $attribute->setAttribute( 'is_searchable', in_array( $attributeID, $searchableCheckedArray ) );
373             $attribute->setAttribute( 'is_information_collector', in_array( $attributeID, $informationCollectorCheckedArray ) );
374             // Set can_translate to 0 if user has clicked Disable translation in GUI
375             $attribute->setAttribute( 'can_translate', !in_array( $attributeID, $canTranslateCheckedArray ) );
376
377             $placement = (int) $placementArray[$key];
378             if ( $attribute->attribute( 'placement' ) != $placement )
379                 $attribute->setAttribute( 'placement', $placement );
380         }
381     }
382 }
383
384 // Fixup input
385 if ( $requireFixup )
386 {
387     foreach( $attributes as $attribute )
388     {
389         $dataType = $attribute->dataType();
390         $status = $dataType->fixupClassAttributeHTTPInput( $http, 'ContentClass', $attribute );
391     }
392 }
393
394 $cur_datatype = 'ezstring';
395 // Apply HTTP POST variables
396 if ( $contentClassHasInput )
397 {
398     eZHTTPPersistence::fetch( 'ContentAttribute', eZContentClassAttribute::definition(), $attributes, $http, true );
399     if ( $http->hasPostVariable( 'ContentAttribute_name' ) )
400     {
401         $attributeNames = $http->postVariable( 'ContentAttribute_name' );
402         foreach( array_keys( $attributes ) as $key )
403         {
404             if ( isset( $attributeNames[$key] ) )
405             {
406                 $attributes[$key]->setName( $attributeNames[$key], $EditLanguage );
407             }
408         }
409     }
410
411     eZHTTPPersistence::fetch( 'ContentClass', eZContentClass::definition(), $class, $http, false );
412     if ( $http->hasPostVariable( 'ContentClass_name' ) )
413     {
414         $class->setName( $http->postVariable( 'ContentClass_name' ), $EditLanguage );
415     }
416
417     if ( $http->hasVariable( 'ContentClass_is_container_exists' ) )
418     {
419         if ( $http->hasVariable( 'ContentClass_is_container_checked' ) )
420         {
421             $class->setAttribute( "is_container", 1 );
422         }
423         else
424         {
425             $class->setAttribute( "is_container", 0 );
426         }
427     }
428
429     if ( $http->hasVariable( 'ContentClass_always_available_exists' ) )
430     {
431         if ( $http->hasVariable( 'ContentClass_always_available' ) )
432         {
433             $class->setAttribute( 'always_available', 1 );
434         }
435         else
436         {
437             $class->setAttribute( 'always_available', 0 );
438         }
439     }
440
441     if ( $http->hasVariable( 'ContentClass_default_sorting_exists' ) )
442     {
443         if ( $http->hasVariable( 'ContentClass_default_sorting_field' ) )
444         {
445             $sortingField = $http->variable( 'ContentClass_default_sorting_field' );
446             $class->setAttribute( 'sort_field', $sortingField );
447         }
448         if ( $http->hasVariable( 'ContentClass_default_sorting_order' ) )
449         {
450             $sortingOrder = $http->variable( 'ContentClass_default_sorting_order' );
451             $class->setAttribute( 'sort_order', $sortingOrder );
452         }
453     }
454
455     if ( $http->hasPostVariable( 'DataTypeString' ) )
456         $cur_datatype = $http->postVariable( 'DataTypeString' );
457 }
458
459 $class->setAttribute( 'version', eZContentClass::VERSION_STATUS_TEMPORARY );
460 $class->NameList->setHasDirtyData();
461
462 //include_once( 'lib/ezi18n/classes/ezchartransform.php' );
463 $trans = eZCharTransform::instance();
464
465 // Fixed identifiers to only contain a-z0-9_
466 foreach( $attributes as $attribute )
467 {
468     $attribute->setAttribute( 'version', eZContentClass::VERSION_STATUS_TEMPORARY );
469     $identifier = $attribute->attribute( 'identifier' );
470     if ( $identifier == '' )
471         $identifier = $attribute->attribute( 'name' );
472
473     $identifier = $trans->transformByGroup( $identifier, 'identifier' );
474     $attribute->setAttribute( 'identifier', $identifier );
475     if ( $dataType = $attribute->dataType() )
476     {
477         $dataType->initializeClassAttribute( $attribute );
478     }
479 }
480
481 // Fixed class identifier to only contain a-z0-9_
482 $identifier = $class->attribute( 'identifier' );
483 if ( $identifier == '' )
484     $identifier = $class->attribute( 'name' );
485 $identifier = $trans->transformByGroup( $identifier, 'identifier' );
486 $class->setAttribute( 'identifier', $identifier );
487
488 // Run custom actions if any
489 if ( $customAction )
490 {
491     foreach( $attributes as $attribute )
492     {
493         if ( $customActionAttributeID == $attribute->attribute( 'id' ) )
494         {
495             $attribute->customHTTPAction( $Module, $http, $customAction );
496         }
497     }
498 }
499 // Set new modification date
500 $date_time = time();
501 $class->setAttribute( 'modified', $date_time );
502 //include_once( 'kernel/classes/datatypes/ezuser/ezuser.php' );
503 $user = eZUser::currentUser();
504 $user_id = $user->attribute( 'contentobject_id' );
505 $class->setAttribute( 'modifier_id', $user_id );
506
507 // Remove attributes which are to be deleted
508 if ( $http->hasPostVariable( 'RemoveButton' ) )
509 {
510     $validation['processed'] = true;
511     if ( eZHTTPPersistence::splitSelected( 'ContentAttribute', $attributes,
512                                            $http, 'id',
513                                            $keepers, $rejects ) )
514     {
515         $attributes = $keepers;
516         foreach ( $rejects as $reject )
517         {
518             if ( !$reject->removeThis( true ) )
519             {
520                 $dataType = $reject->dataType();
521                 $removeInfo = $dataType->classAttributeRemovableInformation( $reject );
522                 if ( $removeInfo !== false )
523                 {
524                     $validation['attributes'] = array( array( 'id' => $reject->attribute( 'id' ),
525                                                               'identifier' => $reject->attribute( 'identifier' ),
526                                                               'reason' => $removeInfo ) );
527                 }
528             }
529         }
530     }
531 }
532
533 // Fetch HTTP input
534 $datatypeValidation = array();
535 if ( $contentClassHasInput )
536 {
537     foreach( $attributes as $attribute )
538     {
539         if ( $dataType = $attribute->dataType() )
540         {
541             $dataType->fetchClassAttributeHTTPInput( $http, 'ContentClass', $attribute );
542         }
543         else
544         {
545             $datatypeValidation['processed'] = 1;
546             $datatypeValidation['attributes'][] =
547                 array( 'reason' => array( 'text' => ezi18n( 'kernel/class', 'Could not load datatype: ' ).
548                                            $attribute->attribute( 'data_type_string' )."\n".
549                                            ezi18n( 'kernel/class', 'Editing this content class may cause data corruption in your system.' ).'<br>'.
550                                            ezi18n( 'kernel/class', 'Press "Cancel" to safely exit this operation.').'<br>'.
551                                            ezi18n( 'kernel/class', 'Please contact your eZ Publish administrator to solve this problem.').'<br>' ),
552                        'item' => $attribute->attribute( 'data_type_string' ),
553                        'identifier' => $attribute->attribute( 'data_type_string' ),
554                        'id' => $key );
555         }
556     }
557 }
558
559 if ( $validationRequired )
560 {
561     // check for duplicate attribute identifiers in the input
562     if ( count( $attributes ) > 1 )
563     {
564         for( $attrIndex = 0; $attrIndex < count( $attributes ) - 1; $attrIndex++ )
565         {
566             $classAttribute = $attributes[$attrIndex];
567             $identifier = $classAttribute->attribute( 'identifier' );
568             $placement = $classAttribute->attribute( 'placement' );
569             for ( $attrIndex2 = $attrIndex + 1; $attrIndex2 < count( $attributes ); $attrIndex2++ )
570             {
571                 $classAttribute2 = $attributes[$attrIndex2];
572                 $identifier2 = $classAttribute2->attribute( 'identifier' );
573                 $placement2 = $classAttribute2->attribute( 'placement' );
574                 if (  $placement ==  $placement2 )
575                 {
576                     $validation['attributes'][] = array( 'identifier' => $identifier2,
577                                                          'name' => $classAttribute2->attribute( 'name' ),
578                                                          'id' => $classAttribute2->attribute( 'id' ),
579                                                          'reason' => array ( 'text' => ezi18n( 'kernel/class', 'duplicate attribute placement' ) ) );
580                     $canStore = false;
581                     break;
582                 }
583
584                 if ( $identifier == $identifier2 )
585                 {
586                     $validation['attributes'][] = array( 'identifier' => $identifier,
587                                                          'name' => $classAttribute->attribute( 'name' ),
588                                                          'id' => $classAttribute->attribute( 'id' ),
589                                                          'reason' => array ( 'text' => ezi18n( 'kernel/class', 'duplicate attribute identifier' ) ) );
590                     $canStore = false;
591                     break;
592                 }
593             }
594         }
595     }
596 }
597
598 // Store version 0 and discard version 1
599 if ( $http->hasPostVariable( 'StoreButton' ) && $canStore )
600 {
601
602     $id = $class->attribute( 'id' );
603     $oldClassAttributes = $class->fetchAttributes( $id, true, eZContentClass::VERSION_STATUS_DEFINED );
604     $newClassAttributes = $class->fetchAttributes( );
605
606     // validate class name and identifier; check presence of class attributes
607     // FIXME: object pattern name is never validated
608
609     $basicClassPropertiesValid = true;
610     $className       = $class->attribute( 'name' );
611     $classIdentifier = $class->attribute( 'identifier' );
612     $classID         = $class->attribute( 'id' );
613
614     // validate class name
615     if( trim( $className ) == '' )
616     {
617         $validation['class_errors'][] = array( 'text' => ezi18n( 'kernel/class', 'The class should have nonempty \'Name\' attribute.' ) );
618         $basicClassPropertiesValid = false;
619     }
620
621     // check presence of attributes
622     if ( count( $newClassAttributes ) == 0 )
623     {
624         $validation['class_errors'][] = array( 'text' => ezi18n( 'kernel/class', 'The class should have at least one attribute.' ) );
625         $basicClassPropertiesValid = false;
626     }
627
628     // validate class identifier
629
630     $db = eZDB::instance();
631     $classCount = $db->arrayQuery( "SELECT COUNT(*) AS count FROM ezcontentclass WHERE  identifier='$classIdentifier' AND version=" . eZContentClass::VERSION_STATUS_DEFINED . " AND id <> $classID" );
632     if ( $classCount[0]['count'] > 0 )
633     {
634         $validation['class_errors'][] = array( 'text' => ezi18n( 'kernel/class', 'There is a class already having the same identifier.' ) );
635         $basicClassPropertiesValid = false;
636     }
637     unset( $classList );
638     unset( $db );
639
640     if ( !$basicClassPropertiesValid )
641     {
642         $canStore = false;
643         $validation['processed'] = false;
644     }
645     else
646     {
647         $firstStoreAttempt = eZSessionRead( $http->sessionVariable( 'CanStoreTicket' ) );
648         if ( !$firstStoreAttempt )
649         {
650             return $Module->redirectToView( 'view', array( $ClassID ), array( 'Language' => $EditLanguage ) );
651         }
652         eZSessionDestroy( $http->sessionVariable( 'CanStoreTicket' ) );
653
654         // Class cleanup, update existing class objects according to new changes
655         //include_once( 'kernel/classes/ezcontentobject.php' );
656
657         $db = eZDB::instance();
658         $db->begin();
659
660         $objects = null;
661         $objectCount = eZContentObject::fetchSameClassListCount( $ClassID );
662         if ( $objectCount > 0 )
663         {
664             // Delete object attributes which have been removed.
665             foreach ( $oldClassAttributes as $oldClassAttribute )
666             {
667                 $attributeExist = false;
668                 $oldClassAttributeID = $oldClassAttribute->attribute( 'id' );
669                 foreach ( $newClassAttributes as $newClassAttribute )
670                 {
671                     $newClassAttributeID = $newClassAttribute->attribute( 'id' );
672                     if ( $oldClassAttributeID == $newClassAttributeID )
673                         $attributeExist = true;
674                 }
675                 if ( !$attributeExist )
676                 {
677                     $objectAttributes = eZContentObjectAttribute::fetchSameClassAttributeIDList( $oldClassAttributeID );
678                     foreach ( $objectAttributes as $objectAttribute )
679                     {
680                         $objectAttributeID = $objectAttribute->attribute( 'id' );
681                         $objectAttribute->removeThis( $objectAttributeID );
682                     }
683                 }
684             }
685             $class->storeDefined( $attributes );
686
687             // Add object attributes which have been added.
688             foreach ( $newClassAttributes as $newClassAttribute )
689             {
690                 $attributeExist = false;
691                 $newClassAttributeID = $newClassAttribute->attribute( 'id' );
692                 foreach ( $oldClassAttributes as $oldClassAttribute )
693                 {
694                     $oldClassAttributeID = $oldClassAttribute->attribute( 'id' );
695                     if ( $oldClassAttributeID == $newClassAttributeID )
696                         $attributeExist = true;
697                 }
698                 if ( !$attributeExist )
699                 {
700                     if ( $objects == null )
701                     {
702                         $objects = eZContentObject::fetchSameClassList( $ClassID );
703                     }
704                     foreach ( $objects as $object )
705                     {
706                         $contentobjectID = $object->attribute( 'id' );
707                         $objectVersions = $object->versions();
708                         foreach ( $objectVersions as $objectVersion )
709                         {
710                             $translations = $objectVersion->translations( false );
711                             $version = $objectVersion->attribute( 'version' );
712                             foreach ( $translations as $translation )
713                             {
714                                 $objectAttribute = eZContentObjectAttribute::create( $newClassAttributeID, $contentobjectID, $version, $translation );
715                                 $objectAttribute->setAttribute( 'language_code', $translation );
716                                 $objectAttribute->initialize();
717                                 $objectAttribute->store();
718                                 $objectAttribute->postInitialize();
719                             }
720                         }
721                     }
722                 }
723             }
724         }
725         else
726         {
727             $class->storeDefined( $attributes );
728         }
729
730         $db->commit();
731
732         $http->removeSessionVariable( 'CanStoreTicket' );
733         return $Module->redirectToView( 'view', array( $ClassID ), array( 'Language' => $EditLanguage ) );
734     }
735 }
736
737 // Store changes
738 if ( $canStore )
739     $class->store( $attributes );
740
741 if ( $http->hasPostVariable( 'NewButton' ) )
742 {
743     $new_attribute = eZContentClassAttribute::create( $ClassID, $cur_datatype, array(), $EditLanguage );
744     $attrcnt = count( $attributes ) + 1;
745     $new_attribute->setName( ezi18n( 'kernel/class/edit', 'new attribute' ) . $attrcnt, $EditLanguage );
746     $dataType = $new_attribute->dataType();
747     $dataType->initializeClassAttribute( $new_attribute );
748     $new_attribute->store();
749     $attributes[] = $new_attribute;
750 }
751 else if ( $http->hasPostVariable( 'MoveUp' ) )
752 {
753     $attribute = eZContentClassAttribute::fetch( $http->postVariable( 'MoveUp' ), true, eZContentClass::VERSION_STATUS_TEMPORARY,
754                                                   array( 'contentclass_id', 'version', 'placement' ) );
755     $attribute->move( false );
756     $Module->redirectTo( $Module->functionURI( 'edit' ) . '/' . $ClassID . '/(language)/' . $EditLanguage );
757     return;
758 }
759 else if ( $http->hasPostVariable( 'MoveDown' ) )
760 {
761     $attribute = eZContentClassAttribute::fetch( $http->postVariable( 'MoveDown' ), true, eZContentClass::VERSION_STATUS_TEMPORARY,
762                                                   array( 'contentclass_id', 'version', 'placement' ) );
763     $attribute->move( true );
764     $Module->redirectTo( $Module->functionURI( 'edit' ) . '/' . $ClassID . '/(language)/' . $EditLanguage );
765     return;
766 }
767
768 $Module->setTitle( 'Edit class ' . $class->attribute( 'name' ) );
769 if ( !$http->hasSessionVariable( 'CanStoreTicket' ) )
770 {
771     $http->setSessionVariable( 'CanStoreTicket', md5( (string)rand() ) );
772     eZSessionWrite( $http->sessionVariable( 'CanStoreTicket' ), 1 );
773 }
774
775 // Fetch updated attributes
776 $attributes = $class->fetchAttributes();
777 $validation = array_merge( $validation, $datatypeValidation );
778
779 // Template handling
780 require_once( 'kernel/common/template.php' );
781 $tpl = templateInit();
782 $res = eZTemplateDesignResource::instance();
783 $res->setKeys( array( array( 'class', $class->attribute( 'id' ) ) ) ); // Class ID
784 $tpl->setVariable( 'http', $http );
785 $tpl->setVariable( 'validation', $validation );
786 $tpl->setVariable( 'can_store', $canStore );
787 $tpl->setVariable( 'require_fixup', $requireFixup );
788 $tpl->setVariable( 'module', $Module );
789 $tpl->setVariable( 'class', $class );
790 $tpl->setVariable( 'attributes', $attributes );
791 $tpl->setVariable( 'datatypes', $datatypes );
792 $tpl->setVariable( 'datatype', $cur_datatype );
793 $tpl->setVariable( 'language_code', $EditLanguage );
794
795 $Result = array();
796 $Result['content'] = $tpl->fetch( 'design:class/edit.tpl' );
797 $Result['path'] = array( array( 'url' => '/class/edit/',
798                                 'text' => ezi18n( 'kernel/class', 'Class edit' ) ) );
799
800 ?>