/** * Updates path identification string for given $locationId. * * @param mixed $locationId * @param mixed $parentLocationId * @param string $text * * @return void */ public function updatePathIdentificationString($locationId, $parentLocationId, $text) { try { return $this->innerGateway->updatePathIdentificationString($locationId, $parentLocationId, $text); } catch (DBALException $e) { throw new RuntimeException('Database error', 0, $e); } catch (PDOException $e) { throw new RuntimeException('Database error', 0, $e); } }
/** * Updates path identification string for locations of given $contentId if main language * is set in update struct. * * This is specific to the Legacy storage engine, as path identification string is deprecated. * * @param int $contentId * @param \eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct $content */ protected function updatePathIdentificationString($contentId, MetadataUpdateStruct $content) { if (isset($content->mainLanguageId)) { $contentLocationsRows = $this->locationGateway->loadLocationDataByContent($contentId); foreach ($contentLocationsRows as $row) { $locationName = ''; $urlAliasRows = $this->urlAliasGateway->loadLocationEntries($row['node_id'], false, $content->mainLanguageId); if (!empty($urlAliasRows)) { $locationName = $urlAliasRows[0]['text']; } $this->locationGateway->updatePathIdentificationString($row['node_id'], $row['parent_node_id'], $this->slugConverter->convert($locationName, 'node_' . $row['node_id'], 'urlalias_compat')); } } }
/** * Internal publish method, accepting language ID instead of language code and optionally * new alias ID (used when swapping Locations). * * @see \eZ\Publish\Core\Persistence\Legacy\Content\UrlAlias\Handler::locationSwapped() * * @param int $locationId * @param int $parentLocationId * @param string $name * @param int $languageId * @param bool $alwaysAvailable * @param bool $updatePathIdentificationString legacy storage specific for updating ezcontentobject_tree.path_identification_string * @param int $newId */ private function internalPublishUrlAliasForLocation($locationId, $parentLocationId, $name, $languageId, $alwaysAvailable = false, $updatePathIdentificationString = false, $newId = null) { $parentId = $this->getRealAliasId($parentLocationId); $name = $this->slugConverter->convert($name, 'location_' . $locationId); $uniqueCounter = $this->slugConverter->getUniqueCounterValue($name, $parentId == 0); $languageMask = $languageId | (int) $alwaysAvailable; $action = 'eznode:' . $locationId; $cleanup = false; // Exiting the loop with break; while (true) { $newText = ''; if ($locationId != self::CONTENT_REPOSITORY_ROOT_LOCATION_ID) { $newText = $name . ($uniqueCounter > 1 ? $uniqueCounter : ''); } $newTextMD5 = $this->getHash($newText); // Try to load existing entry $row = $this->gateway->loadRow($parentId, $newTextMD5); // If nothing was returned insert new entry if (empty($row)) { // Check for existing active location entry on this level and reuse it's id $existingLocationEntry = $this->gateway->loadAutogeneratedEntry($action, $parentId); if (!empty($existingLocationEntry)) { $cleanup = true; $newId = $existingLocationEntry['id']; } $newId = $this->gateway->insertRow(array('id' => $newId, 'link' => $newId, 'parent' => $parentId, 'action' => $action, 'lang_mask' => $languageMask, 'text' => $newText, 'text_md5' => $newTextMD5)); break; } // Row exists, check if it is reusable. There are 3 cases when this is possible: // 1. NOP entry // 2. existing location or custom alias entry // 3. history entry if ($row['action'] == 'nop:' || $row['action'] == $action || $row['is_original'] == 0) { // Check for existing location entry on this level, if it exists and it's id differs from reusable // entry id then reusable entry should be updated with the existing location entry id. // Note: existing location entry may be downgraded and relinked later, depending on its language. $existingLocationEntry = $this->gateway->loadAutogeneratedEntry($action, $parentId); if (!empty($existingLocationEntry)) { // Always cleanup when active autogenerated entry exists on the same level $cleanup = true; $newId = $existingLocationEntry['id']; if ($existingLocationEntry['id'] == $row['id']) { // If we are reusing existing location entry merge existing language mask $languageMask |= $row['lang_mask'] & ~1; } } elseif ($newId === null) { // Use reused row ID only if publishing normally, else use given $newId $newId = $row['id']; } $this->gateway->updateRow($parentId, $newTextMD5, array('action' => $action, 'action_type' => 'eznode', 'lang_mask' => $languageMask, 'text' => $newText, 'id' => $newId, 'link' => $newId, 'alias_redirects' => 1, 'is_original' => 1, 'is_alias' => 0)); break; } // If existing row is not reusable, increment $uniqueCounter and try again $uniqueCounter += 1; } /* @var $newText */ if ($updatePathIdentificationString) { $this->locationGateway->updatePathIdentificationString($locationId, $parentLocationId, $this->slugConverter->convert($newText, 'node_' . $locationId, 'urlalias_compat')); } /* @var $newId */ /* @var $newTextMD5 */ // Note: cleanup does not touch custom and global entries if ($cleanup) { $this->gateway->cleanupAfterPublish($action, $languageId, $newId, $parentId, $newTextMD5); } }
/** * This method creates or updates an urlalias from a new or changed content name in a language * (if published). It also can be used to create an alias for a new location of content. * On update the old alias is linked to the new one (i.e. a history alias is generated). * * $alwaysAvailable controls whether the url alias is accessible in all * languages. * * @param mixed $locationId * @param mixed $parentLocationId * @param string $name the new name computed by the name schema or url alias schema * @param string $languageCode * @param boolean $alwaysAvailable * @param boolean $updatePathIdentificationString legacy storage specific for updating ezcontentobject_tree.path_identification_string * * @return void */ public function publishUrlAliasForLocation($locationId, $parentLocationId, $name, $languageCode, $alwaysAvailable = false, $updatePathIdentificationString = false) { $parentId = $this->getRealAliasId($parentLocationId); $uniqueCounter = $this->slugConverter->getUniqueCounterValue($name, $parentId == 0); $name = $this->slugConverter->convert($name, "location_" . $locationId); $languageId = $this->languageHandler->loadByLanguageCode($languageCode)->id; $languageMask = $languageId | (int) $alwaysAvailable; $action = "eznode:" . $locationId; $cleanup = false; // Exiting the loop with break; while (true) { $newText = $name . ($uniqueCounter > 1 ? $uniqueCounter : ""); $newTextMD5 = $this->getHash($newText); // Try to load existing entry $row = $this->gateway->loadRow($parentId, $newTextMD5); // If nothing was returned insert new entry if (empty($row)) { // Check for existing active location entry on this level and reuse it's id $existingLocationEntry = $this->gateway->loadAutogeneratedEntry($action, $parentId); if (!empty($existingLocationEntry)) { $cleanup = true; $newId = $existingLocationEntry["id"]; } else { $newId = null; } $newId = $this->gateway->insertRow(array("id" => $newId, "link" => $newId, "parent" => $parentId, "action" => $action, "lang_mask" => $languageMask, "text" => $newText, "text_md5" => $newTextMD5)); break; } // Row exists, check if it is reusable. There are 3 cases when this is possible: // 1. NOP entry // 2. existing location or custom alias entry // 3. history entry if ($row["action"] == "nop:" || $row["action"] == $action || $row["is_original"] == 0) { // Check for existing location entry on this level, if it exists and it's id differs from reusable // entry id then reusable entry should be updated with the existing location entry id. // Note: existing location entry may be downgraded and relinked later, depending on its language. $existingLocationEntry = $this->gateway->loadAutogeneratedEntry($action, $parentId); $newId = $row["id"]; if (!empty($existingLocationEntry)) { if ($existingLocationEntry["id"] != $row["id"]) { $cleanup = true; $newId = $existingLocationEntry["id"]; } else { // If we are reusing existing location entry merge existing language mask $languageMask |= $row["lang_mask"] & ~1; } } $this->gateway->updateRow($parentId, $newTextMD5, array("action" => $action, "action_type" => "eznode", "lang_mask" => $languageMask, "text" => $newText, "id" => $newId, "link" => $newId, "alias_redirects" => 1, "is_original" => 1, "is_alias" => 0)); break; } // If existing row is not reusable, increment $uniqueCounter and try again $uniqueCounter += 1; } if ($updatePathIdentificationString) { $this->locationGateway->updatePathIdentificationString($locationId, $parentLocationId, $this->slugConverter->convert($newText, "node_" . $locationId, "urlalias_compat")); } /** @var $newId */ /** @var $newTextMD5 */ // Note: cleanup does not touch custom and global entries if ($cleanup) { $this->gateway->cleanupAfterPublish($action, $languageId, $newId, $parentId, $newTextMD5); } }