/** * Parses the XML for the attributes in $classAttributeIdentifiers, and fixes the relations for $object * @param eZContentObject $object * @param array $classAttributeIdentifiers * @return int The number of created relations */ function restoreXmlRelations(eZContentObject $object, array $classAttributeIdentifiers) { $currentVersion = $object->currentVersion(); $langMask = $currentVersion->attribute('language_mask'); $languageList = eZContentLanguage::decodeLanguageMask($langMask, true); $languageList = $languageList['language_list']; // nothing to do if the object isn't translated if (count($languageList) < 2) { return 0; } $attributeArray = $object->fetchAttributesByIdentifier($classAttributeIdentifiers, $currentVersion->attribute('version'), $languageList); $embedRelationsCount = $object->relatedContentObjectCount(false, 0, array('AllRelations' => eZContentObject::RELATION_EMBED)); $linkRelationsCount = $object->relatedContentObjectCount(false, 0, array('AllRelations' => eZContentObject::RELATION_LINK)); $embeddedObjectIdArray = $linkedObjectIdArray = array(); foreach ($attributeArray as $attribute) { $xmlText = eZXMLTextType::rawXMLText($attribute); $dom = new DOMDocument('1.0', 'utf-8'); if (!$dom->loadXML($xmlText)) { continue; } // linked objects $linkedObjectIdArray = array_merge($linkedObjectIdArray, getRelatedObjectList($dom->getElementsByTagName('link'))); // embedded objects $embeddedObjectIdArray = array_merge($embeddedObjectIdArray, getRelatedObjectList($dom->getElementsByTagName('embed')), getRelatedObjectList($dom->getElementsByTagName('embed-inline'))); } $doCommit = false; $restoredRelations = 0; if (!empty($embeddedObjectIdArray)) { $object->appendInputRelationList($embeddedObjectIdArray, eZContentObject::RELATION_EMBED); $restoredRelations += count($embeddedObjectIdArray) - $embedRelationsCount; $doCommit = true; } if (!empty($linkedObjectIdArray)) { $object->appendInputRelationList($linkedObjectIdArray, eZContentObject::RELATION_LINK); $restoredRelations += count($linkedObjectIdArray) - $linkRelationsCount; $doCommit = true; } if ($doCommit) { $object->commitInputRelations($currentVersion->attribute('version')); } return $restoredRelations; }
/** * Function for simplifying a content object or node * * @param mixed $obj * @param array $params * @return array */ public static function simplify($obj, $params = array()) { if (!$obj) { return array(); } else { if ($obj instanceof eZContentObject) { $node = $obj->attribute('main_node'); $contentObject = $obj; } else { if ($obj instanceof eZContentObjectTreeNode || $obj instanceof eZFindResultNode) { $node = $obj; $contentObject = $obj->attribute('object'); } else { if (isset($params['fetchNodeFunction']) && method_exists($obj, $params['fetchNodeFunction'])) { // You can supply fetchNodeFunction parameter to be able to support other node related classes $node = call_user_func(array($obj, $params['fetchNodeFunction'])); if (!$node instanceof eZContentObjectTreeNode) { return ''; } $contentObject = $node->attribute('object'); } else { if (is_array($obj)) { return $obj; // Array is returned as is } else { return ''; // Other passed objects are not supported } } } } } $ini = eZINI::instance('site.ini'); $params = array_merge(array('dataMap' => array(), 'fetchPath' => false, 'fetchSection' => false, 'fetchChildrenCount' => false, 'dataMapType' => array(), 'loadImages' => false, 'imagePreGenerateSizes' => array('small')), $params); if (!isset($params['imageSizes'])) { $imageIni = eZINI::instance('image.ini'); $params['imageSizes'] = $imageIni->variable('AliasSettings', 'AliasList'); } if ($params['imageSizes'] === null || !isset($params['imageSizes'][0])) { $params['imageSizes'] = array(); } if (!isset($params['imageDataTypes'])) { $params['imageDataTypes'] = $ini->variable('ImageDataTypeSettings', 'AvailableImageDataTypes'); } $ret = array(); $attrtibuteArray = array(); $ret['name'] = htmlentities($contentObject->attribute('name'), ENT_QUOTES, "UTF-8"); $ret['contentobject_id'] = $ret['id'] = (int) $contentObject->attribute('id'); $ret['contentobject_remote_id'] = $contentObject->attribute('remote_id'); $ret['contentobject_state'] = implode(", ", $contentObject->attribute('state_identifier_array')); $ret['main_node_id'] = (int) $contentObject->attribute('main_node_id'); $ret['version'] = (int) $contentObject->attribute('current_version'); $ret['modified'] = $contentObject->attribute('modified'); $ret['published'] = $contentObject->attribute('published'); $ret['section_id'] = (int) $contentObject->attribute('section_id'); $ret['current_language'] = $contentObject->attribute('current_language'); $ret['owner_id'] = (int) $contentObject->attribute('owner_id'); $ret['class_id'] = (int) $contentObject->attribute('contentclass_id'); $ret['class_name'] = $contentObject->attribute('class_name'); $ret['path_identification_string'] = $node->attribute('path_identification_string'); $ret['translations'] = eZContentLanguage::decodeLanguageMask($contentObject->attribute('language_mask'), true); $ret['can_edit'] = $contentObject->attribute('can_edit'); if (isset($params['formatDate'])) { $ret['modified_date'] = self::formatLocaleDate($contentObject->attribute('modified'), $params['formatDate']); $ret['published_date'] = self::formatLocaleDate($contentObject->attribute('published'), $params['formatDate']); } if (isset($params['fetchCreator'])) { $creator = $contentObject->attribute('current')->attribute('creator'); if ($creator instanceof eZContentObject) { $ret['creator'] = array('id' => $creator->attribute('id'), 'name' => $creator->attribute('name')); } else { $ret['creator'] = array('id' => $contentObject->attribute('current')->attribute('creator_id'), 'name' => null); // user has been deleted } } if (isset($params['fetchClassIcon'])) { $operator = new eZWordToImageOperator(); $tpl = eZTemplate::instance(); $operatorValue = $contentObject->attribute('class_identifier'); $operatorParameters = array(array(array(1, 'small'))); $namedParameters = array(); $operatorName = 'class_icon'; $operator->modify($tpl, $operatorName, $operatorParameters, '', '', $operatorValue, $namedParameters, array()); $ret['class_icon'] = $operatorValue; } if (isset($params['fetchThumbPreview'])) { $thumbUrl = ''; $thumbWidth = 0; $thumbHeight = 0; $thumbDataType = isset($params['thumbDataType']) ? $params['thumbDataType'] : 'ezimage'; $thumbImageSize = isset($params['thumbImageSize']) ? $params['thumbImageSize'] : 'small'; foreach ($contentObject->attribute('data_map') as $key => $atr) { if ($atr->attribute('data_type_string') == $thumbDataType && $atr->attribute('has_content')) { $imageContent = $atr->attribute('content'); if ($imageContent->hasAttribute($thumbImageSize)) { $imageAlias = $imageContent->attribute($thumbImageSize); } else { eZDebug::writeError("Image alias does not exist: '{$thumbImageSize}', missing from image.ini?", __METHOD__); } $thumbUrl = isset($imageAlias['full_path']) ? $imageAlias['full_path'] : ''; $thumbWidth = isset($imageAlias['width']) ? (int) $imageAlias['width'] : 0; $thumbHeight = isset($imageAlias['height']) ? (int) $imageAlias['height'] : 0; if ($thumbUrl !== '') { eZURI::transformURI($thumbUrl, true); } break; } } $ret['thumbnail_url'] = $thumbUrl; $ret['thumbnail_width'] = $thumbWidth; $ret['thumbnail_height'] = $thumbHeight; } if ($params['fetchSection']) { $section = eZSection::fetch($ret['section_id']); if ($section instanceof eZSection) { $ret['section'] = array('id' => $section->attribute('id'), 'name' => $section->attribute('name'), 'navigation_part_identifier' => $section->attribute('navigation_part_identifier'), 'locale' => $section->attribute('locale')); } else { $ret['section'] = null; } } if ($node) { // optimization for eZ Publish 4.1 (avoid fetching class) if ($node->hasAttribute('is_container')) { $ret['class_identifier'] = $node->attribute('class_identifier'); $ret['is_container'] = (int) $node->attribute('is_container'); } else { $class = $contentObject->attribute('content_class'); $ret['class_identifier'] = $class->attribute('identifier'); $ret['is_container'] = (int) $class->attribute('is_container'); } $ret['node_id'] = (int) $node->attribute('node_id'); $ret['parent_node_id'] = (int) $node->attribute('parent_node_id'); $ret['node_remote_id'] = $node->attribute('remote_id'); $ret['url_alias'] = $node->attribute('url_alias'); $ret['url'] = $node->url(); // force system url on empty urls (root node) if ($ret['url'] === '') { $ret['url'] = 'content/view/full/' . $node->attribute('node_id'); } eZURI::transformURI($ret['url']); $ret['depth'] = (int) $node->attribute('depth'); $ret['priority'] = (int) $node->attribute('priority'); $ret['hidden_status_string'] = $node->attribute('hidden_status_string'); if ($params['fetchPath']) { $ret['path'] = array(); foreach ($node->attribute('path') as $n) { $ret['path'][] = self::simplify($n); } } else { $ret['path'] = false; } if ($params['fetchChildrenCount']) { $ret['children_count'] = $ret['is_container'] ? (int) $node->attribute('children_count') : 0; } else { $ret['children_count'] = false; } } else { $class = $contentObject->attribute('content_class'); $ret['class_identifier'] = $class->attribute('identifier'); $ret['is_container'] = (int) $class->attribute('is_container'); } $ret['image_attributes'] = array(); if (is_array($params['dataMap']) && is_array($params['dataMapType'])) { $dataMap = $contentObject->attribute('data_map'); $datatypeBlacklist = array_fill_keys($ini->variable('ContentSettings', 'DatatypeBlackListForExternal'), true); foreach ($dataMap as $key => $atr) { $dataTypeString = $atr->attribute('data_type_string'); //if ( in_array( $dataTypeString, $params['imageDataTypes'], true) !== false ) if (!in_array('all', $params['dataMap'], true) && !in_array($key, $params['dataMap'], true) && !in_array($dataTypeString, $params['dataMapType'], true) && !($params['loadImages'] && in_array($dataTypeString, $params['imageDataTypes'], true))) { continue; } $attrtibuteArray[$key]['id'] = $atr->attribute('id'); $attrtibuteArray[$key]['type'] = $dataTypeString; $attrtibuteArray[$key]['identifier'] = $key; if (isset($datatypeBlacklist[$dataTypeString])) { $attrtibuteArray[$key]['content'] = null; } else { $attrtibuteArray[$key]['content'] = $atr->toString(); } // images if (in_array($dataTypeString, $params['imageDataTypes'], true) && $atr->hasContent()) { $content = $atr->attribute('content'); $imageArray = array(); if ($content != null) { foreach ($params['imageSizes'] as $size) { $imageArray[$size] = false; if (in_array($size, $params['imagePreGenerateSizes'], true)) { if ($content->hasAttribute($size)) { $imageArray[$size] = $content->attribute($size); } else { eZDebug::writeError("Image alias does not exist: '{$size}', missing from image.ini?", __METHOD__); } } } $ret['image_attributes'][] = $key; } if (!isset($imageArray['original'])) { $imageArray['original'] = $content->attribute('original'); } array_walk_recursive($imageArray, function (&$element, $key) { // json_encode/xmlEncode need UTF8 encoded strings // (exif) metadata might not be for instance // see https://jira.ez.no/browse/EZP-19929 if (!mb_check_encoding($element, 'UTF-8')) { $element = mb_convert_encoding((string) $element, 'UTF-8'); } }); $attrtibuteArray[$key]['content'] = $imageArray; } } } $ret['data_map'] = $attrtibuteArray; return $ret; }
/** * Method triggered on publish for xml text datatype * * This method makes sure that links from all translations of an xml text * are registered in the ezurl_object_link table, and thus retained, if * previous versions of an object are removed. * * It also checks for embedded objects in other languages xml, and makes * sure the matching object relations are stored for the publish version. * * @param eZContentObjectAttribute $contentObjectAttribute * @param eZContentObject $object * @param array $publishedNodes * @return boolean */ function onPublish($contentObjectAttribute, $object, $publishedNodes) { $currentVersion = $object->currentVersion(); $langMask = $currentVersion->attribute('language_mask'); // We find all translations present in the current version. We calculate // this from the language mask already present in the fetched version, // so no further round-trip to the DB is required. $languageList = eZContentLanguage::decodeLanguageMask($langMask, true); $languageList = $languageList['language_list']; // We want to have the class attribute identifier of the attribute // containing the current ezxmltext, as we then can use the more efficient // eZContentObject->fetchAttributesByIdentifier() to get the data $identifier = $contentObjectAttribute->attribute('contentclass_attribute_identifier'); $attributeArray = $object->fetchAttributesByIdentifier(array($identifier), $currentVersion->attribute('version'), $languageList); foreach ($attributeArray as $attribute) { $xmlText = eZXMLTextType::rawXMLText($attribute); $dom = new DOMDocument('1.0', 'utf-8'); if (!$dom->loadXML($xmlText)) { continue; } // urls $urlIdArray = array(); foreach ($dom->getElementsByTagName('link') as $link) { // We are looking for external 'http://'-style links, not the internal // object or node links. if ($link->hasAttribute('url_id')) { $urlIdArray[] = $link->getAttribute('url_id'); } } if (count($urlIdArray) > 0) { eZSimplifiedXMLInput::updateUrlObjectLinks($attribute, $urlIdArray); } // linked objects $linkedObjectIdArray = $this->getRelatedObjectList($dom->getElementsByTagName('link')); // embedded objects $embeddedObjectIdArray = array_merge($this->getRelatedObjectList($dom->getElementsByTagName('embed')), $this->getRelatedObjectList($dom->getElementsByTagName('embed-inline'))); if (!empty($embeddedObjectIdArray)) { $object->appendInputRelationList($embeddedObjectIdArray, eZContentObject::RELATION_EMBED); } if (!empty($linkedObjectIdArray)) { $object->appendInputRelationList($linkedObjectIdArray, eZContentObject::RELATION_LINK); } if (!empty($linkedObjectIdArray) || !empty($embeddedObjectIdArray)) { $object->commitInputRelations($currentVersion->attribute('version')); } } }
/** * Helper method to validate the parent structure of url entries. * * This method will look at the parent references and validate this to the * actual id values of the parent entries. * * @param array $nameTable * @param array $urlEntryData */ public static function verifyUrlEntryParentStructure($nameTable, $urlEntryData) { $parentStructure = array(); $translationStructure = array(); foreach ($nameTable as $level => $names) { foreach ($names as $name) { $entry = self::urlEntryForName($name, $urlEntryData); if (!$entry) { return false; } $isOriginal = (int) $entry['is_original'] === 0 ? false : true; if (!$isOriginal) { return false; } $id = (int) $entry['id']; $langMask = (int) $entry['lang_mask']; $d = eZContentLanguage::decodeLanguageMask($langMask); foreach ($d['language_list'] as $realLang) { if (!isset($parentStructure[$level])) { $parentStructure[$level] = array("languages" => array($realLang => $id), "always_available" => $d['always_available']); } else { $parentStructure[$level]["languages"][$realLang] = $id; } $parent = (int) $entry['parent']; if ($parent === 0) { continue; } $parentLevel = $level - 1; $langEntries = $parentStructure[$parentLevel]["languages"]; $parentLang = -1; $langMatch = false; foreach ($langEntries as $lang => $realParentId) { $langMatch = ($lang & $realLang) > 0; if (!$langMatch) { continue; } $parentLang = $realParentId; break; } if ($langMatch && $parent !== $parentLang || !$langMatch && !$parentStructure[$parentLevel]['always_available']) { return false; } } } } return true; }
/** * Returns the list of locales for which this tag is translated * * @return array */ public function getAvailableLanguages() { $languages = eZContentLanguage::decodeLanguageMask($this->attribute('language_mask'), true); return $languages['language_list']; }