public function sync($force = false, $removeExtras = false)
 {
     $modified = eZContentClass::fetch($this->id, true, eZContentClass::VERSION_STATUS_MODIFIED);
     if (is_object($modified)) {
         throw new Exception("Classe bloccata in modifica");
     }
     $this->compare();
     if ($this->getData()->hasError && !$force) {
         throw new Exception("La classe contiene campi che ne impediscono la sincronizzazione automatica");
     }
     $temporary = eZContentClass::fetch($this->id, true, eZContentClass::VERSION_STATUS_TEMPORARY);
     if (!is_object($temporary) or $temporary->attribute('id') == null) {
         $temporary = eZContentClass::fetch($this->id, true, eZContentClass::VERSION_STATUS_DEFINED);
         if ($temporary === null) {
             throw new Exception("La classe non esiste");
         }
         /** @var eZContentClassClassGroup[] $classGroups */
         $classGroups = eZContentClassClassGroup::fetchGroupList($this->id, eZContentClass::VERSION_STATUS_DEFINED);
         foreach ($classGroups as $classGroup) {
             $groupID = $classGroup->attribute('group_id');
             $groupName = $classGroup->attribute('group_name');
             $ingroup = eZContentClassClassGroup::create($this->id, eZContentClass::VERSION_STATUS_TEMPORARY, $groupID, $groupName);
             $ingroup->store();
         }
         if (count($classGroups) > 0) {
             $mainGroupID = $classGroups[0]->attribute('group_id');
             $mainGroupName = $classGroups[0]->attribute('group_name');
         }
     } else {
         $user = eZUser::currentUser();
         $contentIni = eZINI::instance('content.ini');
         $timeOut = $contentIni->variable('ClassSettings', 'DraftTimeout');
         /** @var eZContentClassClassGroup[] $groupList */
         $groupList = $temporary->fetchGroupList();
         if (count($groupList) > 0) {
             $mainGroupID = $groupList[0]->attribute('group_id');
             $mainGroupName = $groupList[0]->attribute('group_name');
         }
         if ($temporary->attribute('modifier_id') != $user->attribute('contentobject_id') && $temporary->attribute('modified') + $timeOut > time()) {
             throw new Exception("Modifica alla classe non permessa");
         }
     }
     /** @var eZContentClassAttribute[] $localeAttributes */
     $localeAttributes = array();
     foreach ($this->currentClass->fetchAttributes() as $attribute) {
         /** @var eZContentClassAttribute $attribute */
         $attribute->setAttribute('version', eZContentClass::VERSION_STATUS_TEMPORARY);
         $localeAttributes[$attribute->attribute('identifier')] = $attribute;
     }
     $this->currentClass->setAttribute('version', eZContentClass::VERSION_STATUS_TEMPORARY);
     $remote = $this->getRemote();
     if ($remote === null) {
         throw new Exception("Classe remota non trovata");
     }
     if ($force && $this->getData()->hasError) {
         foreach ($this->getData()->errors as $identifier => $value) {
             if (!$localeAttributes[$identifier] instanceof eZContentClassAttribute) {
                 throw new Exception('Errore forzando la sincronizzazione');
             }
             foreach ($remote->DataMap[0] as $originalAttribute) {
                 if ($originalAttribute->Identifier == $identifier) {
                     ezpEvent::getInstance()->notify('classtools/switch_class_attribute', array($localeAttributes[$identifier], $originalAttribute));
                     if ($value == 'data_type_string') {
                         $localeAttributes[$identifier]->setAttribute('data_type_string', $originalAttribute->DataTypeString);
                         $localeAttributes[$identifier]->store();
                         $this->changeContentObjectAttributeDataTypeString($localeAttributes[$identifier], $originalAttribute->DataTypeString);
                         unset($this->notifications[self::ERROR][$originalAttribute->Identifier]);
                     } else {
                         $this->data->missingAttributes[] = $originalAttribute;
                         $this->currentClass->removeAttributes(array($localeAttributes[$identifier]));
                         unset($localeAttributes[$identifier]);
                     }
                     break;
                 }
             }
         }
     }
     $attributes = array();
     foreach ($this->properties as $identifier => $remoteProperty) {
         if ($remote->{$remoteProperty} != $this->currentClass->attribute($identifier)) {
             $this->currentClass->setAttribute($identifier, $remote->{$remoteProperty});
             if ($identifier == 'serialized_name_list') {
                 $nameList = new eZContentClassNameList();
                 $nameList->initFromSerializedList($remote->{$remoteProperty});
                 $this->currentClass->NameList = $nameList;
             } elseif ($identifier == 'serialized_description_list') {
                 $descriptionList = new eZSerializedObjectNameList();
                 $descriptionList->initFromSerializedList($remote->{$remoteProperty});
                 $this->currentClass->DescriptionList = $descriptionList;
             }
         }
     }
     foreach ($this->getData()->missingAttributes as $originalAttribute) {
         $add = $this->addAttribute($originalAttribute);
         if ($add) {
             $attributes[] = $add;
         }
     }
     foreach ($remote->DataMap[0] as $originalAttribute) {
         if (isset($localeAttributes[$originalAttribute->Identifier])) {
             $modified = $this->syncAttribute($originalAttribute, $localeAttributes[$originalAttribute->Identifier]);
             if ($modified) {
                 $attributes[] = $modified;
             }
         }
     }
     if (!$removeExtras) {
         foreach ($this->extraContentObjectAttributes as $extra) {
             $extra->setAttribute('placement', count($attributes) + 1);
             $attributes[] = $extra;
         }
     }
     $this->currentClass->store($attributes);
     $db = eZDB::instance();
     $db->begin();
     $unorderedParameters = array('Language' => $this->EditLanguage);
     if (eZContentObject::fetchSameClassListCount($this->id) > 0) {
         eZExtension::getHandlerClass(new ezpExtensionOptions(array('iniFile' => 'site.ini', 'iniSection' => 'ContentSettings', 'iniVariable' => 'ContentClassEditHandler')))->store($this->currentClass, $attributes, $unorderedParameters);
     } else {
         $unorderedParameters['ScheduledScriptID'] = 0;
         $this->currentClass->storeVersioned($attributes, eZContentClass::VERSION_STATUS_DEFINED);
     }
     $db->commit();
     $this->syncGroups();
 }