From a8dae412b74ab688ce176439f61694776594ebd2 Mon Sep 17 00:00:00 2001 From: cdujeu Date: Fri, 14 Mar 2014 18:55:44 +0100 Subject: [PATCH] Add methods for recursive search of metadata and implement this by hooking into ShareCenter to make sure shared workspaces are synchronized to their parent and the other way. Added some performance optimizations on the way, to be extensively tested, could have some side-effects. Remove some debugging in AJXP_Cache --- core/src/core/classes/class.AJXP_Cache.php | 4 +- .../core/classes/class.AJXP_Controller.php | 9 +- core/src/core/classes/class.AJXP_Node.php | 44 +++++++ .../classes/class.AJXP_PluginsService.php | 16 ++- core/src/core/classes/class.ConfService.php | 9 +- .../action.share/class.ShareCenter.php | 120 ++++++++++++++++++ core/src/plugins/action.share/manifest.xml | 15 ++- .../index.lucene/class.AjxpLuceneIndexer.php | 8 +- 8 files changed, 208 insertions(+), 17 deletions(-) diff --git a/core/src/core/classes/class.AJXP_Cache.php b/core/src/core/classes/class.AJXP_Cache.php index 720f829dc8..cf59ce01fd 100644 --- a/core/src/core/classes/class.AJXP_Cache.php +++ b/core/src/core/classes/class.AJXP_Cache.php @@ -73,7 +73,6 @@ public static function simpleCopy($master, $target) public static function clearItem($pluginId, $filepath) { $inst = new AJXP_Cache($pluginId,$filepath, false); - AJXP_Logger::debug("SHOULD REMOVE ".$inst->getId()); if (file_exists($inst->getId())) { @unlink($inst->getId()); } @@ -105,13 +104,12 @@ public function AJXP_Cache($pluginId, $filepath, $dataCallback, $idComputerCallb public function getData() { if (!$this->hasCachedVersion()) { - AJXP_Logger::debug("caching data", $this->dataCallback); $result = call_user_func($this->dataCallback, $this->masterFile, $this->cacheId); if ($result !== false) { $this->touch(); } } else { - AJXP_Logger::debug("getting from cache"); + } return file_get_contents($this->cacheId); } diff --git a/core/src/core/classes/class.AJXP_Controller.php b/core/src/core/classes/class.AJXP_Controller.php index 3cd2ff4ccd..9c09ad6589 100644 --- a/core/src/core/classes/class.AJXP_Controller.php +++ b/core/src/core/classes/class.AJXP_Controller.php @@ -449,7 +449,8 @@ private static function appliesCondition($callback, $actionName, $httpVars, $fil * @param Array $httpVars * @param Array $fileVars * @param null $variableArgs - * @throw AJXP_Exception + * @param bool $defer + * @throws AJXP_Exception* @throw AJXP_Exception * @return void */ private static function applyCallback($xPath, $callback, &$actionName, &$httpVars, &$fileVars, &$variableArgs = null, $defer = false) @@ -480,14 +481,14 @@ private static function applyCallback($xPath, $callback, &$actionName, &$httpVar * @static * @param string $hookName * @param array $args - * @return + * @param bool $forceNonDefer + * @return void */ public static function applyHook($hookName, $args, $forceNonDefer = false) { $xPath = self::initXPath(); $callbacks = $xPath->query("hooks/serverCallback[@hookName='$hookName']"); if(!$callbacks->length) return ; - $callback = new DOMNode(); foreach ($callbacks as $callback) { if ($callback->getAttribute("applyCondition")!="") { $apply = false; @@ -506,7 +507,7 @@ public static function applyHook($hookName, $args, $forceNonDefer = false) * @static * @param $hookName * @param $args - * @return + * @return void */ public static function applyIncludeHook($hookName, &$args) { diff --git a/core/src/core/classes/class.AJXP_Node.php b/core/src/core/classes/class.AJXP_Node.php index faf9295747..a061f8cb66 100644 --- a/core/src/core/classes/class.AJXP_Node.php +++ b/core/src/core/classes/class.AJXP_Node.php @@ -209,6 +209,50 @@ public function retrieveMetadata($nameSpace, $private = false, $scope=AJXP_METAD } + /** + * @return AJXP_Node|null + */ + public function getParent(){ + + if(empty($this->urlParts["path"]) || $this->urlParts["path"] == "/"){ + return null; + } + $parent = new AJXP_Node(dirname($this->_url)); + $parent->setDriver($this->_accessDriver); + return $parent; + + } + + public function findMetadataInParent($nameSpace, $private = false, $scope=AJXP_METADATA_SCOPE_REPOSITORY, $indexable = false){ + + $metadata = false; + $parentNode = $this->getParent(); + if($parentNode != null){ + $metadata = $parentNode->retrieveMetadata($nameSpace, $private, $scope,$indexable); + if($metadata == false){ + $metadata = $parentNode->findMetadataInParent($nameSpace, $private, $scope, $indexable); + }else{ + $metadata["SOURCE_NODE"] = $parentNode; + } + } + return $metadata; + + } + + public function collectMetadataInParents($nameSpace, $private = false, $scope=AJXP_METADATA_SCOPE_REPOSITORY, $indexable = false, &$collect=array()){ + + $parentNode = $this->getParent(); + if($parentNode != null){ + $metadata = $parentNode->retrieveMetadata($nameSpace, $private, $scope,$indexable); + if($metadata != false){ + $metadata["SOURCE_NODE"] = $parentNode; + $collect[] = $metadata; + } + $parentNode->collectMetadataInParents($nameSpace, $private, $scope, $indexable, $collect); + } + + } + /** * @param bool $boolean Leaf or Collection? * @return void diff --git a/core/src/core/classes/class.AJXP_PluginsService.php b/core/src/core/classes/class.AJXP_PluginsService.php index a13dd51142..65661351ba 100644 --- a/core/src/core/classes/class.AJXP_PluginsService.php +++ b/core/src/core/classes/class.AJXP_PluginsService.php @@ -464,6 +464,19 @@ public function setPluginActiveInst($type, $name, $active=true, $updateInstance $this->buildXmlRegistry(($this->registryVersion == "extended")); } } + + public static function deferBuildingRegistry(){ + self::getInstance()->tmpDeferRegistryBuild = true; + } + + public static function flushDeferredRegistryBuilding(){ + $t = self::getInstance(); + $t->tmpDeferRegistryBuild = false; + if (isSet($t->xmlRegistry)) { + $t->buildXmlRegistry(($t->registryVersion == "extended")); + } + } + /** * Some type require only one active plugin at a time * @param $type @@ -474,11 +487,12 @@ public function setPluginActiveInst($type, $name, $active=true, $updateInstance public function setPluginUniqueActiveForType($type, $name, $updateInstance = null) { $typePlugs = $this->getPluginsByType($type); + $originalValue = $this->tmpDeferRegistryBuild; $this->tmpDeferRegistryBuild = true; foreach ($typePlugs as $plugName => $plugObject) { $this->setPluginActiveInst($type, $plugName, false); } - $this->tmpDeferRegistryBuild = false; + $this->tmpDeferRegistryBuild = $originalValue; $this->setPluginActiveInst($type, $name, true, $updateInstance); } /** diff --git a/core/src/core/classes/class.ConfService.php b/core/src/core/classes/class.ConfService.php index 79743041b0..ec3de20508 100644 --- a/core/src/core/classes/class.ConfService.php +++ b/core/src/core/classes/class.ConfService.php @@ -1195,7 +1195,12 @@ public function loadRepositoryDriverREST(&$repository) } $accessType = $repository->getAccessType(); $pServ = AJXP_PluginsService::getInstance(); - $plugInstance = $pServ->getPluginByTypeName("access", $accessType); + $plugInstanceOrig = $pServ->getPluginByTypeName("access", $accessType); + if(!empty($plugInstanceOrig->repository) && $plugInstanceOrig->repository != $repository){ + $plugInstance = clone $plugInstanceOrig; + }else{ + return $plugInstanceOrig; + } // TRIGGER BEFORE INIT META $metaSources = $repository->getOption("META_SOURCES"); @@ -1227,6 +1232,7 @@ public function loadRepositoryDriverREST(&$repository) } catch (Exception $e) { throw $e; } + AJXP_PluginsService::deferBuildingRegistry(); $pServ->setPluginUniqueActiveForType("access", $accessType); // TRIGGER INIT META @@ -1251,6 +1257,7 @@ public function loadRepositoryDriverREST(&$repository) $pServ->setPluginActive($split[0], $split[1]); } } + AJXP_PluginsService::flushDeferredRegistryBuilding(); if (count($this->errors)>0) { $e = new AJXP_Exception("Error while loading repository feature : ".implode(",",$this->errors)); throw $e; diff --git a/core/src/plugins/action.share/class.ShareCenter.php b/core/src/plugins/action.share/class.ShareCenter.php index b7dd3defec..bc546e03ea 100644 --- a/core/src/plugins/action.share/class.ShareCenter.php +++ b/core/src/plugins/action.share/class.ShareCenter.php @@ -539,6 +539,126 @@ public static function isShared($ajxpNode) return false; } + /** + * @param AJXP_Node $node + * @param String|null $direction "UP", "DOWN" + * @return array() + */ + private function findMirrorNodesInShares($node, $direction){ + $result = array(); + if($direction !== "UP"){ + $upmetas = array(); + $node->collectMetadataInParents("ajxp_shared", true, AJXP_METADATA_SCOPE_REPOSITORY, false, $upmetas); + foreach($upmetas as $metadata){ + if (is_array($metadata) && !empty($metadata["element"])) { + if(is_string($metadata["element"])){ + $wsId = $metadata["element"]; + if(isSet($metadata["minisite"])){ + $minisiteData = self::loadPublicletData($metadata["element"]); + $wsId = $minisiteData["REPOSITORY"]; + } + $sharedNode = $metadata["SOURCE_NODE"]; + $sharedPath = substr($node->getPath(), strlen($sharedNode->getPath())); + $sharedNodeUrl = $node->getScheme() . "://".$wsId.$sharedPath; + $result[$wsId] = array(new AJXP_Node($sharedNodeUrl), "DOWN"); + } + } + } + } + if($direction !== "DOWN"){ + if($node->getRepository()->hasParent()){ + $parentRepoId = $node->getRepository()->getParentId(); + $currentRoot = $node->getRepository()->getOption("PATH"); + $parentRoot = ConfService::getRepositoryById($parentRepoId)->getOption("PATH"); + $relative = substr($currentRoot, strlen($parentRoot)); + $parentNodeURL = $node->getScheme()."://".$parentRepoId.$relative.$node->getPath(); + $this->logDebug("action.share", "Should trigger on ".$parentNodeURL); + $result[$parentRepoId] = array(new AJXP_Node($parentNodeURL), "UP"); + } + } + return $result; + } + + private function applyForwardEvent($fromMirrors = null, $toMirrors = null, $copy = false, $direction = null){ + if($fromMirrors === null){ + // Create + foreach($toMirrors as $mirror){ + list($node, $direction) = $mirror; + AJXP_Controller::applyHook("node.change", array(null, $node, false, $direction), true); + } + }else if($toMirrors === null){ + foreach($fromMirrors as $mirror){ + list($node, $direction) = $mirror; + AJXP_Controller::applyHook("node.change", array($node, null, false, $direction), true); + } + }else{ + foreach($fromMirrors as $repoId => $mirror){ + list($fNode, $fDirection) = $mirror; + if(isSet($toMirrors[$repoId])){ + list($tNode, $tDirection) = $toMirrors[$repoId]; + unset($toMirrors[$repoId]); + AJXP_Controller::applyHook("node.change", array($fNode, $tNode, $copy, $fDirection), true); + }else{ + AJXP_Controller::applyHook("node.change", array($fNode, null, $copy, $fDirection), true); + } + } + foreach($toMirrors as $mirror){ + list($tNode, $tDirection) = $mirror; + AJXP_Controller::applyHook("node.change", array(null, $tNode, $copy, $tDirection), true); + } + } + + } + + /** + * @param AJXP_Node $fromNode + * @param AJXP_Node $toNode + * @param bool $copy + * @param String $direction + */ + public function forwardEventToShares($fromNode=null, $toNode=null, $copy = false, $direction=null){ + + if(empty($direction) && $this->getFilteredOption("FORK_EVENT_FORWARDING")){ + AJXP_Controller::applyActionInBackground( + ConfService::getRepository()->getId(), + "forward_change_event", + array( + "from" => $fromNode === null ? "" : $fromNode->getUrl(), + "to" => $toNode === null ? "" : $toNode->getUrl(), + "copy" => $copy ? "true" : "false", + "direction" => $direction + )); + return; + } + + $fromMirrors = null; + $toMirrors = null; + if($fromNode != null){ + $fromMirrors = $this->findMirrorNodesInShares($fromNode, $direction); + } + if($toNode != null){ + $toMirrors = $this->findMirrorNodesInShares($toNode, $direction); + } + + $this->applyForwardEvent($fromMirrors, $toMirrors, $copy, $direction); + + } + + public function forwardEventToSharesAction($actionName, $httpVars, $fileVars){ + + $fromMirrors = null; + $toMirrors = null; + if(!empty($httpVars["from"])){ + $fromMirrors = $this->findMirrorNodesInShares(new AJXP_Node($httpVars["from"]), $httpVars["direction"]); + } + if(!empty($httpVars["to"])){ + $toMirrors = $this->findMirrorNodesInShares(new AJXP_Node($httpVars["to"]), $httpVars["direction"]); + } + $this->applyForwardEvent($fromMirrors, $toMirrors, ($httpVars["copy"] === "true"), $httpVars["direction"]); + + } + + /** * * Hooked to node.change, this will update the index diff --git a/core/src/plugins/action.share/manifest.xml b/core/src/plugins/action.share/manifest.xml index 0a9e871499..abbb17d83e 100644 --- a/core/src/plugins/action.share/manifest.xml +++ b/core/src/plugins/action.share/manifest.xml @@ -1,6 +1,7 @@ + @@ -9,13 +10,7 @@ - - - @@ -479,6 +474,11 @@ + + + + + @@ -513,6 +513,9 @@ ]]> + + + diff --git a/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php b/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php index 7dc91b1eb4..1d6da06288 100644 --- a/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php +++ b/core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php @@ -374,7 +374,7 @@ public function updateNodeIndexMeta($node) if (isSet($this->currentIndex)) { $index = $this->currentIndex; } else { - $index = $this->loadIndex(ConfService::getRepository()->getId()); + $index = $this->loadIndex($node->getRepositoryId()); } Zend_Search_Lucene_Analysis_Analyzer::setDefault( new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive()); @@ -412,7 +412,11 @@ public function updateNodeIndex($oldNode, $newNode = null, $copy = false) if (isSet($this->currentIndex)) { $index = $this->currentIndex; } else { - $index = $this->loadIndex(ConfService::getRepository()->getId()); + if($oldNode == null){ + $index = $this->loadIndex($newNode->getRepositoryId()); + }else{ + $index = $this->loadIndex($oldNode->getRepositoryId()); + } } $this->setDefaultAnalyzer(); if ($oldNode != null && $copy == false) {