Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
Add methods for recursive search of metadata and implement this by ho…
Browse files Browse the repository at this point in the history
…oking 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
  • Loading branch information
cdujeu committed Mar 14, 2014
1 parent 7738d3e commit a8dae41
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 17 deletions.
4 changes: 1 addition & 3 deletions core/src/core/classes/class.AJXP_Cache.php
Expand Up @@ -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());
}
Expand Down Expand Up @@ -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);
}
Expand Down
9 changes: 5 additions & 4 deletions core/src/core/classes/class.AJXP_Controller.php
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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)
{
Expand Down
44 changes: 44 additions & 0 deletions core/src/core/classes/class.AJXP_Node.php
Expand Up @@ -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
Expand Down
16 changes: 15 additions & 1 deletion core/src/core/classes/class.AJXP_PluginsService.php
Expand Up @@ -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
Expand All @@ -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);
}
/**
Expand Down
9 changes: 8 additions & 1 deletion core/src/core/classes/class.ConfService.php
Expand Up @@ -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");
Expand Down Expand Up @@ -1227,6 +1232,7 @@ public function loadRepositoryDriverREST(&$repository)
} catch (Exception $e) {
throw $e;
}
AJXP_PluginsService::deferBuildingRegistry();
$pServ->setPluginUniqueActiveForType("access", $accessType);

// TRIGGER INIT META
Expand All @@ -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;
Expand Down
120 changes: 120 additions & 0 deletions core/src/plugins/action.share/class.ShareCenter.php
Expand Up @@ -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
Expand Down
15 changes: 9 additions & 6 deletions core/src/plugins/action.share/manifest.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ajxp_plugin name="share" label="CONF_MESSAGE[Sharing Features]" description="CONF_MESSAGE[Share Center actions and hooks]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:../core.ajaxplorer/ajxp_registry.xsd">
<server_settings>
<global_param name="FORK_EVENT_FORWARDING" type="boolean" label="Fork Events Forwarding" description="If you detect performances issues while modifiyng files under deep trees, try activating that one. Please be sure of what you do, this may trigger a whole lot of php processes on the server." default="false"/>
<global_param name="USE_REWRITE_RULE" group="CONF_MESSAGE[Link Generation]" description="CONF_MESSAGE[Use web server RewriteEngine mechanism to generate prettier URLs]" label="CONF_MESSAGE[Use Rewrite Rule]" type="boolean" default="false"/>
<global_param name="HASH_MIN_LENGTH" group="CONF_MESSAGE[Link Generation]" description="CONF_MESSAGE[Minimum length of the generated hash]" label="CONF_MESSAGE[Hash minimum length]" type="integer" default="6"/>
<global_param name="FILE_MAX_EXPIRATION" group="CONF_MESSAGE[Link Generation]" description="CONF_MESSAGE[Maximum share expiration limit for file, 0 = unlimited]" label="CONF_MESSAGE[Maximum file expiration limit]" type="integer" default="0" expose="true"/>
Expand All @@ -9,13 +10,7 @@
<global_param name="CREATE_QRCODE" group="CONF_MESSAGE[Link Generation]" description="CONF_MESSAGE[Create and display QRCode for shared link]" label="CONF_MESSAGE[Create QRCode]" type="boolean" default="true" expose="true"/>
<global_param name="ENABLE_FOLDER_SHARING" group="CONF_MESSAGE[Folder Sharing]" description="CONF_MESSAGE[Enable folder sharing (workspace and minisite)]" label="CONF_MESSAGE[Enable folder sharing]" type="boolean" default="true" expose="true"/>
<global_param name="AVOID_SHARED_FOLDER_SAME_LABEL" group="CONF_MESSAGE[Folder Sharing]" description="CONF_MESSAGE[Disallow users to create shared folders if a workspace already exists with the same label]" label="CONF_MESSAGE[Avoid labels duplication]" type="boolean" default="false"/>
<!--
<global_param name="SHARED_USERS_LIST_MINIMUM" group="CONF_MESSAGE[Shared users configurations]" description="CONF_MESSAGE[Minimum number of characters to start getting results by auto-completion when sharing a folder with other users]" label="CONF_MESSAGE[Autocomplete minimum chars]" type="integer" default="2" expose="true"/>
<global_param name="SHARED_USERS_LIST_LIMIT" group="CONF_MESSAGE[Shared users configurations]" description="CONF_MESSAGE[Limit the number of results returned by the auto-completion feature when sharing a folder with other users]" label="CONF_MESSAGE[Autocompletion results limit]" type="integer" default="50" expose="true"/>
-->
<global_param name="SHARED_USERS_TMP_PREFIX" group="CONF_MESSAGE[Shared users configurations]" description="CONF_MESSAGE[Mandatory prefix for users created temporary users login]" label="CONF_MESSAGE[Tmp users prefix]" type="string" expose="true"/>
<global_param name="METADATA_FILE" group="CONF_MESSAGE[Metadata Files]" type="string" label="CONF_MESSAGE[Metadata File]" description="CONF_MESSAGE[Hidden file containing shared metadata]" mandatory="true" default=".ajxp_share_meta"/>
<global_param name="METADATA_FILE_LOCATION" group="CONF_MESSAGE[Metadata Files]" type="select" choices="infolders|In Local Folders,global|In Global Folder" label="CONF_MESSAGE[File location]" description="CONF_MESSAGE[Where to store the metadata file : LOCAL means a hidden file will be created in each folder, GLOBAL means that one file will be created in AJXP_DATA_PATH/plugins/action.share folder.]" mandatory="true" default="infolders"/>
<global_param name="CUSTOM_SHAREPAGE_TITLE" group="CONF_MESSAGE[Weblink Page]" type="string" label="CONF_MESSAGE[Page Title]" description="CONF_MESSAGE[Share page title. Use AJXP_FILENAME keyword to display the file name.]" mandatory="false" default=""/>
<global_param name="CUSTOM_SHAREPAGE_LEGEND" group="CONF_MESSAGE[Weblink Page]" type="string" label="CONF_MESSAGE[Download text]" description="CONF_MESSAGE[Text displayed below the download button. Use AJXP_FILENAME keyword to display the file name, and PYDIO_APP_TITLE for the application title.]" mandatory="false" default=""/>
<global_param name="CUSTOM_SHAREPAGE_LEGEND_PASS" group="CONF_MESSAGE[Weblink Page]" type="string" label="CONF_MESSAGE[Download text w/ Pass]" description="CONF_MESSAGE[Text displayed below the download button when a password is mandatory. Use AJXP_FILENAME keyword to display the file name, and PYDIO_APP_TITLE for the application title.]" mandatory="false" default=""/>
Expand Down Expand Up @@ -479,6 +474,11 @@
</serverCallback>
</processing>
</action>
<action name="forward_change_event">
<processing>
<serverCallback methodName="forwardEventToSharesAction"/>
</processing>
</action>
</actions>
<client_configs>
<component_config className="InfoPanel">
Expand Down Expand Up @@ -513,6 +513,9 @@
]]></additional_tab>
</component_config>
</client_configs>
<hooks>
<serverCallback methodName="forwardEventToShares" hookName="node.change" defer="true"/>
</hooks>
</registry_contributions>
<class_definition filename="plugins/action.share/class.ShareCenter.php" classname="ShareCenter"/>
<dependencies>
Expand Down
8 changes: 6 additions & 2 deletions core/src/plugins/index.lucene/class.AjxpLuceneIndexer.php
Expand Up @@ -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());

Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit a8dae41

Please sign in to comment.