/** * @param AJXP_Node $node * @return string */ protected function getUserId($node) { if ($node->hasUser()) { return $node->getUser(); } if (AuthService::usersEnabled()) { return AuthService::getLoggedUser()->getId(); } return "shared"; }
/** * @param bool $private * @param AJXP_Node $node * @return string */ protected function getUserId($private, $node) { if (!$private) { return AJXP_METADATA_SHAREDUSER; } if ($node->hasUser()) { return $node->getUser(); } if (AuthService::usersEnabled()) { return AuthService::getLoggedUser()->getId(); } return "shared"; }
/** * @param AJXP_Node $oldNode * @param AJXP_Node $newNode * @param bool $copy */ public function updateNodesIndex($oldNode = null, $newNode = null, $copy = false) { if (!dibi::isConnected()) { dibi::connect($this->sqlDriver); } //$this->logInfo("Syncable index", array($oldNode == null?'null':$oldNode->getUrl(), $newNode == null?'null':$newNode->getUrl())); try { if ($newNode != null && $this->excludeNode($newNode)) { // CREATE if ($oldNode == null) { AJXP_Logger::debug("Ignoring " . $newNode->getUrl() . " for indexation"); return; } else { AJXP_Logger::debug("Target node is excluded, see it as a deletion: " . $newNode->getUrl()); $newNode = null; } } if ($newNode == null) { $repoId = $this->computeIdentifier($oldNode->getRepository(), $oldNode->getUser()); // DELETE $this->logDebug('DELETE', $oldNode->getUrl()); dibi::query("DELETE FROM [ajxp_index] WHERE [node_path] LIKE %like~ AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); } else { if ($oldNode == null || $copy) { // CREATE $stat = stat($newNode->getUrl()); $newNode->setLeaf(!($stat['mode'] & 040000)); $this->logDebug('INSERT', $newNode->getUrl()); dibi::query("INSERT INTO [ajxp_index]", array("node_path" => SystemTextEncoding::toUTF8($newNode->getPath()), "bytesize" => $stat["size"], "mtime" => $stat["mtime"], "md5" => $newNode->isLeaf() ? md5_file($newNode->getUrl()) : "directory", "repository_identifier" => $repoId = $this->computeIdentifier($newNode->getRepository(), $newNode->getUser()))); } else { $repoId = $this->computeIdentifier($oldNode->getRepository(), $oldNode->getUser()); if ($oldNode->getPath() == $newNode->getPath()) { // CONTENT CHANGE clearstatcache(); $stat = stat($newNode->getUrl()); $this->logDebug("Content changed", "current stat size is : " . $stat["size"]); $this->logDebug('UPDATE CONTENT', $newNode->getUrl()); dibi::query("UPDATE [ajxp_index] SET ", array("bytesize" => $stat["size"], "mtime" => $stat["mtime"], "md5" => md5_file($newNode->getUrl())), "WHERE [node_path] = %s AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); try { $rowCount = dibi::getAffectedRows(); if ($rowCount === 0) { $this->logError(__FUNCTION__, "There was an update event on a non-indexed node (" . $newNode->getPath() . "), creating index entry!"); $this->updateNodesIndex(null, $newNode, false); } } catch (Exception $e) { } } else { // PATH CHANGE ONLY $newNode->loadNodeInfo(); if ($newNode->isLeaf()) { $this->logDebug('UPDATE LEAF PATH', $newNode->getUrl()); dibi::query("UPDATE [ajxp_index] SET ", array("node_path" => SystemTextEncoding::toUTF8($newNode->getPath())), "WHERE [node_path] = %s AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); try { $rowCount = dibi::getAffectedRows(); if ($rowCount === 0) { $this->logError(__FUNCTION__, "There was an update event on a non-indexed node (" . $newNode->getPath() . "), creating index entry!"); $this->updateNodesIndex(null, $newNode, false); } } catch (Exception $e) { } } else { $this->logDebug('UPDATE FOLDER PATH', $newNode->getUrl()); dibi::query("UPDATE [ajxp_index] SET [node_path]=REPLACE( REPLACE(CONCAT('\$\$\$',[node_path]), CONCAT('\$\$\$', %s), CONCAT('\$\$\$', %s)) , '\$\$\$', '') ", $oldNode->getPath(), $newNode->getPath(), "WHERE [node_path] LIKE %like~ AND [repository_identifier] = %s", SystemTextEncoding::toUTF8($oldNode->getPath()), $repoId); try { $rowCount = dibi::getAffectedRows(); if ($rowCount === 0) { $this->logError(__FUNCTION__, "There was an update event on a non-indexed folder (" . $newNode->getPath() . "), relaunching a recursive indexation!"); AJXP_Controller::findActionAndApply("index", array("file" => $newNode->getPath()), array()); } } catch (Exception $e) { } } } } } } catch (Exception $e) { AJXP_Logger::error("[meta.syncable]", "Exception", $e->getTraceAsString()); AJXP_Logger::error("[meta.syncable]", "Indexation", $e->getMessage()); } }
/** * * @param AJXP_Node $node * @param int $depth * @throws Exception */ public function recursiveIndexation($node, $depth = 0) { $repository = $node->getRepository(); $user = $node->getUser(); $messages = ConfService::getMessages(); if ($user == null && AuthService::usersEnabled()) { $user = AuthService::getLoggedUser(); } if ($depth == 0) { $this->logDebug("Starting indexation - node.index.recursive.start - " . memory_get_usage(true) . " - " . $node->getUrl()); $this->setIndexStatus("RUNNING", str_replace("%s", $node->getPath(), $messages["core.index.8"]), $repository, $user); AJXP_Controller::applyHook("node.index.recursive.start", array($node)); } else { if ($this->isInterruptRequired($repository, $user)) { $this->logDebug("Interrupting indexation! - node.index.recursive.end - " . $node->getUrl()); AJXP_Controller::applyHook("node.index.recursive.end", array($node)); $this->releaseStatus($repository, $user); throw new Exception("User interrupted"); } } if (!ConfService::currentContextIsCommandLine()) { @set_time_limit(120); } $url = $node->getUrl(); $this->logDebug("Indexing Node parent node " . $url); $this->setIndexStatus("RUNNING", str_replace("%s", $node->getPath(), $messages["core.index.8"]), $repository, $user); try { AJXP_Controller::applyHook("node.index", array($node)); } catch (Exception $e) { $this->logDebug("Error Indexing Node " . $url . " (" . $e->getMessage() . ")"); } $handle = opendir($url); if ($handle !== false) { while (($child = readdir($handle)) != false) { if ($child[0] == ".") { continue; } $childNode = new AJXP_Node(rtrim($url, "/") . "/" . $child); $childUrl = $childNode->getUrl(); if (is_dir($childUrl)) { $this->logDebug("Entering recursive indexation for " . $childUrl); $this->recursiveIndexation($childNode, $depth + 1); } else { try { $this->logDebug("Indexing Node " . $childUrl); AJXP_Controller::applyHook("node.index", array($childNode)); } catch (Exception $e) { $this->logDebug("Error Indexing Node " . $childUrl . " (" . $e->getMessage() . ")"); } } } closedir($handle); } else { $this->logDebug("Cannot open {$url}!!"); } if ($depth == 0) { $this->logDebug("End indexation - node.index.recursive.end - " . memory_get_usage(true) . " - " . $node->getUrl()); $this->setIndexStatus("RUNNING", "Indexation finished, cleaning...", $repository, $user); AJXP_Controller::applyHook("node.index.recursive.end", array($node)); $this->releaseStatus($repository, $user); $this->logDebug("End indexation - After node.index.recursive.end - " . memory_get_usage(true) . " - " . $node->getUrl()); } }
/** * @param AJXP_Node $origNode * @param AJXP_Node $newNode * @param bool $copy */ public function publishNodeChange($origNode = null, $newNode = null, $copy = false) { $content = ""; $repo = ""; $targetUserId = null; $nodePathes = array(); $update = false; if ($newNode != null) { $repo = $newNode->getRepositoryId(); $targetUserId = $newNode->getUser(); $nodePathes[] = $newNode->getPath(); $update = false; $data = array(); if ($origNode != null && !$copy) { $update = true; $data[$origNode->getPath()] = $newNode; } else { $data[] = $newNode; } $content = AJXP_XMLWriter::writeNodesDiff(array($update ? "UPDATE" : "ADD" => $data)); } if ($origNode != null && !$update && !$copy) { $repo = $origNode->getRepositoryId(); $targetUserId = $origNode->getUser(); $nodePathes[] = $origNode->getPath(); $content = AJXP_XMLWriter::writeNodesDiff(array("REMOVE" => array($origNode->getPath()))); } if (!empty($content) && $repo != "") { $this->sendInstantMessage($content, $repo, $targetUserId, null, $nodePathes); } }
/** * * Hooked to node.change, this will update the index * if $oldNode = null => create node $newNode * if $newNode = null => delete node $oldNode * Else copy or move oldNode to newNode. * * @param AJXP_Node $oldNode * @param AJXP_Node $newNode * @param Boolean $copy * @param bool $recursive */ public function updateNodeIndex($oldNode, $newNode = null, $copy = false, $recursive = false) { if ($oldNode == null) { $this->loadIndex($newNode->getRepositoryId(), true, $newNode->getUser()); } else { $this->loadIndex($oldNode->getRepositoryId(), true, $oldNode->getUser()); } if ($oldNode != null && $copy == false) { $oldDocId = $this->getIndexedDocumentId($oldNode); if ($oldDocId != null) { $this->currentType->deleteById($oldDocId); $childrenHits = $this->getIndexedChildrenDocuments($newNode); if ($childrenHits != null) { $childrenHits = $childrenHits->getResults(); foreach ($childrenHits as $hit) { $this->currentType->deleteById($hit->getId()); } } } } if ($newNode != null) { // Make sure it does not already exists anyway $newDocId = $this->getIndexedDocumentId($newNode); if ($newDocId != null) { try { $this->currentType->deleteById($newDocId); } catch (Elastica\Exception\NotFoundException $eEx) { $this->logError(__FUNCTION__, "Trying to delete a non existing document"); } $childrenHits = $this->getIndexedChildrenDocuments($newNode); if ($childrenHits != null) { $childrenHits = $childrenHits->getResults(); foreach ($childrenHits as $hit) { try { $this->currentType->deleteById($hit->getId()); } catch (Elastica\Exception\NotFoundException $eEx) { $this->logError(__FUNCTION__, "Trying to delete a non existing document"); } } } } $this->createIndexedDocument($newNode); if ($recursive && $oldNode == null && is_dir($newNode->getUrl())) { $this->recursiveIndexation($newNode->getUrl()); } } if ($oldNode != null && $newNode != null && is_dir($newNode->getUrl())) { // Copy / Move / Rename // Get old node children docs, and update them manually, no need to scan real directory $childrenHits = $this->getIndexedChildrenDocuments($oldNode); if ($childrenHits != null) { $childrenHits = $childrenHits->getResults(); foreach ($childrenHits as $hit) { $oldChildURL = $this->currentType->getDocument($hit->getId())->get("node_url"); if ($copy == false) { $this->currentType->deleteById($hit->getId()); } $newChildURL = str_replace(SystemTextEncoding::toUTF8($oldNode->getUrl()), SystemTextEncoding::toUTF8($newNode->getUrl()), $oldChildURL); $newChildURL = SystemTextEncoding::fromUTF8($newChildURL); $this->createIndexedDocument(new AJXP_Node($newChildURL)); } } } }
/** * * Hooked to node.change, this will update the index * if $oldNode = null => create node $newNode * if $newNode = null => delete node $oldNode * Else copy or move oldNode to newNode. * * @param AJXP_Node $oldNode * @param AJXP_Node $newNode * @param Boolean $copy * @param bool $recursive */ public function updateNodeIndex($oldNode, $newNode = null, $copy = false, $recursive = false) { require_once "Zend/Search/Lucene.php"; if (isset($this->currentIndex)) { $oldIndex = $newIndex = $this->currentIndex; } else { if ($oldNode == null) { $newIndex = $oldIndex = $this->loadIndex($newNode->getRepositoryId(), true, $newNode->getUser()); } else { if ($newNode == null) { $oldIndex = $newIndex = $this->loadIndex($oldNode->getRepositoryId(), true, $oldNode->getUser()); } else { $newId = $newNode->getRepositoryId(); $oldId = $oldNode->getRepositoryId(); if ($newId == $oldId) { $newIndex = $oldIndex = $this->loadIndex($newNode->getRepositoryId(), true, $newNode->getUser()); } else { $newIndex = $this->loadIndex($newNode->getRepositoryId(), true, $newNode->getUser()); $oldIndex = $this->loadIndex($oldNode->getRepositoryId(), true, $oldNode->getUser()); } } } } $this->setDefaultAnalyzer(); if ($oldNode != null && $copy == false) { $oldDocId = $this->getIndexedDocumentId($oldIndex, $oldNode); if ($oldDocId != null) { $oldIndex->delete($oldDocId); if ($newNode == null) { // DELETION $childrenHits = $this->getIndexedChildrenDocuments($oldIndex, $oldNode); foreach ($childrenHits as $hit) { $oldIndex->delete($hit->id); } } } } if ($newNode != null) { // Make sure it does not already exists anyway $newDocId = $this->getIndexedDocumentId($newIndex, $newNode); if ($newDocId != null) { $newIndex->delete($newDocId); $childrenHits = $this->getIndexedChildrenDocuments($newIndex, $newNode); foreach ($childrenHits as $hit) { $newIndex->delete($hit->id); } } $this->createIndexedDocument($newNode, $newIndex); if ($recursive && $oldNode == null && is_dir($newNode->getUrl())) { $this->recursiveIndexation($newNode->getUrl()); } } if ($oldNode != null && $newNode != null && is_dir($newNode->getUrl()) && $newIndex == $oldIndex) { // Copy / Move / Rename // Get old node children docs, and update them manually, no need to scan real directory $childrenHits = $this->getIndexedChildrenDocuments($oldIndex, $oldNode); foreach ($childrenHits as $hit) { $oldChildURL = $oldIndex->getDocument($hit->id)->node_url; if ($copy == false) { $oldIndex->delete($hit->id); } $newChildURL = str_replace(SystemTextEncoding::toUTF8($oldNode->getUrl()), SystemTextEncoding::toUTF8($newNode->getUrl()), $oldChildURL); $newChildURL = SystemTextEncoding::fromUTF8($newChildURL); $this->createIndexedDocument(new AJXP_Node($newChildURL), $oldIndex); } } if (!isset($this->currentIndex)) { $oldIndex->commit(); if ($newIndex != $oldIndex) { $newIndex->commit(); } } }
/** * @param AJXP_Node $ajxpNode * @param String $scope * @param String $userId */ protected function saveMetaFileData($ajxpNode, $scope, $userId) { $currentFile = $ajxpNode->getUrl(); $repositoryId = $ajxpNode->getRepositoryId(); $fileKey = $ajxpNode->getPath(); if (isset($this->options["METADATA_FILE_LOCATION"]) && $this->options["METADATA_FILE_LOCATION"] == "outside") { // Force scope $scope = AJXP_METADATA_SCOPE_REPOSITORY; } if ($scope == AJXP_METADATA_SCOPE_GLOBAL) { $metaFile = dirname($currentFile) . "/" . $this->options["METADATA_FILE"]; $fileKey = basename($fileKey); } else { if (!is_dir(dirname($this->globalMetaFile))) { mkdir(dirname($this->globalMetaFile), 0755, true); } $metaFile = $this->globalMetaFile . "_" . $repositoryId; $metaFile = $this->updateSecurityScope($metaFile, $ajxpNode->getRepositoryId(), $ajxpNode->getUser()); } if ($scope == AJXP_METADATA_SCOPE_REPOSITORY || @is_file($metaFile) && call_user_func(array($this->accessDriver, "isWriteable"), $metaFile) || call_user_func(array($this->accessDriver, "isWriteable"), dirname($metaFile))) { if (is_array(self::$metaCache) && count(self::$metaCache)) { if (!isset(self::$fullMetaCache[$metaFile])) { self::$fullMetaCache[$metaFile] = array(); } if (!isset(self::$fullMetaCache[$metaFile][$fileKey])) { self::$fullMetaCache[$metaFile][$fileKey] = array(); } if (!isset(self::$fullMetaCache[$metaFile][$fileKey][$userId])) { self::$fullMetaCache[$metaFile][$fileKey][$userId] = array(); } self::$fullMetaCache[$metaFile][$fileKey][$userId] = self::$metaCache; } else { // CLEAN if (isset(self::$fullMetaCache[$metaFile][$fileKey][$userId])) { unset(self::$fullMetaCache[$metaFile][$fileKey][$userId]); } if (isset(self::$fullMetaCache[$metaFile][$fileKey]) && !count(self::$fullMetaCache[$metaFile][$fileKey])) { unset(self::$fullMetaCache[$metaFile][$fileKey]); } } $fp = @fopen($metaFile, "w"); if ($fp !== false) { @fwrite($fp, serialize(self::$fullMetaCache[$metaFile]), strlen(serialize(self::$fullMetaCache[$metaFile]))); @fclose($fp); } else { $this->logError(__FUNCTION__, "Error while trying to open the meta file, maybe a permission problem?"); } if ($scope == AJXP_METADATA_SCOPE_GLOBAL) { AJXP_Controller::applyHook("version.commit_file", array($metaFile, $ajxpNode)); } } }
/** * @param AJXP_Node $ajxpNode * @param string $nameSpace * @param string $userScope * @return array */ public function collectChildrenWithRepositoryMeta($ajxpNode, $nameSpace, $userScope) { $result = array(); $repositoryId = $ajxpNode->getRepositoryId(); $metaFile = $this->globalMetaFile . "_" . $repositoryId; $metaFile = $this->updateSecurityScope($metaFile, $ajxpNode->getRepositoryId(), $ajxpNode->getUser()); if (!is_file($metaFile)) { return $result; } $raw_data = file_get_contents($metaFile); if ($raw_data === false) { return $result; } $metadata = unserialize($raw_data); if ($metadata === false || !is_array($metadata)) { return $result; } $srcPath = $ajxpNode->getPath(); if ($srcPath == "/") { $srcPath = ""; } foreach ($metadata as $path => $data) { preg_match("#^" . preg_quote($srcPath, "#") . "/#", $path, $matches); if ($path == $srcPath || count($matches)) { $relativePath = substr($path, strlen($srcPath)); // REMOVE ORIGINAL NODE PATH if ($relativePath === false) { $relativePath = "/"; } foreach ($data as $userId => $meta) { if (($userScope == $userId || $userScope == AJXP_METADATA_ALLUSERS) && isset($meta[$nameSpace])) { if (!isset($result[$relativePath])) { $result[$relativePath] = array(); } $result[$relativePath][$userId] = $meta[$nameSpace]; } } } } return $result; }