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()

This commit is contained in:
Ralf Becker 2021-10-28 21:08:31 +02:00 committed by nathan
parent 75bbd063c6
commit 45437a5c9d
2 changed files with 46 additions and 20 deletions

View File

@ -1,4 +1,5 @@
<?php <?php /** @noinspection ALL */
/** /**
* EGroupware API: VFS - static methods to use the new eGW virtual file system * EGroupware API: VFS - static methods to use the new eGW virtual file system
* *
@ -1662,28 +1663,37 @@ class Vfs extends Vfs\Base
* checkLock() helper * checkLock() helper
* *
* @param string $url url or path, lock is granted for the path only, but url is used for access checks * @param string $url url or path, lock is granted for the path only, but url is used for access checks
* @return array|boolean false if there's no lock, else array with lock info * @param int $depth=0 currently only 0 or >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); $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))); 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]; return self::$lock_cache[$path];
} }
if ($depth > 0)
{
$where = ['lock_path LIKE '.self::$db->quote($path.'%')];
}
else
{
$where = 'lock_path='.self::$db->quote($path); $where = 'lock_path='.self::$db->quote($path);
}
// ToDo: additional check parent dirs for locks and children of the requested directory // 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.'%'); //$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 // 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 = Db::strip_array_keys($result, 'lock_');
$result['type'] = Db::from_bool($result['write']) ? 'write' : 'read'; $result['type'] = Db::from_bool($result['write']) ? 'write' : 'read';
$result['scope'] = Db::from_bool($result['exclusive']) ? 'exclusive' : 'shared'; $result['scope'] = Db::from_bool($result['exclusive']) ? 'exclusive' : 'shared';
$result['depth'] = Db::from_bool($result['recursive']) ? 'infinite' : 0; $result['depth'] = Db::from_bool($result['recursive']) ? 'infinite' : 0;
} if ($result['expires'] < time()) // lock is expired --> remove it
if ($result && $result['expires'] < time()) // lock is expired --> remove it
{ {
self::$db->delete(self::LOCK_TABLE, array( self::$db->delete(self::LOCK_TABLE, array(
'lock_path' => $result['path'], 'lock_path' => $result['path'],
@ -1693,8 +1703,17 @@ class Vfs extends Vfs\Base
if (self::LOCK_DEBUG) error_log(__METHOD__ . "($url) lock is expired at " . date('Y-m-d H:i:s', $result['expires']) . " --> removed"); if (self::LOCK_DEBUG) error_log(__METHOD__ . "($url) lock is expired at " . date('Y-m-d H:i:s', $result['expires']) . " --> removed");
$result = false; $result = false;
} }
if (self::LOCK_DEBUG) error_log(__METHOD__."($url) returns ".($result?array2string($result):'false')); else
return self::$lock_cache[$path] = $result; {
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, $depth) returns ".array2string($depth ? $result : ($result ?? false)));
return $depth ? $results : ($result ?? false);
} }
/** /**

View File

@ -1012,6 +1012,13 @@ class filemanager_ui
$GLOBALS['egw']->session->commit_session(); $GLOBALS['egw']->session->commit_session();
$rows = $dir_is_writable = array(); $rows = $dir_is_writable = array();
$vfs_options = $this->get_vfs_options($query); $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) 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); //echo $path; _debug_array($row);
@ -1043,7 +1050,7 @@ class filemanager_ui
{ {
$row['class'] .= 'noEdit '; $row['class'] .= 'noEdit ';
} }
if($lock = Vfs::checkLock($path)) if (!empty($lock = $locks[$path]))
{ {
$row['locked'] = 'lock'; $row['locked'] = 'lock';
$row['locked_status'] = lang( $row['locked_status'] = lang(