From c15cb2de41961079165abcaa5e046bb11c510e25 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 28 Oct 2021 21:08:31 +0200 Subject: [PATCH] add $depth parameter to Vfs::checkLock($url, int $depth=0) and use it to query all locks in one go for filemanager_ui::get_rows() --- api/src/Vfs.php | 57 +++++++++++++------- filemanager/inc/class.filemanager_ui.inc.php | 9 +++- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/api/src/Vfs.php b/api/src/Vfs.php index b7e3329700..5ad033ff85 100644 --- a/api/src/Vfs.php +++ b/api/src/Vfs.php @@ -1,4 +1,5 @@ -0 = infinit/whole tree is evaluated + * @return array[]|array|boolean $depth > 0: array of path => lock info arrays for $depth > 0 + * $depth=0: false if there's no lock, else array with lock info */ - static function checkLock($url) + static function checkLock($url, int $depth=0) { $path = self::parse_url($url, PHP_URL_PATH); - if (isset(self::$lock_cache[$path])) + if (!$depth && isset(self::$lock_cache[$path])) { if (self::LOCK_DEBUG) error_log(__METHOD__."($url) returns from CACHE ".str_replace(array("\n",' '),'',print_r(self::$lock_cache[$url],true))); return self::$lock_cache[$path]; } - $where = 'lock_path='.self::$db->quote($path); + if ($depth > 0) + { + $where = ['lock_path LIKE '.self::$db->quote($path.'%')]; + } + else + { + $where = 'lock_path='.self::$db->quote($path); + } // ToDo: additional check parent dirs for locks and children of the requested directory //$where .= ' OR '.self::$db->quote($path).' LIKE '.self::$db->concat('lock_path',"'%'").' OR lock_path LIKE '.self::$db->quote($path.'%'); // ToDo: shared locks can return multiple rows - if (($result = self::$db->select(self::LOCK_TABLE,'*',$where,__LINE__,__FILE__)->fetch())) + $results = []; + foreach(self::$db->select(self::LOCK_TABLE,'*',$where,__LINE__,__FILE__) as $result) { - $result = Db::strip_array_keys($result,'lock_'); - $result['type'] = Db::from_bool($result['write']) ? 'write' : 'read'; + $result = Db::strip_array_keys($result, 'lock_'); + $result['type'] = Db::from_bool($result['write']) ? 'write' : 'read'; $result['scope'] = Db::from_bool($result['exclusive']) ? 'exclusive' : 'shared'; $result['depth'] = Db::from_bool($result['recursive']) ? 'infinite' : 0; - } - if ($result && $result['expires'] < time()) // lock is expired --> remove it - { - self::$db->delete(self::LOCK_TABLE,array( - 'lock_path' => $result['path'], - 'lock_token' => $result['token'], - ),__LINE__,__FILE__); + if ($result['expires'] < time()) // lock is expired --> remove it + { + self::$db->delete(self::LOCK_TABLE, array( + 'lock_path' => $result['path'], + 'lock_token' => $result['token'], + ), __LINE__, __FILE__); - if (self::LOCK_DEBUG) error_log(__METHOD__."($url) lock is expired at ".date('Y-m-d H:i:s',$result['expires'])." --> removed"); - $result = false; + if (self::LOCK_DEBUG) error_log(__METHOD__ . "($url) lock is expired at " . date('Y-m-d H:i:s', $result['expires']) . " --> removed"); + $result = false; + } + else + { + if ($result['path'] === $path || str_starts_with($result['path'], $path)) + { + $results[$result['path']] = $result; + } + self::$lock_cache[$result['path']] = $result; + } } - if (self::LOCK_DEBUG) error_log(__METHOD__."($url) returns ".($result?array2string($result):'false')); - return self::$lock_cache[$path] = $result; + if (self::LOCK_DEBUG) error_log(__METHOD__."($url, $depth) returns ".array2string($depth ? $result : ($result ?? false))); + return $depth ? $results : ($result ?? false); } /** diff --git a/filemanager/inc/class.filemanager_ui.inc.php b/filemanager/inc/class.filemanager_ui.inc.php index 92a45c8fee..b4b44a1d4a 100644 --- a/filemanager/inc/class.filemanager_ui.inc.php +++ b/filemanager/inc/class.filemanager_ui.inc.php @@ -1012,6 +1012,13 @@ class filemanager_ui $GLOBALS['egw']->session->commit_session(); $rows = $dir_is_writable = array(); $vfs_options = $this->get_vfs_options($query); + // query and cache locks for whole directory + $locks = []; + foreach(!empty($query['col_filter']['dir']) ? (array)$query['col_filter']['dir'] : (array)$query['path'] as $path) + { + $locks += Vfs::checkLock($path, 999); + } + $n = 0; foreach(Vfs::find(!empty($query['col_filter']['dir']) ? $query['col_filter']['dir'] : $query['path'],$vfs_options,true) as $path => $row) { //echo $path; _debug_array($row); @@ -1043,7 +1050,7 @@ class filemanager_ui { $row['class'] .= 'noEdit '; } - if($lock = Vfs::checkLock($path)) + if (!empty($lock = $locks[$path])) { $row['locked'] = 'lock'; $row['locked_status'] = lang(