function runOperation(&$node)
{
$target_parent_node_id = $this->target_id;
if (empty($target_parent_node_id)) {
if ($this->move_to_depth >= $node->attribute('depth')) {
return false;
}
// Find the correct target node for the specified depth
$path_array = $node->attribute('path_array');
$target_parent_node_id = $path_array[$this->move_to_depth - 1];
}
$assigned_nodes = $node->attribute('object')->attribute('assigned_nodes');
// Find the target node
foreach ($assigned_nodes as $target_node) {
if ($target_node->attribute('parent_node_id') == $target_parent_node_id) {
$target_node_id = $target_node->attribute('node_id');
// Make sure target node is not us
if ($node->attribute('node_id') == $target_node_id) {
return false;
}
$urlalias_list = eZURLAliasML::fetchByAction('eznode', $node->attribute('node_id'));
$target_node_urlalias_list = eZURLAliasML::fetchByAction('eznode', $target_node_id);
// Sanity check, this should never happen
if (!isset($target_node_urlalias_list[0])) {
eZDebug::writeError('Found no url alias records for node with id ' . $target_node_id, 'batchtool/nodemerge');
return false;
}
$target_node_urlalias_id = $target_node_urlalias_list[0]->attribute('id');
$target_parent_urlalias_id = $target_node_urlalias_list[0]->attribute('parent');
$db = eZDB::instance();
$db->begin();
// Make sure any children nodes are moved to the new node
foreach ($node->attribute('children') as $child) {
moveNode($child, $target_node_id);
}
// Make sure any bookmarks are moved to the new node
$bookmark_list = eZPersistentObject::fetchObjectList(eZContentBrowseBookmark::definition(), null, array('node_id' => $node->attribute('node_id')));
foreach ($bookmark_list as $bookmark) {
$bookmark->setAttribute('node_id', $target_node_id);
$bookmark->store();
}
// Remove the node in question
$node->removeNodeFromTree(true);
// Set up url alias redirects to the new node
foreach ($urlalias_list as $url_alias) {
$url_alias->setAttribute('action', 'eznode:' . $target_node_id);
$url_alias->setAttribute('action_type', 'eznode');
$url_alias->setAttribute('link', $target_node_urlalias_id);
$url_alias->setAttribute('is_original', 0);
$url_alias->store();
}
$db->commit();
return true;
}
}
return false;
}
/**
* Returns URL alias for the specified <var>$locale</var>
*
* @param string $url
* @param string $locale
* @return void
*/
public function destinationUrl()
{
$nodeId = $this->origUrl;
$urlAlias = '';
if (!is_numeric($this->origUrl)) {
if (!$this->isUrlPointingToModule($this->origUrl)) {
$this->origUrl = self::addPathPrefixIfNeeded($this->origUrl);
}
$nodeId = eZURLAliasML::fetchNodeIDByPath($this->origUrl);
}
$siteLanguageList = $this->getSiteAccessIni()->variable('RegionalSettings', 'SiteLanguageList');
// set prioritized languages of destination SA, and fetch corresponding (prioritized) URL alias
eZContentLanguage::setPrioritizedLanguages($siteLanguageList);
$destinationElement = eZURLAliasML::fetchByAction('eznode', $nodeId, false, true);
eZContentLanguage::clearPrioritizedLanguages();
if (empty($destinationElement) || !isset($destinationElement[0]) && !$destinationElement[0] instanceof eZURLAliasML) {
// If the return of fetchByAction is empty, it can mean a couple
// of different things:
// Either we are looking at a module, and we should pass the
// original URL on
//
// Or we are looking at URL which does not exist in the
// destination siteaccess, for instance an untranslated object. In
// which case we will point to the root of the site, unless it is
// available as a fallback.
if ($nodeId) {
$urlAlias = $this->origUrl;
// if applicable, remove destination PathPrefix from url
if (!self::removePathPrefixIfNeeded($this->getSiteAccessIni(), $urlAlias)) {
// If destination siteaccess has a PathPrefix but url is not matched,
// also check current SA's prefix, and remove if it matches.
self::removePathPrefixIfNeeded(eZINI::instance('site.ini'), $urlAlias);
}
} else {
if ($this->isUrlPointingToModule($this->origUrl)) {
$urlAlias = $this->origUrl;
}
}
} else {
// Translated object found, forwarding to new URL.
$urlAlias = $destinationElement[0]->getPath($this->destinationLocale, $siteLanguageList);
// if applicable, remove destination PathPrefix from url
self::removePathPrefixIfNeeded($this->getSiteAccessIni(), $urlAlias);
$urlAlias .= $this->userParamString;
}
$this->baseDestinationUrl = rtrim($this->baseDestinationUrl, '/');
$ini = eZINI::instance();
if ($GLOBALS['eZCurrentAccess']['type'] === eZSiteAccess::TYPE_URI && !($ini->variable('SiteAccessSettings', 'RemoveSiteAccessIfDefaultAccess') === "enabled" && $ini->variable('SiteSettings', 'DefaultAccess') == $this->destinationSiteAccess)) {
$finalUrl = $this->baseDestinationUrl . '/' . $this->destinationSiteAccess . '/' . $urlAlias;
} else {
$finalUrl = $this->baseDestinationUrl . '/' . $urlAlias;
}
if ($this->queryString != '') {
$finalUrl .= '?' . $this->queryString;
}
return $finalUrl;
}
}
}
fclose($handle);
} else {
$cli->output("Warning: Cannot open apache log-file '{$logFilePath}' for reading, please check permissions and try again.");
}
} else {
$cli->output("Warning: apache log-file '{$logFilePath}' doesn't exist, please check your ini-settings and try again.");
}
// Process the content of $pathHashCounter to transform it into $nodeIDHashCounter
foreach ($pathHashCounter as $path => $count) {
$nodeID = eZURLAliasML::fetchNodeIDByPath($path);
// Support for PathPrefix
for ($pathPrefixIndex = 0; !$nodeID && $pathPrefixIndex < $pathPrefixesCount; ++$pathPrefixIndex) {
// Try prepending each of the existing pathPrefixes, to see if one of them matches an existing node
$nodeID = eZURLAliasML::fetchNodeIDByPath($pathPrefixes[$pathPrefixIndex] . $path);
}
if ($nodeID) {
if (!isset($nodeIDHashCounter[$nodeID])) {
$nodeIDHashCounter[$nodeID] = $count;
} else {
$nodeIDHashCounter[$nodeID] += $count;
}
}
}
foreach ($nodeIDHashCounter as $nodeID => $count) {
if (eZContentObjectTreeNode::fetch($nodeID) != null) {
$counter = eZViewCounter::fetch($nodeID);
if ($counter == null) {
$counter = eZViewCounter::create($nodeID);
$counter->setAttribute('count', $count);
/**
* Returns URL alias for the specified <var>$locale</var>
*
* @param string $url
* @param string $locale
* @return void
*/
public function destinationUrl()
{
$nodeId = $this->origUrl;
if (!is_numeric($this->origUrl)) {
$nodeId = eZURLAliasML::fetchNodeIDByPath($this->origUrl);
}
$destinationElement = eZURLAliasML::fetchByAction('eznode', $nodeId, $this->destinationLocale, false);
if (empty($destinationElement) || !isset($destinationElement[0]) && !$destinationElement[0] instanceof eZURLAliasML) {
// If the return of fetchByAction is empty, it can mean a couple
// of different things:
// Either we are looking at a module, and we should pass the
// original URL on
//
// Or we are looking at URL which does not exist in the
// destination siteaccess, for instance an untranslated object. In
// which case we will point to the root of the site, unless it is
// available as a fallback.
if ($this->isUrlPointingToModule($this->origUrl) || $this->isLocaleAvailableAsFallback()) {
// We have a module, we're keeping the orignal url.
$urlAlias = $this->origUrl;
} else {
// We probably have an untranslated object, which is not
// available with SiteLanguageList setting, we direct to root.
$urlAlias = '';
}
} else {
// Translated object found, forwarding to new URL.
$saIni = $this->getSiteAccessIni();
$siteLanguageList = $saIni->variable('RegionalSettings', 'SiteLanguageList');
$urlAlias = $destinationElement[0]->getPath($this->destinationLocale, $siteLanguageList);
$urlAlias .= $this->userParamString;
}
$this->baseDestinationUrl = rtrim($this->baseDestinationUrl, '/');
if ($GLOBALS['eZCurrentAccess']['type'] === eZSiteAccess::TYPE_URI) {
$finalUrl = $this->baseDestinationUrl . '/' . $this->destinationSiteAccess . '/' . $urlAlias;
} else {
$finalUrl = $this->baseDestinationUrl . '/' . $urlAlias;
}
return $finalUrl;
}
/**
* Attempts to fetch a possible node by translating the provided
* string/path to a node-number.
*
* The last section of the path is removed before the actual
* translation: hence, the PARENT node is returned.
*
* @param string $nodePathString Eg. 'Folder1/file1.txt'
* @return eZContentObject Eg. the node of 'Folder1'
*/
protected function fetchParentNodeByTranslation($nodePathString)
{
// Strip extensions. E.g. .jpg
$nodePathString = $this->fileBasename($nodePathString);
// Strip away last slash
if (strlen($nodePathString) > 0 and $nodePathString[strlen($nodePathString) - 1] === '/') {
$nodePathString = substr($nodePathString, 0, strlen($nodePathString) - 1);
}
$nodePathString = $this->splitLastPathElement($nodePathString, $element);
if (strlen($nodePathString) === 0) {
$nodePathString = '/';
}
$nodePathString = eZURLAliasML::convertPathToAlias($nodePathString);
// Attempt to translate the URL to something like "/content/view/full/84".
$translateResult = eZURLAliasML::translate($nodePathString);
// handle redirects
while ($nodePathString === 'error/301') {
$nodePathString = $translateResult;
$translateResult = eZURLAliasML::translate($nodePathString);
}
// Get the ID of the node (which is the last part of the translated path).
if (preg_match("#^content/view/full/([0-9]+)\$#", $nodePathString, $matches)) {
$nodeID = $matches[1];
} else {
$ini = eZINI::instance('webdav.ini');
if ($ini->hasVariable('GeneralSettings', 'StartNode')) {
$nodeID = $ini->variable('GeneralSettings', 'StartNode');
}
}
// Attempt to fetch the node.
$node = eZContentObjectTreeNode::fetch($nodeID);
// Return the node.
return $node;
}
/**
* \static
* Load content SSL zones definitions.
* Substitute URIs with corresponding path strings
* (e.g. "/news" would be subsituted with "/1/2/50").
* The result is cached in memory to save time on multiple invocations.
* It is also saved in a cache file that is usually updated by eZContentCacheManager along with content cache.
*/
static function getSSLZones()
{
if (!isset($GLOBALS['eZSSLZonesCachedPathStrings'])) {
$cacheFileName = eZSSLZone::cacheFileName();
$cacheDirName = eZSys::cacheDirectory();
// if file cache does not exist then create it
if (!is_readable($cacheFileName)) {
$ini = eZINI::instance();
$sslSubtrees = $ini->variable('SSLZoneSettings', 'SSLSubtrees');
if (!isset($sslSubtrees) || !$sslSubtrees) {
return array();
}
// if there are some content SSL zones defined in the ini settings
// then let's calculate path strings for them
$pathStringsArray = array();
foreach ($sslSubtrees as $uri) {
$elements = eZURLAliasML::fetchByPath($uri);
if (count($elements) == 0) {
eZDebug::writeError("Cannot fetch URI '{$uri}'", __METHOD__);
continue;
}
$action = $elements[0]->attribute('action');
if (!preg_match("#^eznode:(.+)#", $action, $matches)) {
eZDebug::writeError("Cannot decode action '{$action}' for URI '{$uri}'", __METHOD__);
continue;
}
$nodeID = (int) $matches[1];
$node = eZContentObjectTreeNode::fetch($nodeID);
if (!$node instanceof eZContentObjectTreeNode) {
eZDebug::writeError("cannot fetch node by URI '{$uri}'", __METHOD__);
continue;
}
$pathStringsArray[$uri] = $node->attribute('path_string');
unset($node);
}
// write calculated path strings to the file
if (!file_exists($cacheDirName)) {
eZDir::mkdir($cacheDirName, false, true);
}
$fh = fopen($cacheFileName, 'w');
if ($fh) {
fwrite($fh, "<?php\n\$pathStringsArray = " . var_export($pathStringsArray, true) . ";\n?>");
fclose($fh);
$perm = eZINI::instance()->variable('FileSettings', 'StorageFilePermissions');
chmod($cacheFileName, octdec($perm));
}
return $GLOBALS['eZSSLZonesCachedPathStrings'] = $pathStringsArray;
} else {
// let's read its contents and return them
include_once $cacheFileName;
// stores array to $pathStringsArray
return $GLOBALS['eZSSLZonesCachedPathStrings'] = $pathStringsArray;
}
}
// else if in-memory cache already exists then return its contents
$pathStringsArray = $GLOBALS['eZSSLZonesCachedPathStrings'];
return $pathStringsArray;
}
/**
* Test that store path does not reparent children of entries with same action
* if they are custom aliases
*/
public function testStorePathReparentAliasEntries()
{
// Create a real folder
$r = mt_rand();
$theRealFolder = new ezpObject("folder", 2);
$theRealFolder->name = __FUNCTION__ . $r;
$theRealFolder->publish();
// Create a real article in real folder
$myNode = new ezpObject("article", $theRealFolder->mainNode->node_id);
$myNode->title = "MyNode";
$myNode->publish();
// We fetch the url path element of our real folder entry,
// in order to create an alias to it
$realFolderUrl = eZURLAliasML::fetchByAction("eznode", $theRealFolder->mainNode->node_id);
$realFolderUrlId = $realFolderUrl[0]->attribute('id');
$myNodeUrl = eZURLAliasML::fetchByAction("eznode", $myNode->mainNode->node_id);
$myNodeUrlId = $myNodeUrl[0]->attribute('id');
// We create a custom url alias for the real folder under $realFolderAliasPath
// Note the first path element will be a virtual nop:
$realFolderAliasPath = "VirtualPath/AliasToTheRealFolder{$r}";
$action = "eznode:" . $theRealFolder->mainNode->node_id;
$realFolderAlias = eZURLAliasML::storePath($realFolderAliasPath, $action, false, $realFolderUrlId);
$realFolderAliasId = $realFolderAlias['element']->attribute('id');
/*
We create a custom url alias for MyNode, which is located underneath
the alias for real folder, in the url path
\
|-- TheRealFolder (node a)
| `-- MyNode (node b)
`-- VirtualPath (nop:)
`-- AliasToTheRealFolder (node a)
`-- AliasToMyNode (node b)
*/
// $myNodeAliasPath = "{$realFolderAliasPath}/AliasToMyNode{$r}";
$myNodeAliasPath = "AliasToMyNode{$r}";
$myNodeAction = "eznode:" . $myNode->mainNode->node_id;
$myNodeAlias = eZURLAliasML::storePath($myNodeAliasPath, $myNodeAction, false, $myNodeUrlId, false, $realFolderAliasId);
$myNodeAliasOriginalParent = $myNodeAlias['element']->attribute('parent');
// We republish the real folder, not strictly necessary to change the
// but it is more illustrative.
$theRealFolder->name = __FUNCTION__ . $r . "Renamed";
$theRealFolder->publish();
// Assert that our alias to MyNode was indeed placed underneath $realFolderAliasPath
self::assertEquals($realFolderAliasId, $myNodeAliasOriginalParent);
$db = eZDB::instance();
$q = self::buildSql(array($myNode->mainNode->node_id), false, array('is_alias' => 1, 'is_original' => 1));
$myNodeAliasPostChange = $db->arrayQuery($q);
$myNodeAliasPostChangeParent = $myNodeAliasPostChange[0]['parent'];
// Make sure the the alias to MyNode have not been moved in the url path
// after publishing the parent of the real node.
self::assertEquals($myNodeAliasOriginalParent, $myNodeAliasPostChangeParent, "Parent have custom url alias have been changed inadvertently.");
}
请发表评论