diff --git a/core/src/plugins/meta.syncable/class.ChangesTracker.php b/core/src/plugins/meta.syncable/class.ChangesTracker.php index ca19c13301..8d31c24014 100644 --- a/core/src/plugins/meta.syncable/class.ChangesTracker.php +++ b/core/src/plugins/meta.syncable/class.ChangesTracker.php @@ -36,6 +36,96 @@ public function init($options) parent::init($options); } + protected function indexIsSync(){ + // Grab all folders mtime and compare them + $repoIdentifier = $this->computeIdentifier($this->accessDriver->repository); + $res = dibi::query("SELECT [node_path],[mtime] FROM [ajxp_index] WHERE [md5] = %s AND [repository_identifier] = %s", 'directory', $repoIdentifier); + $modified = array(); + + // REGISTER ROOT ANYWAY: WE PROBABLY CAN'T GET A "FILEMTIME" ON IT. + $mod = array( + "url" => $this->accessDriver->getResourceUrl(""), + "path" => "/", + "children" => array() + ); + $children = dibi::query("SELECT [node_path],[mtime] FROM [ajxp_index] WHERE [repository_identifier] = %s AND [node_path] LIKE %s AND [node_path] NOT LIKE %s", + $repoIdentifier, "/%", "/%/%"); + foreach($children as $cRow){ + $mod["children"][substr($cRow->node_path, 1)] = $cRow->mtime; + } + $modified[] = $mod; + + clearstatcache(); + // CHECK ALL FOLDERS + foreach($res as $row){ + $path = $row->node_path; + $mtime = intval($row->mtime); + $url = $this->accessDriver->getResourceUrl($path); + $currentTime = @filemtime($url); + if($currentTime === false && !file_exists($url)) { + // Deleted folder! + $this->logDebug(__FUNCTION__, "Folder deleted directly on storage: ".$url); + $node = new AJXP_Node($url); + AJXP_Controller::applyHook("node.change", array(&$node, null, false)); + continue; + } + if($currentTime > $mtime){ + $mod = array( + "url" => $url, + "path" => $path, + "children" => array(), + "current_time" => $currentTime + ); + $children = dibi::query("SELECT [node_path],[mtime],[md5] FROM [ajxp_index] WHERE [md5] != %s AND [repository_identifier] = %s AND [node_path] LIKE %s AND [node_path] NOT LIKE %s", + 'directory', $repoIdentifier, "$path/%", "$path/%/%"); + foreach($children as $cRow){ + $mod["children"][substr($cRow->node_path, strlen($path)+1)] = $cRow->mtime; + } + $modified[] = $mod; + } + } + + // NOW COMPUTE DIFFS + foreach($modified as $mod_data){ + $url = $mod_data["url"]; + $current_time = $mod_data["current_time"]; + $currentChildren = $mod_data["children"]; + $files = scandir($url); + foreach($files as $f){ + if($f[0] == ".") continue; + $nodeUrl = $url."/".$f; + $node = new AJXP_Node($nodeUrl); + // Ignore dirs modified time + // if(is_dir($nodeUrl) && $mod_data["path"] != "/") continue; + if(!isSet($currentChildren[$f])){ + // New items detected + $this->logDebug(__FUNCTION__, "New item detected on storage: ".$nodeUrl); + AJXP_Controller::applyHook("node.change", array(null, &$node, false)); + continue; + }else { + if(is_dir($nodeUrl)) continue; // Make sure to not trigger a recursive indexation here. + if(filemtime($nodeUrl) > $currentChildren[$f]){ + // Changed! + $this->logDebug(__FUNCTION__, "Item modified directly on storage: ".$nodeUrl); + AJXP_Controller::applyHook("node.change", array(&$node, &$node, false)); + } + } + } + foreach($currentChildren as $cPath => $mtime){ + if(!in_array($cPath, $files)){ + // Deleted + $this->logDebug(__FUNCTION__, "File deleted directly on storage: ".$url."/".$cPath); + $node = new AJXP_Node($url."/".$cPath); + AJXP_Controller::applyHook("node.change", array(&$node, null, false)); + } + } + // Now "touch" parent directory + if(isSet($current_time)){ + dibi::query("UPDATE [ajxp_index] SET ", array("mtime" => $current_time), " WHERE [repository_identifier] = %s AND [node_path] = %s", $repoIdentifier, $mod_data["path"]); + } + } + } + public function switchActions($actionName, $httpVars, $fileVars) { if($actionName != "changes" || !isSet($httpVars["seq_id"])) return false; @@ -47,6 +137,10 @@ public function switchActions($actionName, $httpVars, $fileVars) $recycle = $currentRepo->getOption("RECYCLE_BIN"); $recycle = (!empty($recycle)?$recycle:false); + if($this->options["OBSERVE_STORAGE_CHANGES"]){ + $this->indexIsSync(); + } + HTMLWriter::charsetHeader('application/json', 'UTF-8'); if(isSet($httpVars["filter"])){ $filter = AJXP_Utils::decodeSecureMagic($httpVars["filter"]); diff --git a/core/src/plugins/meta.syncable/manifest.xml b/core/src/plugins/meta.syncable/manifest.xml index cf4f256a2f..d70d687f98 100644 --- a/core/src/plugins/meta.syncable/manifest.xml +++ b/core/src/plugins/meta.syncable/manifest.xml @@ -5,6 +5,7 @@ +