/** * Internal method for creating global or custom URL alias (these are handled in the same way). * * @throws \eZ\Publish\Core\Base\Exceptions\ForbiddenException if the path already exists for the given language * * @param string $action * @param string $path * @param bool $forward * @param string|null $languageCode * @param bool $alwaysAvailable * * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias */ protected function createUrlAlias($action, $path, $forward, $languageCode, $alwaysAvailable) { $pathElements = explode('/', $path); $topElement = array_pop($pathElements); $languageId = $this->languageHandler->loadByLanguageCode($languageCode)->id; $parentId = 0; // Handle all path elements except topmost one $isPathNew = false; foreach ($pathElements as $level => $pathElement) { $pathElement = $this->slugConverter->convert($pathElement, 'noname' . ($level + 1)); $pathElementMD5 = $this->getHash($pathElement); if (!$isPathNew) { $row = $this->gateway->loadRow($parentId, $pathElementMD5); if (empty($row)) { $isPathNew = true; } else { $parentId = $row['link']; } } if ($isPathNew) { $parentId = $this->insertNopEntry($parentId, $pathElement, $pathElementMD5); } } // Handle topmost path element $topElement = $this->slugConverter->convert($topElement, 'noname' . (count($pathElements) + 1)); // If last (next to topmost) entry parent is special root entry we handle topmost entry as first level entry // That is why we need to reset $parentId to 0 if ($parentId != 0 && $this->gateway->isRootEntry($parentId)) { $parentId = 0; } $topElementMD5 = $this->getHash($topElement); // Set common values for two cases below $data = array('action' => $action, 'is_alias' => 1, 'alias_redirects' => $forward ? 1 : 0, 'parent' => $parentId, 'text' => $topElement, 'text_md5' => $topElementMD5, 'is_original' => 1); // Try to load topmost element if (!$isPathNew) { $row = $this->gateway->loadRow($parentId, $topElementMD5); } // If nothing was returned perform insert if ($isPathNew || empty($row)) { $data['lang_mask'] = $languageId | (int) $alwaysAvailable; $id = $this->gateway->insertRow($data); } elseif ($row['action'] == 'nop:' || $row['is_original'] == 0) { // Row exists, check if it is reusable. There are 2 cases when this is possible: // 1. NOP entry // 2. history entry $data['lang_mask'] = $languageId | (int) $alwaysAvailable; // If history is reused move link to id $data['link'] = $id = $row['id']; $this->gateway->updateRow($parentId, $topElementMD5, $data); } else { throw new ForbiddenException("Path '%path%' already exists for the given language", ['%path%' => $path]); } $data['raw_path_data'] = $this->gateway->loadPathData($id); return $this->mapper->extractUrlAliasFromData($data); }
/** * Internal method for creating global or custom URL alias (these are handled in the same way) * * @throws \eZ\Publish\Core\Base\Exceptions\ForbiddenException if the path already exists for the given language * * @param string $action * @param string $path * @param boolean $forward * @param string|null $languageCode * @param boolean $alwaysAvailable * * @return \eZ\Publish\SPI\Persistence\Content\UrlAlias */ protected function createUrlAlias($action, $path, $forward, $languageCode, $alwaysAvailable) { $pathElements = explode("/", $path); $topElement = array_pop($pathElements); $languageId = $this->languageHandler->loadByLanguageCode($languageCode)->id; $parentId = 0; // Handle all path elements except topmost one $isPathNew = false; foreach ($pathElements as $level => $pathElement) { $pathElement = $this->slugConverter->convert($pathElement, "noname" . ($level + 1)); $pathElementMD5 = $this->getHash($pathElement); if (!$isPathNew) { $row = $this->gateway->loadRow($parentId, $pathElementMD5); if (empty($row)) { $isPathNew = true; } else { $parentId = $row["link"]; } } if ($isPathNew) { $parentId = $this->insertNopEntry($parentId, $pathElement, $pathElementMD5); } } // Handle topmost path element $topElement = $this->slugConverter->convert($topElement, "noname" . (count($pathElements) + 1)); // If last (next to topmost) entry parent is special root entry we handle topmost entry as first level entry // That is why we need to reset $parentId to 0 and empty $createdPath if ($parentId != 0 && $this->gateway->isRootEntry($parentId)) { $parentId = 0; } $topElementMD5 = $this->getHash($topElement); // Set common values for two cases below $data = array("action" => $action, "is_alias" => 1, "alias_redirects" => $forward ? 1 : 0, "parent" => $parentId, "text" => $topElement, "text_md5" => $topElementMD5, "is_original" => 1); // Try to load topmost element if (!$isPathNew) { $row = $this->gateway->loadRow($parentId, $topElementMD5); } // If nothing was returned perform insert if ($isPathNew || empty($row)) { $data["lang_mask"] = $languageId | (int) $alwaysAvailable; $id = $this->gateway->insertRow($data); } else { if ($row["action"] == "nop:" || $row["is_original"] == 0) { $data["lang_mask"] = $languageId | (int) $alwaysAvailable; // If history is reused move link to id $data["link"] = $id = $row["id"]; $this->gateway->updateRow($parentId, $topElementMD5, $data); } else { throw new ForbiddenException("Path '{$path}' already exists for the given language"); } } $data["raw_path_data"] = $this->gateway->loadPathData($id); return $this->mapper->extractUrlAliasFromData($data); }
/** * Sets the name for Content $contentId in version $version to $name in $language. * * @param int $contentId * @param int $version * @param string $name * @param string $language */ public function setName($contentId, $version, $name, $language) { $language = $this->languageHandler->loadByLanguageCode($language); // Is it an insert or an update ? $qSelect = $this->dbHandler->createSelectQuery(); $qSelect->select($qSelect->alias($qSelect->expr->count('*'), 'count'))->from($this->dbHandler->quoteTable('ezcontentobject_name'))->where($qSelect->expr->lAnd($qSelect->expr->eq($this->dbHandler->quoteColumn('contentobject_id'), $qSelect->bindValue($contentId)), $qSelect->expr->eq($this->dbHandler->quoteColumn('content_version'), $qSelect->bindValue($version)), $qSelect->expr->eq($this->dbHandler->quoteColumn('content_translation'), $qSelect->bindValue($language->languageCode)))); $stmt = $qSelect->prepare(); $stmt->execute(); $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); $insert = $res[0]['count'] == 0; if ($insert) { $q = $this->dbHandler->createInsertQuery(); $q->insertInto($this->dbHandler->quoteTable('ezcontentobject_name')); } else { $q = $this->dbHandler->createUpdateQuery(); $q->update($this->dbHandler->quoteTable('ezcontentobject_name'))->where($q->expr->lAnd($q->expr->eq($this->dbHandler->quoteColumn('contentobject_id'), $q->bindValue($contentId)), $q->expr->eq($this->dbHandler->quoteColumn('content_version'), $q->bindValue($version)), $q->expr->eq($this->dbHandler->quoteColumn('content_translation'), $q->bindValue($language->languageCode)))); } $q->set($this->dbHandler->quoteColumn('contentobject_id'), $q->bindValue($contentId, null, \PDO::PARAM_INT))->set($this->dbHandler->quoteColumn('content_version'), $q->bindValue($version, null, \PDO::PARAM_INT))->set($this->dbHandler->quoteColumn('language_id'), $q->bindValue($language->id, null, \PDO::PARAM_INT))->set($this->dbHandler->quoteColumn('content_translation'), $q->bindValue($language->languageCode))->set($this->dbHandler->quoteColumn('real_translation'), $q->bindValue($language->languageCode))->set($this->dbHandler->quoteColumn('name'), $q->bindValue($name)); $q->prepare()->execute(); }
/** * Loads the actual content based on the provided IDs * * @param array $contentIds * @param mixed $translations * * @return mixed[] */ protected function loadContent(array $contentIds, $translations) { $loadQuery = $this->queryBuilder->createFindQuery($translations); $loadQuery->where($loadQuery->expr->eq('ezcontentobject_version.status', VersionInfo::STATUS_PUBLISHED), $loadQuery->expr->in($this->handler->quoteColumn('id', 'ezcontentobject'), $contentIds)); $statement = $loadQuery->prepare(); $statement->execute(); $rows = $statement->fetchAll(\PDO::FETCH_ASSOC); // Sort array, as defined in the $contentIds array $contentIdOrder = array_flip($contentIds); usort($rows, function ($current, $next) use($contentIdOrder) { return $contentIdOrder[$current['ezcontentobject_id']] - $contentIdOrder[$next['ezcontentobject_id']]; }); foreach ($rows as &$row) { $row['ezcontentobject_always_available'] = $this->languageMaskGenerator->isAlwaysAvailable($row['ezcontentobject_language_mask']); $row['ezcontentobject_main_language_code'] = $this->languageHandler->load($row['ezcontentobject_initial_language_id'])->languageCode; $row['ezcontentobject_version_languages'] = $this->languageMaskGenerator->extractLanguageIdsFromMask($row['ezcontentobject_version_language_mask']); $row['ezcontentobject_version_initial_language_code'] = $this->languageHandler->load($row['ezcontentobject_version_initial_language_id'])->languageCode; } return $rows; }