Merge pull request #17765 from nextcloud/filecache-extension
Upload time and Creation time
This commit is contained in:
commit
5320f08cd2
23 changed files with 871 additions and 456 deletions
|
@ -303,6 +303,19 @@ class File extends Node implements IFile {
|
|||
}
|
||||
}
|
||||
|
||||
$fileInfoUpdate = [
|
||||
'upload_time' => time()
|
||||
];
|
||||
|
||||
// allow sync clients to send the creation time along in a header
|
||||
if (isset($this->request->server['HTTP_X_OC_CTIME'])) {
|
||||
$ctime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_CTIME']);
|
||||
$fileInfoUpdate['creation_time'] = $ctime;
|
||||
$this->header('X-OC-CTime: accepted');
|
||||
}
|
||||
|
||||
$this->fileView->putFileInfo($this->path, $fileInfoUpdate);
|
||||
|
||||
if ($view) {
|
||||
$this->emitPostHooks($exists);
|
||||
}
|
||||
|
|
|
@ -70,6 +70,9 @@ class FilesPlugin extends ServerPlugin {
|
|||
const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
|
||||
const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
|
||||
const IS_ENCRYPTED_PROPERTYNAME = '{http://nextcloud.org/ns}is-encrypted';
|
||||
const METADATA_ETAG_PROPERTYNAME = '{http://nextcloud.org/ns}metadata_etag';
|
||||
const UPLOAD_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}upload_time';
|
||||
const CREATION_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}creation_time';
|
||||
const SHARE_NOTE = '{http://nextcloud.org/ns}note';
|
||||
|
||||
/**
|
||||
|
@ -400,6 +403,14 @@ class FilesPlugin extends ServerPlugin {
|
|||
return new ChecksumList($checksum);
|
||||
});
|
||||
|
||||
$propFind->handle(self::CREATION_TIME_PROPERTYNAME, function() use ($node) {
|
||||
return $node->getFileInfo()->getCreationTime();
|
||||
});
|
||||
|
||||
$propFind->handle(self::UPLOAD_TIME_PROPERTYNAME, function() use ($node) {
|
||||
return $node->getFileInfo()->getUploadTime();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
|
||||
|
@ -470,6 +481,13 @@ class FilesPlugin extends ServerPlugin {
|
|||
}
|
||||
return false;
|
||||
});
|
||||
$propPatch->handle(self::CREATION_TIME_PROPERTYNAME, function($time) use ($node) {
|
||||
if (empty($time)) {
|
||||
return false;
|
||||
}
|
||||
$node->setCreationTime((int) $time);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -201,6 +201,14 @@ abstract class Node implements \Sabre\DAV\INode {
|
|||
return $this->fileView->putFileInfo($this->path, array('etag' => $etag));
|
||||
}
|
||||
|
||||
public function setCreationTime(int $time) {
|
||||
return $this->fileView->putFileInfo($this->path, array('creation_time' => $time));
|
||||
}
|
||||
|
||||
public function setUploadTime(int $time) {
|
||||
return $this->fileView->putFileInfo($this->path, array('upload_time' => $time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the node, in bytes
|
||||
*
|
||||
|
|
|
@ -177,4 +177,12 @@ class TrashItem implements ITrashItem {
|
|||
public function getTitle(): string {
|
||||
return $this->getOriginalLocation();
|
||||
}
|
||||
|
||||
public function getCreationTime(): int {
|
||||
return $this->fileInfo->getCreationTime();
|
||||
}
|
||||
|
||||
public function getUploadTime(): int {
|
||||
return $this->fileInfo->getUploadTime();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class Version17000Date20190514105811 extends SimpleMigrationStep {
|
|||
$schema = $schemaClosure();
|
||||
if(!$schema->hasTable('filecache_extended')) {
|
||||
$table = $schema->createTable('filecache_extended');
|
||||
$table->addColumn('fileid', Type::INTEGER, [
|
||||
$table->addColumn('fileid', Type::BIGINT, [
|
||||
'notnull' => true,
|
||||
'length' => 4,
|
||||
'unsigned' => true,
|
||||
|
|
|
@ -866,6 +866,7 @@ return array(
|
|||
'OC\\Files\\Cache\\AbstractCacheEvent' => $baseDir . '/lib/private/Files/Cache/AbstractCacheEvent.php',
|
||||
'OC\\Files\\Cache\\Cache' => $baseDir . '/lib/private/Files/Cache/Cache.php',
|
||||
'OC\\Files\\Cache\\CacheEntry' => $baseDir . '/lib/private/Files/Cache/CacheEntry.php',
|
||||
'OC\\Files\\Cache\\CacheQueryBuilder' => $baseDir . '/lib/private/Files/Cache/CacheQueryBuilder.php',
|
||||
'OC\\Files\\Cache\\FailedCache' => $baseDir . '/lib/private/Files/Cache/FailedCache.php',
|
||||
'OC\\Files\\Cache\\HomeCache' => $baseDir . '/lib/private/Files/Cache/HomeCache.php',
|
||||
'OC\\Files\\Cache\\HomePropagator' => $baseDir . '/lib/private/Files/Cache/HomePropagator.php',
|
||||
|
|
|
@ -895,6 +895,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Files\\Cache\\AbstractCacheEvent' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/AbstractCacheEvent.php',
|
||||
'OC\\Files\\Cache\\Cache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Cache.php',
|
||||
'OC\\Files\\Cache\\CacheEntry' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/CacheEntry.php',
|
||||
'OC\\Files\\Cache\\CacheQueryBuilder' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/CacheQueryBuilder.php',
|
||||
'OC\\Files\\Cache\\FailedCache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/FailedCache.php',
|
||||
'OC\\Files\\Cache\\HomeCache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/HomeCache.php',
|
||||
'OC\\Files\\Cache\\HomePropagator' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/HomePropagator.php',
|
||||
|
|
|
@ -72,9 +72,10 @@ class FunctionBuilder implements IFunctionBuilder {
|
|||
return new QueryFunction($this->helper->quoteColumnName($x) . ' - ' . $this->helper->quoteColumnName($y));
|
||||
}
|
||||
|
||||
public function count($count, $alias = '') {
|
||||
public function count($count = '', $alias = '') {
|
||||
$alias = $alias ? (' AS ' . $this->helper->quoteColumnName($alias)) : '';
|
||||
return new QueryFunction('COUNT(' . $this->helper->quoteColumnName($count) . ')' . $alias);
|
||||
$quotedName = $count === '' ? '*' : $this->helper->quoteColumnName($count);
|
||||
return new QueryFunction('COUNT(' . $quotedName . ')' . $alias);
|
||||
}
|
||||
|
||||
public function max($field) {
|
||||
|
|
|
@ -245,7 +245,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param mixed $value The parameter value.
|
||||
* @param string|null|int $type One of the IQueryBuilder::PARAM_* constants.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function setParameter($key, $value, $type = null) {
|
||||
$this->queryBuilder->setParameter($key, $value, $type);
|
||||
|
@ -270,7 +270,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param array $params The query parameters to set.
|
||||
* @param array $types The query parameters types to set.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function setParameters(array $params, array $types = array()) {
|
||||
$this->queryBuilder->setParameters($params, $types);
|
||||
|
@ -323,7 +323,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param integer $firstResult The first result to return.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function setFirstResult($firstResult) {
|
||||
$this->queryBuilder->setFirstResult($firstResult);
|
||||
|
@ -350,7 +350,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param integer $maxResults The maximum number of results to retrieve.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function setMaxResults($maxResults) {
|
||||
$this->queryBuilder->setMaxResults($maxResults);
|
||||
|
@ -381,7 +381,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$selects The selection expressions.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* '@return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function select(...$selects) {
|
||||
if (count($selects) === 1 && is_array($selects[0])) {
|
||||
|
@ -408,7 +408,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param mixed $select The selection expressions.
|
||||
* @param string $alias The column alias used in the constructed query.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function selectAlias($select, $alias) {
|
||||
|
||||
|
@ -430,7 +430,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed $select The selection expressions.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function selectDistinct($select) {
|
||||
|
||||
|
@ -454,7 +454,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$selects The selection expression.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function addSelect(...$selects) {
|
||||
if (count($selects) === 1 && is_array($selects[0])) {
|
||||
|
@ -482,7 +482,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $delete The table whose rows are subject to the deletion.
|
||||
* @param string $alias The table alias used in the constructed query.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function delete($delete = null, $alias = null) {
|
||||
$this->queryBuilder->delete(
|
||||
|
@ -507,7 +507,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $update The table whose rows are subject to the update.
|
||||
* @param string $alias The table alias used in the constructed query.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function update($update = null, $alias = null) {
|
||||
$this->queryBuilder->update(
|
||||
|
@ -535,7 +535,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param string $insert The table into which the rows should be inserted.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function insert($insert = null) {
|
||||
$this->queryBuilder->insert(
|
||||
|
@ -560,7 +560,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $from The table.
|
||||
* @param string|null $alias The alias of the table.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function from($from, $alias = null) {
|
||||
$this->queryBuilder->from(
|
||||
|
@ -586,7 +586,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function join($fromAlias, $join, $alias, $condition = null) {
|
||||
$this->queryBuilder->join(
|
||||
|
@ -614,7 +614,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function innerJoin($fromAlias, $join, $alias, $condition = null) {
|
||||
$this->queryBuilder->innerJoin(
|
||||
|
@ -642,7 +642,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function leftJoin($fromAlias, $join, $alias, $condition = null) {
|
||||
$this->queryBuilder->leftJoin(
|
||||
|
@ -670,7 +670,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function rightJoin($fromAlias, $join, $alias, $condition = null) {
|
||||
$this->queryBuilder->rightJoin(
|
||||
|
@ -696,7 +696,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $key The column to set.
|
||||
* @param string $value The value, expression, placeholder, etc.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
$this->queryBuilder->set(
|
||||
|
@ -731,7 +731,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$predicates The restriction predicates.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function where(...$predicates) {
|
||||
call_user_func_array(
|
||||
|
@ -756,7 +756,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$where The query restrictions.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*
|
||||
* @see where()
|
||||
*/
|
||||
|
@ -783,7 +783,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$where The WHERE statement.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*
|
||||
* @see where()
|
||||
*/
|
||||
|
@ -809,7 +809,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$groupBys The grouping expression.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function groupBy(...$groupBys) {
|
||||
if (count($groupBys) === 1 && is_array($groupBys[0])) {
|
||||
|
@ -837,7 +837,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$groupBy The grouping expression.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function addGroupBy(...$groupBys) {
|
||||
if (count($groupBys) === 1 && is_array($groupBys[0])) {
|
||||
|
@ -869,7 +869,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $column The column into which the value should be inserted.
|
||||
* @param string $value The value that should be inserted into the column.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function setValue($column, $value) {
|
||||
$this->queryBuilder->setValue(
|
||||
|
@ -897,7 +897,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param array $values The values to specify for the insert query indexed by column names.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function values(array $values) {
|
||||
$quotedValues = [];
|
||||
|
@ -916,7 +916,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$having The restriction over the groups.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function having(...$having) {
|
||||
call_user_func_array(
|
||||
|
@ -933,7 +933,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$having The restriction to append.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function andHaving(...$having) {
|
||||
call_user_func_array(
|
||||
|
@ -950,7 +950,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$having The restriction to add.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function orHaving(...$having) {
|
||||
call_user_func_array(
|
||||
|
@ -968,7 +968,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $sort The ordering expression.
|
||||
* @param string $order The ordering direction.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function orderBy($sort, $order = null) {
|
||||
$this->queryBuilder->orderBy(
|
||||
|
@ -985,7 +985,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
* @param string $sort The ordering expression.
|
||||
* @param string $order The ordering direction.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function addOrderBy($sort, $order = null) {
|
||||
$this->queryBuilder->addOrderBy(
|
||||
|
@ -1021,7 +1021,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param array|null $queryPartNames
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function resetQueryParts($queryPartNames = null) {
|
||||
$this->queryBuilder->resetQueryParts($queryPartNames);
|
||||
|
@ -1034,7 +1034,7 @@ class QueryBuilder implements IQueryBuilder {
|
|||
*
|
||||
* @param string $queryPartName
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*/
|
||||
public function resetQueryPart($queryPartName) {
|
||||
$this->queryBuilder->resetQueryPart($queryPartName);
|
||||
|
|
|
@ -45,6 +45,7 @@ use OCP\Files\Cache\CacheInsertEvent;
|
|||
use OCP\Files\Cache\CacheUpdateEvent;
|
||||
use OCP\Files\Cache\ICache;
|
||||
use OCP\Files\Cache\ICacheEntry;
|
||||
use OCP\Files\FileInfo;
|
||||
use \OCP\Files\IMimeTypeLoader;
|
||||
use OCP\Files\Search\ISearchQuery;
|
||||
use OCP\Files\Storage\IStorage;
|
||||
|
@ -68,7 +69,7 @@ class Cache implements ICache {
|
|||
/**
|
||||
* @var array partial data for the cache
|
||||
*/
|
||||
protected $partial = array();
|
||||
protected $partial = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -112,6 +113,15 @@ class Cache implements ICache {
|
|||
$this->querySearchHelper = new QuerySearchHelper($this->mimetypeLoader);
|
||||
}
|
||||
|
||||
private function getQueryBuilder() {
|
||||
return new CacheQueryBuilder(
|
||||
$this->connection,
|
||||
\OC::$server->getSystemConfig(),
|
||||
\OC::$server->getLogger(),
|
||||
$this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the numeric storage id for this cache's storage
|
||||
*
|
||||
|
@ -128,34 +138,24 @@ class Cache implements ICache {
|
|||
* @return ICacheEntry|false the cache entry as array of false if the file is not found in the cache
|
||||
*/
|
||||
public function get($file) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->selectFileCache();
|
||||
|
||||
if (is_string($file) or $file == '') {
|
||||
// normalize file
|
||||
$file = $this->normalize($file);
|
||||
|
||||
$where = 'WHERE `storage` = ? AND `path_hash` = ?';
|
||||
$params = array($this->getNumericStorageId(), md5($file));
|
||||
$query->whereStorageId()
|
||||
->wherePath($file);
|
||||
} else { //file id
|
||||
$where = 'WHERE `fileid` = ?';
|
||||
$params = array($file);
|
||||
$query->whereFileId($file);
|
||||
}
|
||||
$sql = 'SELECT `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
|
||||
`storage_mtime`, `encrypted`, `etag`, `permissions`, `checksum`
|
||||
FROM `*PREFIX*filecache` ' . $where;
|
||||
$result = $this->connection->executeQuery($sql, $params);
|
||||
$data = $result->fetch();
|
||||
|
||||
//FIXME hide this HACK in the next database layer, or just use doctrine and get rid of MDB2 and PDO
|
||||
//PDO returns false, MDB2 returns null, oracle always uses MDB2, so convert null to false
|
||||
if ($data === null) {
|
||||
$data = false;
|
||||
}
|
||||
$data = $query->execute()->fetch();
|
||||
|
||||
//merge partial data
|
||||
if (!$data and is_string($file)) {
|
||||
if (isset($this->partial[$file])) {
|
||||
$data = $this->partial[$file];
|
||||
}
|
||||
return $data;
|
||||
if (!$data and is_string($file) and isset($this->partial[$file])) {
|
||||
return $this->partial[$file];
|
||||
} else if (!$data) {
|
||||
return $data;
|
||||
} else {
|
||||
|
@ -187,6 +187,12 @@ class Cache implements ICache {
|
|||
$data['storage_mtime'] = $data['mtime'];
|
||||
}
|
||||
$data['permissions'] = (int)$data['permissions'];
|
||||
if (isset($data['creation_time'])) {
|
||||
$data['creation_time'] = (int) $data['creation_time'];
|
||||
}
|
||||
if (isset($data['upload_time'])) {
|
||||
$data['upload_time'] = (int) $data['upload_time'];
|
||||
}
|
||||
return new CacheEntry($data);
|
||||
}
|
||||
|
||||
|
@ -209,11 +215,12 @@ class Cache implements ICache {
|
|||
*/
|
||||
public function getFolderContentsById($fileId) {
|
||||
if ($fileId > -1) {
|
||||
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
|
||||
`storage_mtime`, `encrypted`, `etag`, `permissions`, `checksum`
|
||||
FROM `*PREFIX*filecache` WHERE `parent` = ? ORDER BY `name` ASC';
|
||||
$result = $this->connection->executeQuery($sql, [$fileId]);
|
||||
$files = $result->fetchAll();
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->selectFileCache()
|
||||
->whereParent($fileId)
|
||||
->orderBy('name', 'ASC');
|
||||
|
||||
$files = $query->execute()->fetchAll();
|
||||
return array_map(function (array $data) {
|
||||
return self::cacheEntryFromData($data, $this->mimetypeLoader);
|
||||
}, $files);
|
||||
|
@ -259,7 +266,7 @@ class Cache implements ICache {
|
|||
unset($this->partial[$file]);
|
||||
}
|
||||
|
||||
$requiredFields = array('size', 'mtime', 'mimetype');
|
||||
$requiredFields = ['size', 'mtime', 'mimetype'];
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!isset($data[$field])) { //data not complete save as partial and return
|
||||
$this->partial[$file] = $data;
|
||||
|
@ -271,14 +278,8 @@ class Cache implements ICache {
|
|||
$data['parent'] = $this->getParentId($file);
|
||||
$data['name'] = basename($file);
|
||||
|
||||
list($queryParts, $params) = $this->buildParts($data);
|
||||
$queryParts[] = '`storage`';
|
||||
$params[] = $this->getNumericStorageId();
|
||||
|
||||
$queryParts = array_map(function ($item) {
|
||||
return trim($item, "`");
|
||||
}, $queryParts);
|
||||
$values = array_combine($queryParts, $params);
|
||||
[$values, $extensionValues] = $this->normalizeData($data);
|
||||
$values['storage'] = $this->getNumericStorageId();
|
||||
|
||||
try {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
@ -289,7 +290,19 @@ class Cache implements ICache {
|
|||
}
|
||||
|
||||
if ($builder->execute()) {
|
||||
$fileId = (int)$this->connection->lastInsertId('*PREFIX*filecache');
|
||||
$fileId = $builder->getLastInsertId();
|
||||
|
||||
if (count($extensionValues)) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->insert('filecache_extended');
|
||||
|
||||
$query->setValue('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT));
|
||||
foreach ($extensionValues as $column => $value) {
|
||||
$query->setValue($column, $query->createNamedParameter($value));
|
||||
}
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
$this->eventDispatcher->dispatch(CacheInsertEvent::class, new CacheInsertEvent($this->storage, $file, $fileId));
|
||||
return $fileId;
|
||||
}
|
||||
|
@ -324,20 +337,56 @@ class Cache implements ICache {
|
|||
$data['name'] = $this->normalize($data['name']);
|
||||
}
|
||||
|
||||
list($queryParts, $params) = $this->buildParts($data);
|
||||
// duplicate $params because we need the parts twice in the SQL statement
|
||||
// once for the SET part, once in the WHERE clause
|
||||
$params = array_merge($params, $params);
|
||||
$params[] = $id;
|
||||
[$values, $extensionValues] = $this->normalizeData($data);
|
||||
|
||||
// don't update if the data we try to set is the same as the one in the record
|
||||
// some databases (Postgres) don't like superfluous updates
|
||||
$sql = 'UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? ' .
|
||||
'WHERE (' .
|
||||
implode(' <> ? OR ', $queryParts) . ' <> ? OR ' .
|
||||
implode(' IS NULL OR ', $queryParts) . ' IS NULL' .
|
||||
') AND `fileid` = ? ';
|
||||
$this->connection->executeQuery($sql, $params);
|
||||
if (count($values)) {
|
||||
$query = $this->getQueryBuilder();
|
||||
|
||||
$query->update('filecache')
|
||||
->whereFileId($id)
|
||||
->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
|
||||
return $query->expr()->orX(
|
||||
$query->expr()->neq($key, $query->createNamedParameter($value)),
|
||||
$query->expr()->isNull($key)
|
||||
);
|
||||
}, array_keys($values), array_values($values))));
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$query->set($key, $query->createNamedParameter($value));
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
if (count($extensionValues)) {
|
||||
try {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->insert('filecache_extended');
|
||||
|
||||
$query->setValue('fileid', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT));
|
||||
foreach ($extensionValues as $column => $value) {
|
||||
$query->setValue($column, $query->createNamedParameter($value));
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->update('filecache_extended')
|
||||
->whereFileId($id)
|
||||
->andWhere($query->expr()->orX(...array_map(function ($key, $value) use ($query) {
|
||||
return $query->expr()->orX(
|
||||
$query->expr()->neq($key, $query->createNamedParameter($value)),
|
||||
$query->expr()->isNull($key)
|
||||
);
|
||||
}, array_keys($extensionValues), array_values($extensionValues))));
|
||||
|
||||
foreach ($extensionValues as $key => $value) {
|
||||
$query->set($key, $query->createNamedParameter($value));
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$path = $this->getPathById($id);
|
||||
// path can still be null if the file doesn't exist
|
||||
|
@ -350,14 +399,13 @@ class Cache implements ICache {
|
|||
* extract query parts and params array from data array
|
||||
*
|
||||
* @param array $data
|
||||
* @return array [$queryParts, $params]
|
||||
* $queryParts: string[], the (escaped) column names to be set in the query
|
||||
* $params: mixed[], the new values for the columns, to be passed as params to the query
|
||||
* @return array
|
||||
*/
|
||||
protected function buildParts(array $data) {
|
||||
$fields = array(
|
||||
protected function normalizeData(array $data): array {
|
||||
$fields = [
|
||||
'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted',
|
||||
'etag', 'permissions', 'checksum', 'storage');
|
||||
'etag', 'permissions', 'checksum', 'storage'];
|
||||
$extensionFields = ['metadata_etag', 'creation_time', 'upload_time'];
|
||||
|
||||
$doNotCopyStorageMTime = false;
|
||||
if (array_key_exists('mtime', $data) && $data['mtime'] === null) {
|
||||
|
@ -366,23 +414,20 @@ class Cache implements ICache {
|
|||
$doNotCopyStorageMTime = true;
|
||||
}
|
||||
|
||||
$params = array();
|
||||
$queryParts = array();
|
||||
$params = [];
|
||||
$extensionParams = [];
|
||||
foreach ($data as $name => $value) {
|
||||
if (array_search($name, $fields) !== false) {
|
||||
if ($name === 'path') {
|
||||
$params[] = md5($value);
|
||||
$queryParts[] = '`path_hash`';
|
||||
} elseif ($name === 'mimetype') {
|
||||
$params[] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/')));
|
||||
$queryParts[] = '`mimepart`';
|
||||
$params['path_hash'] = md5($value);
|
||||
} else if ($name === 'mimetype') {
|
||||
$params['mimepart'] = $this->mimetypeLoader->getId(substr($value, 0, strpos($value, '/')));
|
||||
$value = $this->mimetypeLoader->getId($value);
|
||||
} elseif ($name === 'storage_mtime') {
|
||||
} else if ($name === 'storage_mtime') {
|
||||
if (!$doNotCopyStorageMTime && !isset($data['mtime'])) {
|
||||
$params[] = $value;
|
||||
$queryParts[] = '`mtime`';
|
||||
$params['mtime'] = $value;
|
||||
}
|
||||
} elseif ($name === 'encrypted') {
|
||||
} else if ($name === 'encrypted') {
|
||||
if (isset($data['encryptedVersion'])) {
|
||||
$value = $data['encryptedVersion'];
|
||||
} else {
|
||||
|
@ -390,11 +435,13 @@ class Cache implements ICache {
|
|||
$value = $value ? 1 : 0;
|
||||
}
|
||||
}
|
||||
$params[] = $value;
|
||||
$queryParts[] = '`' . $name . '`';
|
||||
$params[$name] = $value;
|
||||
}
|
||||
if (array_search($name, $extensionFields) !== false) {
|
||||
$extensionParams[$name] = $value;
|
||||
}
|
||||
}
|
||||
return array($queryParts, $params);
|
||||
return [$params, array_filter($extensionParams)];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,15 +458,14 @@ class Cache implements ICache {
|
|||
// normalize file
|
||||
$file = $this->normalize($file);
|
||||
|
||||
$pathHash = md5($file);
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select('fileid')
|
||||
->from('filecache')
|
||||
->whereStorageId()
|
||||
->wherePath($file);
|
||||
|
||||
$sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?';
|
||||
$result = $this->connection->executeQuery($sql, array($this->getNumericStorageId(), $pathHash));
|
||||
if ($row = $result->fetch()) {
|
||||
return (int)$row['fileid'];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
$id = $query->execute()->fetchColumn();
|
||||
return $id === false ? -1 : (int)$id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -464,39 +510,64 @@ class Cache implements ICache {
|
|||
*/
|
||||
public function remove($file) {
|
||||
$entry = $this->get($file);
|
||||
$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
|
||||
$this->connection->executeQuery($sql, array($entry['fileid']));
|
||||
if ($entry['mimetype'] === 'httpd/unix-directory') {
|
||||
$this->removeChildren($entry);
|
||||
|
||||
if ($entry) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache')
|
||||
->whereFileId($entry->getId());
|
||||
$query->execute();
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache_extended')
|
||||
->whereFileId($entry->getId());
|
||||
$query->execute();
|
||||
|
||||
if ($entry->getMimeType() == FileInfo::MIMETYPE_FOLDER) {
|
||||
$this->removeChildren($entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all sub folders of a folder
|
||||
*
|
||||
* @param array $entry the cache entry of the folder to get the subfolders for
|
||||
* @return array[] the cache entries for the subfolders
|
||||
* @param ICacheEntry $entry the cache entry of the folder to get the subfolders for
|
||||
* @return ICacheEntry[] the cache entries for the subfolders
|
||||
*/
|
||||
private function getSubFolders($entry) {
|
||||
$children = $this->getFolderContentsById($entry['fileid']);
|
||||
private function getSubFolders(ICacheEntry $entry) {
|
||||
$children = $this->getFolderContentsById($entry->getId());
|
||||
return array_filter($children, function ($child) {
|
||||
return $child['mimetype'] === 'httpd/unix-directory';
|
||||
return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively remove all children of a folder
|
||||
*
|
||||
* @param array $entry the cache entry of the folder to remove the children of
|
||||
* @param ICacheEntry $entry the cache entry of the folder to remove the children of
|
||||
* @throws \OC\DatabaseException
|
||||
*/
|
||||
private function removeChildren($entry) {
|
||||
$subFolders = $this->getSubFolders($entry);
|
||||
foreach ($subFolders as $folder) {
|
||||
private function removeChildren(ICacheEntry $entry) {
|
||||
$children = $this->getFolderContentsById($entry->getId());
|
||||
$childIds = array_map(function(ICacheEntry $cacheEntry) {
|
||||
return $cacheEntry->getId();
|
||||
}, $children);
|
||||
$childFolders = array_filter($children, function ($child) {
|
||||
return $child->getMimeType() == FileInfo::MIMETYPE_FOLDER;
|
||||
});
|
||||
foreach ($childFolders as $folder) {
|
||||
$this->removeChildren($folder);
|
||||
}
|
||||
$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `parent` = ?';
|
||||
$this->connection->executeQuery($sql, array($entry['fileid']));
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache')
|
||||
->whereParent($entry->getId());
|
||||
$query->execute();
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache_extended')
|
||||
->where($query->expr()->in('fileid', $query->createNamedParameter($childIds, IQueryBuilder::PARAM_INT_ARRAY)));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -575,8 +646,16 @@ class Cache implements ICache {
|
|||
}
|
||||
}
|
||||
|
||||
$sql = 'UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` = ? WHERE `fileid` = ?';
|
||||
$this->connection->executeQuery($sql, array($targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId));
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->update('filecache')
|
||||
->set('storage', $query->createNamedParameter($targetStorageId))
|
||||
->set('path', $query->createNamedParameter($targetPath))
|
||||
->set('path_hash', $query->createNamedParameter(md5($targetPath)))
|
||||
->set('name', $query->createNamedParameter(basename($targetPath)))
|
||||
->set('parent', $query->createNamedParameter($newParentId, IQueryBuilder::PARAM_INT))
|
||||
->whereFileId($sourceId);
|
||||
$query->execute();
|
||||
|
||||
$this->connection->commit();
|
||||
} else {
|
||||
$this->moveFromCacheFallback($sourceCache, $sourcePath, $targetPath);
|
||||
|
@ -587,11 +666,15 @@ class Cache implements ICache {
|
|||
* remove all entries for files that are stored on the storage from the cache
|
||||
*/
|
||||
public function clear() {
|
||||
$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `storage` = ?';
|
||||
$this->connection->executeQuery($sql, array($this->getNumericStorageId()));
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->delete('filecache')
|
||||
->whereStorageId();
|
||||
$query->execute();
|
||||
|
||||
$sql = 'DELETE FROM `*PREFIX*storages` WHERE `id` = ?';
|
||||
$this->connection->executeQuery($sql, array($this->storageId));
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->delete('storages')
|
||||
->where($query->expr()->eq('id', $query->createNamedParameter($this->storageId)));
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -610,11 +693,14 @@ class Cache implements ICache {
|
|||
// normalize file
|
||||
$file = $this->normalize($file);
|
||||
|
||||
$pathHash = md5($file);
|
||||
$sql = 'SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?';
|
||||
$result = $this->connection->executeQuery($sql, array($this->getNumericStorageId(), $pathHash));
|
||||
if ($row = $result->fetch()) {
|
||||
if ((int)$row['size'] === -1) {
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select('size')
|
||||
->from('filecache')
|
||||
->whereStorageId()
|
||||
->wherePath($file);
|
||||
$size = $query->execute()->fetchColumn();
|
||||
if ($size !== false) {
|
||||
if ((int)$size === -1) {
|
||||
return self::SHALLOW;
|
||||
} else {
|
||||
return self::COMPLETE;
|
||||
|
@ -642,18 +728,14 @@ class Cache implements ICache {
|
|||
return [];
|
||||
}
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->selectFileCache()
|
||||
->whereStorageId()
|
||||
->andWhere($query->expr()->iLike('name', $query->createNamedParameter($pattern)));
|
||||
|
||||
$sql = '
|
||||
SELECT `fileid`, `storage`, `path`, `parent`, `name`,
|
||||
`mimetype`, `storage_mtime`, `mimepart`, `size`, `mtime`,
|
||||
`encrypted`, `etag`, `permissions`, `checksum`
|
||||
FROM `*PREFIX*filecache`
|
||||
WHERE `storage` = ? AND `name` ILIKE ?';
|
||||
$result = $this->connection->executeQuery($sql,
|
||||
[$this->getNumericStorageId(), $pattern]
|
||||
);
|
||||
|
||||
return $this->searchResultToCacheEntries($result);
|
||||
return array_map(function (array $data) {
|
||||
return self::cacheEntryFromData($data, $this->mimetypeLoader);
|
||||
}, $query->execute()->fetchAll());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -676,26 +758,29 @@ class Cache implements ICache {
|
|||
* @return ICacheEntry[] an array of cache entries where the mimetype matches the search
|
||||
*/
|
||||
public function searchByMime($mimetype) {
|
||||
if (strpos($mimetype, '/')) {
|
||||
$where = '`mimetype` = ?';
|
||||
} else {
|
||||
$where = '`mimepart` = ?';
|
||||
}
|
||||
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `storage_mtime`, `mtime`, `encrypted`, `etag`, `permissions`, `checksum`
|
||||
FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?';
|
||||
$mimetype = $this->mimetypeLoader->getId($mimetype);
|
||||
$result = $this->connection->executeQuery($sql, array($mimetype, $this->getNumericStorageId()));
|
||||
$mimeId = $this->mimetypeLoader->getId($mimetype);
|
||||
|
||||
return $this->searchResultToCacheEntries($result);
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->selectFileCache()
|
||||
->whereStorageId();
|
||||
|
||||
if (strpos($mimetype, '/')) {
|
||||
$query->andWhere($query->expr()->eq('mimetype', $query->createNamedParameter($mimeId, IQueryBuilder::PARAM_INT)));
|
||||
} else {
|
||||
$query->andWhere($query->expr()->eq('mimepart', $query->createNamedParameter($mimeId, IQueryBuilder::PARAM_INT)));
|
||||
}
|
||||
|
||||
return array_map(function (array $data) {
|
||||
return self::cacheEntryFromData($data, $this->mimetypeLoader);
|
||||
}, $query->execute()->fetchAll());
|
||||
}
|
||||
|
||||
public function searchQuery(ISearchQuery $searchQuery) {
|
||||
$builder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
|
||||
$builder = $this->getQueryBuilder();
|
||||
|
||||
$query = $builder->select(['fileid', 'storage', 'path', 'parent', 'name', 'mimetype', 'mimepart', 'size', 'mtime', 'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum'])
|
||||
->from('filecache', 'file');
|
||||
$query = $builder->selectFileCache('file');
|
||||
|
||||
$query->where($builder->expr()->eq('storage', $builder->createNamedParameter($this->getNumericStorageId())));
|
||||
$query->whereStorageId();
|
||||
|
||||
if ($this->querySearchHelper->shouldJoinTags($searchQuery->getSearchOperation())) {
|
||||
$query
|
||||
|
@ -755,10 +840,13 @@ class Cache implements ICache {
|
|||
*/
|
||||
public function getIncompleteChildrenCount($fileId) {
|
||||
if ($fileId > -1) {
|
||||
$sql = 'SELECT count(*)
|
||||
FROM `*PREFIX*filecache` WHERE `parent` = ? AND size = -1';
|
||||
$result = $this->connection->executeQuery($sql, [$fileId]);
|
||||
return (int)$result->fetchColumn();
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select($query->func()->count())
|
||||
->from('filecache')
|
||||
->whereParent($fileId)
|
||||
->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return (int)$query->execute()->fetchColumn();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -775,14 +863,17 @@ class Cache implements ICache {
|
|||
if (is_null($entry) or !isset($entry['fileid'])) {
|
||||
$entry = $this->get($path);
|
||||
}
|
||||
if (isset($entry['mimetype']) && $entry['mimetype'] === 'httpd/unix-directory') {
|
||||
if (isset($entry['mimetype']) && $entry['mimetype'] === FileInfo::MIMETYPE_FOLDER) {
|
||||
$id = $entry['fileid'];
|
||||
$sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 ' .
|
||||
'FROM `*PREFIX*filecache` ' .
|
||||
'WHERE `parent` = ? AND `storage` = ?';
|
||||
$result = $this->connection->executeQuery($sql, array($id, $this->getNumericStorageId()));
|
||||
if ($row = $result->fetch()) {
|
||||
$result->closeCursor();
|
||||
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->selectAlias($query->func()->sum('size'), 'f1')
|
||||
->selectAlias($query->func()->min('size'), 'f2')
|
||||
->from('filecache')
|
||||
->whereStorageId()
|
||||
->whereParent($id);
|
||||
|
||||
if ($row = $query->execute()->fetch()) {
|
||||
list($sum, $min) = array_values($row);
|
||||
$sum = 0 + $sum;
|
||||
$min = 0 + $min;
|
||||
|
@ -791,15 +882,9 @@ class Cache implements ICache {
|
|||
} else {
|
||||
$totalSize = $sum;
|
||||
}
|
||||
$update = array();
|
||||
if ($entry['size'] !== $totalSize) {
|
||||
$update['size'] = $totalSize;
|
||||
$this->update($id, ['size' => $totalSize]);
|
||||
}
|
||||
if (count($update) > 0) {
|
||||
$this->update($id, $update);
|
||||
}
|
||||
} else {
|
||||
$result->closeCursor();
|
||||
}
|
||||
}
|
||||
return $totalSize;
|
||||
|
@ -811,13 +896,14 @@ class Cache implements ICache {
|
|||
* @return int[]
|
||||
*/
|
||||
public function getAll() {
|
||||
$sql = 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?';
|
||||
$result = $this->connection->executeQuery($sql, array($this->getNumericStorageId()));
|
||||
$ids = array();
|
||||
while ($row = $result->fetch()) {
|
||||
$ids[] = $row['fileid'];
|
||||
}
|
||||
return $ids;
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select('fileid')
|
||||
->from('filecache')
|
||||
->whereStorageId();
|
||||
|
||||
return array_map(function ($id) {
|
||||
return (int)$id;
|
||||
}, $query->execute()->fetchAll(\PDO::FETCH_COLUMN));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -830,14 +916,14 @@ class Cache implements ICache {
|
|||
* @return string|bool the path of the folder or false when no folder matched
|
||||
*/
|
||||
public function getIncomplete() {
|
||||
$query = $this->connection->prepare('SELECT `path` FROM `*PREFIX*filecache`'
|
||||
. ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC', 1);
|
||||
$query->execute([$this->getNumericStorageId()]);
|
||||
if ($row = $query->fetch()) {
|
||||
return $row['path'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select('path')
|
||||
->from('filecache')
|
||||
->whereStorageId()
|
||||
->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
|
||||
->orderBy('fileid', 'DESC');
|
||||
|
||||
return $query->execute()->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -847,17 +933,14 @@ class Cache implements ICache {
|
|||
* @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache
|
||||
*/
|
||||
public function getPathById($id) {
|
||||
$sql = 'SELECT `path` FROM `*PREFIX*filecache` WHERE `fileid` = ? AND `storage` = ?';
|
||||
$result = $this->connection->executeQuery($sql, array($id, $this->getNumericStorageId()));
|
||||
if ($row = $result->fetch()) {
|
||||
// Oracle stores empty strings as null...
|
||||
if ($row['path'] === null) {
|
||||
return '';
|
||||
}
|
||||
return $row['path'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
$query = $this->getQueryBuilder();
|
||||
$query->select('path')
|
||||
->from('filecache')
|
||||
->whereStorageId()
|
||||
->whereFileId($id);
|
||||
|
||||
$path = $query->execute()->fetchColumn();
|
||||
return $path === false ? null : $path;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -866,14 +949,15 @@ class Cache implements ICache {
|
|||
* instead does a global search in the cache table
|
||||
*
|
||||
* @param int $id
|
||||
* @deprecated use getPathById() instead
|
||||
* @return array first element holding the storage id, second the path
|
||||
* @deprecated use getPathById() instead
|
||||
*/
|
||||
static public function getById($id) {
|
||||
$connection = \OC::$server->getDatabaseConnection();
|
||||
$sql = 'SELECT `storage`, `path` FROM `*PREFIX*filecache` WHERE `fileid` = ?';
|
||||
$result = $connection->executeQuery($sql, array($id));
|
||||
if ($row = $result->fetch()) {
|
||||
$query = \OC::$server->getDatabaseConnection()->getQueryBuilder();
|
||||
$query->select('path', 'storage')
|
||||
->from('filecache')
|
||||
->where($query->expr()->eq('fileid', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
|
||||
if ($row = $query->execute()->fetch()) {
|
||||
$numericId = $row['storage'];
|
||||
$path = $row['path'];
|
||||
} else {
|
||||
|
@ -881,7 +965,7 @@ class Cache implements ICache {
|
|||
}
|
||||
|
||||
if ($id = Storage::getStorageId($numericId)) {
|
||||
return array($id, $path);
|
||||
return [$id, $path];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,18 @@ class CacheEntry implements ICacheEntry, \ArrayAccess {
|
|||
return isset($this->data['encrypted']) && $this->data['encrypted'];
|
||||
}
|
||||
|
||||
public function getMetadataEtag(): ?string {
|
||||
return $this->data['metadata_etag'];
|
||||
}
|
||||
|
||||
public function getCreationTime(): ?int {
|
||||
return $this->data['creation_time'];
|
||||
}
|
||||
|
||||
public function getUploadTime(): ?int {
|
||||
return $this->data['upload_time'];
|
||||
}
|
||||
|
||||
public function getData() {
|
||||
return $this->data;
|
||||
}
|
||||
|
|
92
lib/private/Files/Cache/CacheQueryBuilder.php
Normal file
92
lib/private/Files/Cache/CacheQueryBuilder.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Files\Cache;
|
||||
|
||||
use OC\DB\QueryBuilder\QueryBuilder;
|
||||
use OC\SystemConfig;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\ILogger;
|
||||
|
||||
/**
|
||||
* Query builder with commonly used helpers for filecache queries
|
||||
*/
|
||||
class CacheQueryBuilder extends QueryBuilder {
|
||||
private $cache;
|
||||
private $alias = null;
|
||||
|
||||
public function __construct(IDBConnection $connection, SystemConfig $systemConfig, ILogger $logger, Cache $cache) {
|
||||
parent::__construct($connection, $systemConfig, $logger);
|
||||
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
public function selectFileCache(string $alias = null) {
|
||||
$name = $alias ? $alias : 'filecache';
|
||||
$this->select("$name.fileid", 'storage', 'path', 'path_hash', "$name.parent", 'name', 'mimetype', 'mimepart', 'size', 'mtime',
|
||||
'storage_mtime', 'encrypted', 'etag', 'permissions', 'checksum', 'metadata_etag', 'creation_time', 'upload_time')
|
||||
->from('filecache', $name)
|
||||
->leftJoin($name, 'filecache_extended', 'fe', $this->expr()->eq("$name.fileid", 'fe.fileid'));
|
||||
|
||||
$this->alias = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereStorageId() {
|
||||
$this->andWhere($this->expr()->eq('storage', $this->createNamedParameter($this->cache->getNumericStorageId(), IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereFileId(int $fileId) {
|
||||
$alias = $this->alias;
|
||||
if ($alias) {
|
||||
$alias .= '.';
|
||||
} else {
|
||||
$alias = '';
|
||||
}
|
||||
|
||||
$this->andWhere($this->expr()->eq("{$alias}fileid", $this->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function wherePath(string $path) {
|
||||
$this->andWhere($this->expr()->eq('path_hash', $this->createNamedParameter(md5($path))));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function whereParent(int $parent) {
|
||||
$alias = $this->alias;
|
||||
if ($alias) {
|
||||
$alias .= '.';
|
||||
} else {
|
||||
$alias = '';
|
||||
}
|
||||
|
||||
$this->andWhere($this->expr()->eq("{$alias}parent", $this->createNamedParameter($parent, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -82,7 +82,10 @@ trait MoveFromCacheTrait {
|
|||
'mimepart' => $entry->getMimePart(),
|
||||
'etag' => $entry->getEtag(),
|
||||
'permissions' => $entry->getPermissions(),
|
||||
'encrypted' => $entry->isEncrypted()
|
||||
'encrypted' => $entry->isEncrypted(),
|
||||
'creation_time' => $entry->getCreationTime(),
|
||||
'upload_time' => $entry->getUploadTime(),
|
||||
'metadata_etag' => $entry->getMetadataEtag(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -406,4 +406,12 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
|
|||
public function getExtension(): string {
|
||||
return pathinfo($this->getName(), PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
public function getCreationTime(): int {
|
||||
return (int) $this->data['creation_time'];
|
||||
}
|
||||
|
||||
public function getUploadTime(): int {
|
||||
return (int) $this->data['upload_time'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -480,4 +480,18 @@ class LazyRoot implements IRootFolder {
|
|||
public function getRecent($limit, $offset = 0) {
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getCreationTime(): int {
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getUploadTime(): int {
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -444,4 +444,12 @@ class Node implements \OCP\Files\Node {
|
|||
}
|
||||
}
|
||||
|
||||
public function getCreationTime(): int {
|
||||
return $this->getFileInfo()->getCreationTime();
|
||||
}
|
||||
|
||||
public function getUploadTime(): int {
|
||||
return $this->getFileInfo()->getUploadTime();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ interface IFunctionBuilder {
|
|||
* @return IQueryFunction
|
||||
* @since 14.0.0
|
||||
*/
|
||||
public function count($count, $alias = '');
|
||||
public function count($count = '', $alias = '');
|
||||
|
||||
/**
|
||||
* Takes the maximum of all rows in a column
|
||||
|
|
|
@ -180,7 +180,7 @@ interface IQueryBuilder {
|
|||
* @param mixed $value The parameter value.
|
||||
* @param string|null|int $type One of the IQueryBuilder::PARAM_* constants.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function setParameter($key, $value, $type = null);
|
||||
|
@ -202,7 +202,7 @@ interface IQueryBuilder {
|
|||
* @param array $params The query parameters to set.
|
||||
* @param array $types The query parameters types to set.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function setParameters(array $params, array $types = array());
|
||||
|
@ -248,7 +248,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param integer $firstResult The first result to return.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function setFirstResult($firstResult);
|
||||
|
@ -267,7 +267,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param integer $maxResults The maximum number of results to retrieve.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function setMaxResults($maxResults);
|
||||
|
@ -294,7 +294,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$selects The selection expressions.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function select(...$selects);
|
||||
|
@ -312,7 +312,7 @@ interface IQueryBuilder {
|
|||
* @param mixed $select The selection expressions.
|
||||
* @param string $alias The column alias used in the constructed query.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.1
|
||||
*/
|
||||
public function selectAlias($select, $alias);
|
||||
|
@ -328,7 +328,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed $select The selection expressions.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 9.0.0
|
||||
*/
|
||||
public function selectDistinct($select);
|
||||
|
@ -346,7 +346,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$select The selection expression.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function addSelect(...$select);
|
||||
|
@ -365,7 +365,7 @@ interface IQueryBuilder {
|
|||
* @param string $delete The table whose rows are subject to the deletion.
|
||||
* @param string $alias The table alias used in the constructed query.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function delete($delete = null, $alias = null);
|
||||
|
@ -384,7 +384,7 @@ interface IQueryBuilder {
|
|||
* @param string $update The table whose rows are subject to the update.
|
||||
* @param string $alias The table alias used in the constructed query.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function update($update = null, $alias = null);
|
||||
|
@ -406,7 +406,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param string $insert The table into which the rows should be inserted.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function insert($insert = null);
|
||||
|
@ -424,7 +424,7 @@ interface IQueryBuilder {
|
|||
* @param string $from The table.
|
||||
* @param string|null $alias The alias of the table.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function from($from, $alias = null);
|
||||
|
@ -444,7 +444,7 @@ interface IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function join($fromAlias, $join, $alias, $condition = null);
|
||||
|
@ -464,7 +464,7 @@ interface IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function innerJoin($fromAlias, $join, $alias, $condition = null);
|
||||
|
@ -484,7 +484,7 @@ interface IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function leftJoin($fromAlias, $join, $alias, $condition = null);
|
||||
|
@ -504,7 +504,7 @@ interface IQueryBuilder {
|
|||
* @param string $alias The alias of the join table.
|
||||
* @param string $condition The condition for the join.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function rightJoin($fromAlias, $join, $alias, $condition = null);
|
||||
|
@ -522,7 +522,7 @@ interface IQueryBuilder {
|
|||
* @param string $key The column to set.
|
||||
* @param string $value The value, expression, placeholder, etc.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function set($key, $value);
|
||||
|
@ -551,7 +551,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed $predicates The restriction predicates.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function where(...$predicates);
|
||||
|
@ -570,7 +570,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$where The query restrictions.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*
|
||||
* @see where()
|
||||
* @since 8.2.0
|
||||
|
@ -591,7 +591,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$where The WHERE statement.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
*
|
||||
* @see where()
|
||||
* @since 8.2.0
|
||||
|
@ -611,7 +611,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$groupBys The grouping expression.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function groupBy(...$groupBys);
|
||||
|
@ -629,7 +629,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$groupBy The grouping expression.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function addGroupBy(...$groupBy);
|
||||
|
@ -651,7 +651,7 @@ interface IQueryBuilder {
|
|||
* @param string $column The column into which the value should be inserted.
|
||||
* @param string $value The value that should be inserted into the column.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function setValue($column, $value);
|
||||
|
@ -673,7 +673,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param array $values The values to specify for the insert query indexed by column names.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function values(array $values);
|
||||
|
@ -684,7 +684,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$having The restriction over the groups.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function having(...$having);
|
||||
|
@ -695,7 +695,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$having The restriction to append.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function andHaving(...$having);
|
||||
|
@ -706,7 +706,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param mixed ...$having The restriction to add.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function orHaving(...$having);
|
||||
|
@ -718,7 +718,7 @@ interface IQueryBuilder {
|
|||
* @param string $sort The ordering expression.
|
||||
* @param string $order The ordering direction.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function orderBy($sort, $order = null);
|
||||
|
@ -729,7 +729,7 @@ interface IQueryBuilder {
|
|||
* @param string $sort The ordering expression.
|
||||
* @param string $order The ordering direction.
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function addOrderBy($sort, $order = null);
|
||||
|
@ -757,7 +757,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param array|null $queryPartNames
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function resetQueryParts($queryPartNames = null);
|
||||
|
@ -767,7 +767,7 @@ interface IQueryBuilder {
|
|||
*
|
||||
* @param string $queryPartName
|
||||
*
|
||||
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
|
||||
* @return $this This QueryBuilder instance.
|
||||
* @since 8.2.0
|
||||
*/
|
||||
public function resetQueryPart($queryPartName);
|
||||
|
|
|
@ -132,4 +132,28 @@ interface ICacheEntry {
|
|||
* @since 9.0.0
|
||||
*/
|
||||
public function isEncrypted();
|
||||
|
||||
/**
|
||||
* Get the metadata etag for the file
|
||||
*
|
||||
* @return string | null
|
||||
* @since 18.0.0
|
||||
*/
|
||||
public function getMetadataEtag(): ?string;
|
||||
|
||||
/**
|
||||
* Get the last modified date as unix timestamp
|
||||
*
|
||||
* @return int | null
|
||||
* @since 18.0.0
|
||||
*/
|
||||
public function getCreationTime(): ?int;
|
||||
|
||||
/**
|
||||
* Get the last modified date as unix timestamp
|
||||
*
|
||||
* @return int | null
|
||||
* @since 18.0.0
|
||||
*/
|
||||
public function getUploadTime(): ?int;
|
||||
}
|
||||
|
|
|
@ -268,4 +268,30 @@ interface FileInfo {
|
|||
* @since 15.0.0
|
||||
*/
|
||||
public function getExtension(): string;
|
||||
|
||||
/**
|
||||
* Get the creation date as unix timestamp
|
||||
*
|
||||
* If the creation time is not known, 0 will be returned
|
||||
*
|
||||
* creation time is not set automatically by the server and is generally only available
|
||||
* for files uploaded by the sync clients
|
||||
*
|
||||
* @return int
|
||||
* @since 18.0.0
|
||||
*/
|
||||
public function getCreationTime(): int;
|
||||
|
||||
/**
|
||||
* Get the upload date as unix timestamp
|
||||
*
|
||||
* If the upload time is not known, 0 will be returned
|
||||
*
|
||||
* Upload time will be set automatically by the server for files uploaded over DAV
|
||||
* files created by Nextcloud apps generally do not have an the upload time set
|
||||
*
|
||||
* @return int
|
||||
* @since 18.0.0
|
||||
*/
|
||||
public function getUploadTime(): int;
|
||||
}
|
||||
|
|
|
@ -707,6 +707,76 @@ class CacheTest extends \Test\TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public function testExtended() {
|
||||
$folderData = ['size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'];
|
||||
$this->cache->put("", $folderData);
|
||||
|
||||
$data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'creation_time' => 20];
|
||||
$id1 = $this->cache->put("foo1", $data);
|
||||
$data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'upload_time' => 30];
|
||||
$this->cache->put("foo2", $data);
|
||||
$data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'metadata_etag' => 'foo'];
|
||||
$this->cache->put("foo3", $data);
|
||||
$data = ['size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain'];
|
||||
$id4 = $this->cache->put("foo4", $data);
|
||||
|
||||
$entry = $this->cache->get($id1);
|
||||
$this->assertEquals(20, $entry->getCreationTime());
|
||||
$this->assertEquals(0, $entry->getUploadTime());
|
||||
$this->assertEquals(null, $entry->getMetadataEtag());
|
||||
|
||||
$entries = $this->cache->getFolderContents("");
|
||||
$this->assertCount(4, $entries);
|
||||
|
||||
$this->assertEquals("foo1", $entries[0]->getName());
|
||||
$this->assertEquals("foo2", $entries[1]->getName());
|
||||
$this->assertEquals("foo3", $entries[2]->getName());
|
||||
$this->assertEquals("foo4", $entries[3]->getName());
|
||||
|
||||
$this->assertEquals(20, $entries[0]->getCreationTime());
|
||||
$this->assertEquals(0, $entries[0]->getUploadTime());
|
||||
$this->assertEquals(null, $entries[0]->getMetadataEtag());
|
||||
|
||||
$this->assertEquals(0, $entries[1]->getCreationTime());
|
||||
$this->assertEquals(30, $entries[1]->getUploadTime());
|
||||
$this->assertEquals(null, $entries[1]->getMetadataEtag());
|
||||
|
||||
$this->assertEquals(0, $entries[2]->getCreationTime());
|
||||
$this->assertEquals(0, $entries[2]->getUploadTime());
|
||||
$this->assertEquals('foo', $entries[2]->getMetadataEtag());
|
||||
|
||||
$this->assertEquals(0, $entries[3]->getCreationTime());
|
||||
$this->assertEquals(0, $entries[3]->getUploadTime());
|
||||
$this->assertEquals(null, $entries[3]->getMetadataEtag());
|
||||
|
||||
$this->cache->update($id1, ['upload_time' => 25]);
|
||||
|
||||
$entry = $this->cache->get($id1);
|
||||
$this->assertEquals(20, $entry->getCreationTime());
|
||||
$this->assertEquals(25, $entry->getUploadTime());
|
||||
$this->assertEquals(null, $entry->getMetadataEtag());
|
||||
|
||||
$this->cache->put("sub", $folderData);
|
||||
|
||||
$this->cache->move("foo1", "sub/foo1");
|
||||
|
||||
$entries = $this->cache->getFolderContents("sub");
|
||||
$this->assertCount(1, $entries);
|
||||
|
||||
$this->assertEquals(20, $entries[0]->getCreationTime());
|
||||
$this->assertEquals(25, $entries[0]->getUploadTime());
|
||||
$this->assertEquals(null, $entries[0]->getMetadataEtag());
|
||||
|
||||
$this->cache->update($id4, ['upload_time' => 25]);
|
||||
|
||||
$entry = $this->cache->get($id4);
|
||||
$this->assertEquals(0, $entry->getCreationTime());
|
||||
$this->assertEquals(25, $entry->getUploadTime());
|
||||
$this->assertEquals(null, $entry->getMetadataEtag());
|
||||
|
||||
$this->cache->remove("sub");
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
if ($this->cache) {
|
||||
$this->cache->clear();
|
||||
|
|
|
@ -25,6 +25,7 @@ use OCP\Share;
|
|||
use OCP\Util;
|
||||
use Test\TestMoveableMountPoint;
|
||||
use Test\HookHelper;
|
||||
use Test\Traits\UserTrait;
|
||||
|
||||
class TemporaryNoTouch extends Temporary {
|
||||
public function touch($path, $mtime = null) {
|
||||
|
@ -60,10 +61,12 @@ class TemporaryNoLocal extends Temporary {
|
|||
* @package Test\Files
|
||||
*/
|
||||
class ViewTest extends \Test\TestCase {
|
||||
use UserTrait;
|
||||
|
||||
/**
|
||||
* @var \OC\Files\Storage\Storage[] $storages
|
||||
*/
|
||||
private $storages = array();
|
||||
private $storages = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -138,9 +141,9 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage2 = $this->getTestStorage();
|
||||
$storage3 = $this->getTestStorage();
|
||||
$root = self::getUniqueID('/');
|
||||
Filesystem::mount($storage1, array(), $root . '/');
|
||||
Filesystem::mount($storage2, array(), $root . '/substorage');
|
||||
Filesystem::mount($storage3, array(), $root . '/folder/anotherstorage');
|
||||
Filesystem::mount($storage1, [], $root . '/');
|
||||
Filesystem::mount($storage2, [], $root . '/substorage');
|
||||
Filesystem::mount($storage3, [], $root . '/folder/anotherstorage');
|
||||
$textSize = strlen("dummy file data\n");
|
||||
$imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo/logo.png');
|
||||
$storageSize = $textSize * 2 + $imageSize;
|
||||
|
@ -204,13 +207,13 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
$cachedData = $rootView->getFileInfo('/foo.txt');
|
||||
$this->assertFalse($cachedData['encrypted']);
|
||||
$id = $rootView->putFileInfo('/foo.txt', array('encrypted' => true));
|
||||
$id = $rootView->putFileInfo('/foo.txt', ['encrypted' => true]);
|
||||
$cachedData = $rootView->getFileInfo('/foo.txt');
|
||||
$this->assertTrue($cachedData['encrypted']);
|
||||
$this->assertEquals($cachedData['fileid'], $id);
|
||||
|
||||
$this->assertFalse($rootView->getFileInfo('/non/existing'));
|
||||
$this->assertEquals(array(), $rootView->getDirectoryContent('/non/existing'));
|
||||
$this->assertEquals([], $rootView->getDirectoryContent('/non/existing'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,9 +223,9 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
$storage3 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage3, array(), '/folder/anotherstorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
Filesystem::mount($storage3, [], '/folder/anotherstorage');
|
||||
|
||||
$rootView = new View('');
|
||||
|
||||
|
@ -262,8 +265,8 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage1 = $this->getTestStorage(false);
|
||||
$storage2 = $this->getTestStorage();
|
||||
$storage1->mkdir('substorage');
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
|
||||
$rootView = new View('');
|
||||
$folderContent = $rootView->getDirectoryContent('/');
|
||||
|
@ -292,8 +295,8 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/mount');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/mount');
|
||||
|
||||
$view = new View('/');
|
||||
|
||||
|
@ -313,7 +316,7 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testCacheIncompleteFolder() {
|
||||
$storage1 = $this->getTestStorage(false);
|
||||
Filesystem::clearMounts();
|
||||
Filesystem::mount($storage1, array(), '/incomplete');
|
||||
Filesystem::mount($storage1, [], '/incomplete');
|
||||
$rootView = new View('/incomplete');
|
||||
|
||||
$entries = $rootView->getDirectoryContent('/');
|
||||
|
@ -327,8 +330,8 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testAutoScan() {
|
||||
$storage1 = $this->getTestStorage(false);
|
||||
$storage2 = $this->getTestStorage(false);
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
$textSize = strlen("dummy file data\n");
|
||||
|
||||
$rootView = new View('');
|
||||
|
@ -349,15 +352,15 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
$storage3 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage3, array(), '/folder/anotherstorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
Filesystem::mount($storage3, [], '/folder/anotherstorage');
|
||||
|
||||
$rootView = new View('');
|
||||
|
||||
$results = $rootView->search('foo');
|
||||
$this->assertCount(6, $results);
|
||||
$paths = array();
|
||||
$paths = [];
|
||||
foreach ($results as $result) {
|
||||
$this->assertEquals($result['path'], Filesystem::normalizePath($result['path']));
|
||||
$paths[] = $result['path'];
|
||||
|
@ -372,7 +375,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$folderView = new View('/folder');
|
||||
$results = $folderView->search('bar');
|
||||
$this->assertCount(2, $results);
|
||||
$paths = array();
|
||||
$paths = [];
|
||||
foreach ($results as $result) {
|
||||
$paths[] = $result['path'];
|
||||
}
|
||||
|
@ -381,7 +384,7 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
$results = $folderView->search('foo');
|
||||
$this->assertCount(2, $results);
|
||||
$paths = array();
|
||||
$paths = [];
|
||||
foreach ($results as $result) {
|
||||
$paths[] = $result['path'];
|
||||
}
|
||||
|
@ -397,7 +400,7 @@ class ViewTest extends \Test\TestCase {
|
|||
*/
|
||||
public function testWatcher() {
|
||||
$storage1 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
$storage1->getWatcher()->setPolicy(Watcher::CHECK_ALWAYS);
|
||||
|
||||
$rootView = new View('');
|
||||
|
@ -405,7 +408,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$cachedData = $rootView->getFileInfo('foo.txt');
|
||||
$this->assertEquals(16, $cachedData['size']);
|
||||
|
||||
$rootView->putFileInfo('foo.txt', array('storage_mtime' => 10));
|
||||
$rootView->putFileInfo('foo.txt', ['storage_mtime' => 10]);
|
||||
$storage1->file_put_contents('foo.txt', 'foo');
|
||||
clearstatcache();
|
||||
|
||||
|
@ -441,8 +444,8 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function copyBetweenStorages($storage1, $storage2) {
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
|
||||
$rootView = new View('');
|
||||
$rootView->mkdir('substorage/emptyfolder');
|
||||
|
@ -487,8 +490,8 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function moveBetweenStorages($storage1, $storage2) {
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
|
||||
$rootView = new View('');
|
||||
$rootView->rename('foo.txt', 'substorage/folder/foo.txt');
|
||||
|
@ -506,8 +509,8 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testUnlink() {
|
||||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
|
||||
$rootView = new View('');
|
||||
$rootView->file_put_contents('/foo.txt', 'asd');
|
||||
|
@ -552,8 +555,8 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testUnlinkRootMustFail() {
|
||||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), '/substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], '/substorage');
|
||||
|
||||
$rootView = new View('');
|
||||
$rootView->file_put_contents('/foo.txt', 'asd');
|
||||
|
@ -571,7 +574,7 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testTouch() {
|
||||
$storage = $this->getTestStorage(true, TemporaryNoTouch::class);
|
||||
|
||||
Filesystem::mount($storage, array(), '/');
|
||||
Filesystem::mount($storage, [], '/');
|
||||
|
||||
$rootView = new View('');
|
||||
$oldCachedData = $rootView->getFileInfo('foo.txt');
|
||||
|
@ -582,7 +585,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$this->assertEquals(500, $cachedData['mtime']);
|
||||
$this->assertEquals($oldCachedData['storage_mtime'], $cachedData['storage_mtime']);
|
||||
|
||||
$rootView->putFileInfo('foo.txt', array('storage_mtime' => 1000)); //make sure the watcher detects the change
|
||||
$rootView->putFileInfo('foo.txt', ['storage_mtime' => 1000]); //make sure the watcher detects the change
|
||||
$rootView->file_put_contents('foo.txt', 'asd');
|
||||
$cachedData = $rootView->getFileInfo('foo.txt');
|
||||
$this->assertGreaterThanOrEqual($oldCachedData['mtime'], $cachedData['mtime']);
|
||||
|
@ -595,7 +598,7 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testTouchFloat() {
|
||||
$storage = $this->getTestStorage(true, TemporaryNoTouch::class);
|
||||
|
||||
Filesystem::mount($storage, array(), '/');
|
||||
Filesystem::mount($storage, [], '/');
|
||||
|
||||
$rootView = new View('');
|
||||
$oldCachedData = $rootView->getFileInfo('foo.txt');
|
||||
|
@ -613,8 +616,8 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
$defaultRoot = Filesystem::getRoot();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), $defaultRoot . '/substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], $defaultRoot . '/substorage');
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook');
|
||||
|
||||
$rootView = new View('');
|
||||
|
@ -636,7 +639,7 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
public function testSearchNotOutsideView() {
|
||||
$storage1 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
$storage1->rename('folder', 'foo');
|
||||
$scanner = $storage1->getScanner();
|
||||
$scanner->scan('');
|
||||
|
@ -656,7 +659,7 @@ class ViewTest extends \Test\TestCase {
|
|||
/**
|
||||
* @var \OC\Files\Storage\Storage $storage
|
||||
*/
|
||||
$storage = new $class(array());
|
||||
$storage = new $class([]);
|
||||
$textData = "dummy file data\n";
|
||||
$imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo/logo.png');
|
||||
$storage->mkdir('folder');
|
||||
|
@ -679,8 +682,8 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
$defaultRoot = Filesystem::getRoot();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), $defaultRoot . '_substorage');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], $defaultRoot . '_substorage');
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook');
|
||||
|
||||
$subView = new View($defaultRoot . '_substorage');
|
||||
|
@ -710,8 +713,8 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage1 = $this->getTestStorage();
|
||||
$storage2 = $this->getTestStorage();
|
||||
$defaultRoot = Filesystem::getRoot();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage2, array(), $defaultRoot);
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
Filesystem::mount($storage2, [], $defaultRoot);
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_create', $this, 'dummyHookCreate');
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_update', $this, 'dummyHookUpdate');
|
||||
\OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHookWrite');
|
||||
|
@ -741,7 +744,7 @@ class ViewTest extends \Test\TestCase {
|
|||
*/
|
||||
public function testResolvePath($expected, $pathToTest) {
|
||||
$storage1 = $this->getTestStorage();
|
||||
Filesystem::mount($storage1, array(), '/');
|
||||
Filesystem::mount($storage1, [], '/');
|
||||
|
||||
$view = new View('');
|
||||
|
||||
|
@ -756,25 +759,25 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function resolvePathTestProvider() {
|
||||
return array(
|
||||
array('foo.txt', 'foo.txt'),
|
||||
array('foo.txt', '/foo.txt'),
|
||||
array('folder', 'folder'),
|
||||
array('folder', '/folder'),
|
||||
array('folder', 'folder/'),
|
||||
array('folder', '/folder/'),
|
||||
array('folder/bar.txt', 'folder/bar.txt'),
|
||||
array('folder/bar.txt', '/folder/bar.txt'),
|
||||
array('', ''),
|
||||
array('', '/'),
|
||||
);
|
||||
return [
|
||||
['foo.txt', 'foo.txt'],
|
||||
['foo.txt', '/foo.txt'],
|
||||
['folder', 'folder'],
|
||||
['folder', '/folder'],
|
||||
['folder', 'folder/'],
|
||||
['folder', '/folder/'],
|
||||
['folder/bar.txt', 'folder/bar.txt'],
|
||||
['folder/bar.txt', '/folder/bar.txt'],
|
||||
['', ''],
|
||||
['', '/'],
|
||||
];
|
||||
}
|
||||
|
||||
public function testUTF8Names() {
|
||||
$names = array('虚', '和知しゃ和で', 'regular ascii', 'sɨˈrɪlɪk', 'ѨѬ', 'أنا أحب القراءة كثيرا');
|
||||
$names = ['虚', '和知しゃ和で', 'regular ascii', 'sɨˈrɪlɪk', 'ѨѬ', 'أنا أحب القراءة كثيرا'];
|
||||
|
||||
$storage = new Temporary(array());
|
||||
Filesystem::mount($storage, array(), '/');
|
||||
$storage = new Temporary([]);
|
||||
Filesystem::mount($storage, [], '/');
|
||||
|
||||
$rootView = new View('');
|
||||
foreach ($names as $name) {
|
||||
|
@ -802,8 +805,8 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
public function xtestLongPath() {
|
||||
|
||||
$storage = new Temporary(array());
|
||||
Filesystem::mount($storage, array(), '/');
|
||||
$storage = new Temporary([]);
|
||||
Filesystem::mount($storage, [], '/');
|
||||
|
||||
$rootView = new View('');
|
||||
|
||||
|
@ -851,9 +854,9 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testTouchNotSupported() {
|
||||
$storage = new TemporaryNoTouch(array());
|
||||
$storage = new TemporaryNoTouch([]);
|
||||
$scanner = $storage->getScanner();
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$past = time() - 100;
|
||||
$storage->file_put_contents('test', 'foobar');
|
||||
$scanner->scan('');
|
||||
|
@ -868,13 +871,13 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testWatcherEtagCrossStorage() {
|
||||
$storage1 = new Temporary(array());
|
||||
$storage2 = new Temporary(array());
|
||||
$storage1 = new Temporary([]);
|
||||
$storage2 = new Temporary([]);
|
||||
$scanner1 = $storage1->getScanner();
|
||||
$scanner2 = $storage2->getScanner();
|
||||
$storage1->mkdir('sub');
|
||||
Filesystem::mount($storage1, array(), '/test/');
|
||||
Filesystem::mount($storage2, array(), '/test/sub/storage');
|
||||
Filesystem::mount($storage1, [], '/test/');
|
||||
Filesystem::mount($storage2, [], '/test/sub/storage');
|
||||
|
||||
$past = time() - 100;
|
||||
$storage2->file_put_contents('test.txt', 'foobar');
|
||||
|
@ -887,9 +890,9 @@ class ViewTest extends \Test\TestCase {
|
|||
$oldFileInfo = $view->getFileInfo('/test/sub/storage/test.txt');
|
||||
$oldFolderInfo = $view->getFileInfo('/test');
|
||||
|
||||
$storage2->getCache()->update($oldFileInfo->getId(), array(
|
||||
'storage_mtime' => $past
|
||||
));
|
||||
$storage2->getCache()->update($oldFileInfo->getId(), [
|
||||
'storage_mtime' => $past,
|
||||
]);
|
||||
|
||||
$oldEtag = $oldFolderInfo->getEtag();
|
||||
|
||||
|
@ -908,9 +911,9 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testPartFileInfo() {
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
$scanner = $storage->getScanner();
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$storage->file_put_contents('test.part', 'foobar');
|
||||
$scanner->scan('');
|
||||
$view = new View('/test');
|
||||
|
@ -922,15 +925,15 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function absolutePathProvider() {
|
||||
return array(
|
||||
array('/files/', ''),
|
||||
array('/files/0', '0'),
|
||||
array('/files/false', 'false'),
|
||||
array('/files/true', 'true'),
|
||||
array('/files/', '/'),
|
||||
array('/files/test', 'test'),
|
||||
array('/files/test', '/test'),
|
||||
);
|
||||
return [
|
||||
['/files/', ''],
|
||||
['/files/0', '0'],
|
||||
['/files/false', 'false'],
|
||||
['/files/true', 'true'],
|
||||
['/files/', '/'],
|
||||
['/files/test', 'test'],
|
||||
['/files/test', '/test'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -959,81 +962,81 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function relativePathProvider($missingRootExpectedPath) {
|
||||
return array(
|
||||
return [
|
||||
// No root - returns the path
|
||||
array('', '/files', '/files'),
|
||||
array('', '/files/', '/files/'),
|
||||
['', '/files', '/files'],
|
||||
['', '/files/', '/files/'],
|
||||
|
||||
// Root equals path - /
|
||||
array('/files/', '/files/', '/'),
|
||||
array('/files/', '/files', '/'),
|
||||
array('/files', '/files/', '/'),
|
||||
array('/files', '/files', '/'),
|
||||
['/files/', '/files/', '/'],
|
||||
['/files/', '/files', '/'],
|
||||
['/files', '/files/', '/'],
|
||||
['/files', '/files', '/'],
|
||||
|
||||
// False negatives: chroot fixes those by adding the leading slash.
|
||||
// But setting them up with this root (instead of chroot($root))
|
||||
// will fail them, although they should be the same.
|
||||
// TODO init should be fixed, so it also adds the leading slash
|
||||
array('files/', '/files/', $missingRootExpectedPath),
|
||||
array('files', '/files/', $missingRootExpectedPath),
|
||||
array('files/', '/files', $missingRootExpectedPath),
|
||||
array('files', '/files', $missingRootExpectedPath),
|
||||
['files/', '/files/', $missingRootExpectedPath],
|
||||
['files', '/files/', $missingRootExpectedPath],
|
||||
['files/', '/files', $missingRootExpectedPath],
|
||||
['files', '/files', $missingRootExpectedPath],
|
||||
|
||||
// False negatives: Paths provided to the method should have a leading slash
|
||||
// TODO input should be checked to have a leading slash
|
||||
array('/files/', 'files/', null),
|
||||
array('/files', 'files/', null),
|
||||
array('/files/', 'files', null),
|
||||
array('/files', 'files', null),
|
||||
['/files/', 'files/', null],
|
||||
['/files', 'files/', null],
|
||||
['/files/', 'files', null],
|
||||
['/files', 'files', null],
|
||||
|
||||
// with trailing slashes
|
||||
array('/files/', '/files/0', '0'),
|
||||
array('/files/', '/files/false', 'false'),
|
||||
array('/files/', '/files/true', 'true'),
|
||||
array('/files/', '/files/test', 'test'),
|
||||
array('/files/', '/files/test/foo', 'test/foo'),
|
||||
['/files/', '/files/0', '0'],
|
||||
['/files/', '/files/false', 'false'],
|
||||
['/files/', '/files/true', 'true'],
|
||||
['/files/', '/files/test', 'test'],
|
||||
['/files/', '/files/test/foo', 'test/foo'],
|
||||
|
||||
// without trailing slashes
|
||||
// TODO false expectation: Should match "with trailing slashes"
|
||||
array('/files', '/files/0', '/0'),
|
||||
array('/files', '/files/false', '/false'),
|
||||
array('/files', '/files/true', '/true'),
|
||||
array('/files', '/files/test', '/test'),
|
||||
array('/files', '/files/test/foo', '/test/foo'),
|
||||
['/files', '/files/0', '/0'],
|
||||
['/files', '/files/false', '/false'],
|
||||
['/files', '/files/true', '/true'],
|
||||
['/files', '/files/test', '/test'],
|
||||
['/files', '/files/test/foo', '/test/foo'],
|
||||
|
||||
// leading slashes
|
||||
array('/files/', '/files_trashbin/', null),
|
||||
array('/files', '/files_trashbin/', null),
|
||||
array('/files/', '/files_trashbin', null),
|
||||
array('/files', '/files_trashbin', null),
|
||||
['/files/', '/files_trashbin/', null],
|
||||
['/files', '/files_trashbin/', null],
|
||||
['/files/', '/files_trashbin', null],
|
||||
['/files', '/files_trashbin', null],
|
||||
|
||||
// no leading slashes
|
||||
array('files/', 'files_trashbin/', null),
|
||||
array('files', 'files_trashbin/', null),
|
||||
array('files/', 'files_trashbin', null),
|
||||
array('files', 'files_trashbin', null),
|
||||
['files/', 'files_trashbin/', null],
|
||||
['files', 'files_trashbin/', null],
|
||||
['files/', 'files_trashbin', null],
|
||||
['files', 'files_trashbin', null],
|
||||
|
||||
// mixed leading slashes
|
||||
array('files/', '/files_trashbin/', null),
|
||||
array('/files/', 'files_trashbin/', null),
|
||||
array('files', '/files_trashbin/', null),
|
||||
array('/files', 'files_trashbin/', null),
|
||||
array('files/', '/files_trashbin', null),
|
||||
array('/files/', 'files_trashbin', null),
|
||||
array('files', '/files_trashbin', null),
|
||||
array('/files', 'files_trashbin', null),
|
||||
['files/', '/files_trashbin/', null],
|
||||
['/files/', 'files_trashbin/', null],
|
||||
['files', '/files_trashbin/', null],
|
||||
['/files', 'files_trashbin/', null],
|
||||
['files/', '/files_trashbin', null],
|
||||
['/files/', 'files_trashbin', null],
|
||||
['files', '/files_trashbin', null],
|
||||
['/files', 'files_trashbin', null],
|
||||
|
||||
array('files', 'files_trashbin/test', null),
|
||||
array('/files', '/files_trashbin/test', null),
|
||||
array('/files', 'files_trashbin/test', null),
|
||||
);
|
||||
['files', 'files_trashbin/test', null],
|
||||
['/files', '/files_trashbin/test', null],
|
||||
['/files', 'files_trashbin/test', null],
|
||||
];
|
||||
}
|
||||
|
||||
public function testFileView() {
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
$scanner = $storage->getScanner();
|
||||
$storage->file_put_contents('foo.txt', 'bar');
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$scanner->scan('');
|
||||
$view = new View('/test/foo.txt');
|
||||
|
||||
|
@ -1059,9 +1062,9 @@ class ViewTest extends \Test\TestCase {
|
|||
$longPath .= '/' . $folderName;
|
||||
}
|
||||
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
$this->tempStorage = $storage; // for later hard cleanup
|
||||
Filesystem::mount($storage, array(), '/');
|
||||
Filesystem::mount($storage, [], '/');
|
||||
|
||||
$rootView = new View('');
|
||||
|
||||
|
@ -1074,64 +1077,64 @@ class ViewTest extends \Test\TestCase {
|
|||
$longPath = 'md5';
|
||||
}
|
||||
|
||||
call_user_func(array($rootView, $operation), $longPath, $param0);
|
||||
call_user_func([$rootView, $operation], $longPath, $param0);
|
||||
}
|
||||
|
||||
public function tooLongPathDataProvider() {
|
||||
return array(
|
||||
array('getAbsolutePath'),
|
||||
array('getRelativePath'),
|
||||
array('getMountPoint'),
|
||||
array('resolvePath'),
|
||||
array('getLocalFile'),
|
||||
array('getLocalFolder'),
|
||||
array('mkdir'),
|
||||
array('rmdir'),
|
||||
array('opendir'),
|
||||
array('is_dir'),
|
||||
array('is_file'),
|
||||
array('stat'),
|
||||
array('filetype'),
|
||||
array('filesize'),
|
||||
array('readfile'),
|
||||
array('isCreatable'),
|
||||
array('isReadable'),
|
||||
array('isUpdatable'),
|
||||
array('isDeletable'),
|
||||
array('isSharable'),
|
||||
array('file_exists'),
|
||||
array('filemtime'),
|
||||
array('touch'),
|
||||
array('file_get_contents'),
|
||||
array('unlink'),
|
||||
array('deleteAll'),
|
||||
array('toTmpFile'),
|
||||
array('getMimeType'),
|
||||
array('free_space'),
|
||||
array('getFileInfo'),
|
||||
array('getDirectoryContent'),
|
||||
array('getOwner'),
|
||||
array('getETag'),
|
||||
array('file_put_contents', 'ipsum'),
|
||||
array('rename', '@0'),
|
||||
array('copy', '@0'),
|
||||
array('fopen', 'r'),
|
||||
array('fromTmpFile', '@0'),
|
||||
array('hash'),
|
||||
array('hasUpdated', 0),
|
||||
array('putFileInfo', array()),
|
||||
);
|
||||
return [
|
||||
['getAbsolutePath'],
|
||||
['getRelativePath'],
|
||||
['getMountPoint'],
|
||||
['resolvePath'],
|
||||
['getLocalFile'],
|
||||
['getLocalFolder'],
|
||||
['mkdir'],
|
||||
['rmdir'],
|
||||
['opendir'],
|
||||
['is_dir'],
|
||||
['is_file'],
|
||||
['stat'],
|
||||
['filetype'],
|
||||
['filesize'],
|
||||
['readfile'],
|
||||
['isCreatable'],
|
||||
['isReadable'],
|
||||
['isUpdatable'],
|
||||
['isDeletable'],
|
||||
['isSharable'],
|
||||
['file_exists'],
|
||||
['filemtime'],
|
||||
['touch'],
|
||||
['file_get_contents'],
|
||||
['unlink'],
|
||||
['deleteAll'],
|
||||
['toTmpFile'],
|
||||
['getMimeType'],
|
||||
['free_space'],
|
||||
['getFileInfo'],
|
||||
['getDirectoryContent'],
|
||||
['getOwner'],
|
||||
['getETag'],
|
||||
['file_put_contents', 'ipsum'],
|
||||
['rename', '@0'],
|
||||
['copy', '@0'],
|
||||
['fopen', 'r'],
|
||||
['fromTmpFile', '@0'],
|
||||
['hash'],
|
||||
['hasUpdated', 0],
|
||||
['putFileInfo', []],
|
||||
];
|
||||
}
|
||||
|
||||
public function testRenameCrossStoragePreserveMtime() {
|
||||
$storage1 = new Temporary(array());
|
||||
$storage2 = new Temporary(array());
|
||||
$storage1 = new Temporary([]);
|
||||
$storage2 = new Temporary([]);
|
||||
$storage1->mkdir('sub');
|
||||
$storage1->mkdir('foo');
|
||||
$storage1->file_put_contents('foo.txt', 'asd');
|
||||
$storage1->file_put_contents('foo/bar.txt', 'asd');
|
||||
Filesystem::mount($storage1, array(), '/test/');
|
||||
Filesystem::mount($storage2, array(), '/test/sub/storage');
|
||||
Filesystem::mount($storage1, [], '/test/');
|
||||
Filesystem::mount($storage2, [], '/test/sub/storage');
|
||||
|
||||
$view = new View('');
|
||||
$time = time() - 200;
|
||||
|
@ -1157,7 +1160,7 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
private function doTestCopyRenameFail($operation) {
|
||||
$storage1 = new Temporary(array());
|
||||
$storage1 = new Temporary([]);
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject|Temporary $storage2 */
|
||||
$storage2 = $this->getMockBuilder(TemporaryNoCross::class)
|
||||
->setConstructorArgs([[]])
|
||||
|
@ -1180,8 +1183,8 @@ class ViewTest extends \Test\TestCase {
|
|||
$storage2->file_put_contents('existing.txt', '0123');
|
||||
$storage1->getScanner()->scan('');
|
||||
$storage2->getScanner()->scan('');
|
||||
Filesystem::mount($storage1, array(), '/test/');
|
||||
Filesystem::mount($storage2, array(), '/test/sub/storage');
|
||||
Filesystem::mount($storage1, [], '/test/');
|
||||
Filesystem::mount($storage2, [], '/test/sub/storage');
|
||||
|
||||
// move file
|
||||
$view = new View('');
|
||||
|
@ -1212,8 +1215,8 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testDeleteFailKeepCache() {
|
||||
/** @var Temporary|\PHPUnit_Framework_MockObject_MockObject $storage */
|
||||
$storage = $this->getMockBuilder(Temporary::class)
|
||||
->setConstructorArgs(array(array()))
|
||||
->setMethods(array('unlink'))
|
||||
->setConstructorArgs([[]])
|
||||
->setMethods(['unlink'])
|
||||
->getMock();
|
||||
$storage->expects($this->once())
|
||||
->method('unlink')
|
||||
|
@ -1222,7 +1225,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$cache = $storage->getCache();
|
||||
$storage->file_put_contents('foo.txt', 'asd');
|
||||
$scanner->scan('');
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
|
||||
$view = new View('/test');
|
||||
|
||||
|
@ -1248,14 +1251,14 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testRenameOverWrite() {
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
$scanner = $storage->getScanner();
|
||||
$storage->mkdir('sub');
|
||||
$storage->mkdir('foo');
|
||||
$storage->file_put_contents('foo.txt', 'asd');
|
||||
$storage->file_put_contents('foo/bar.txt', 'asd');
|
||||
$scanner->scan('');
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$view = new View('');
|
||||
$this->assertTrue($view->rename('/test/foo.txt', '/test/foo/bar.txt'));
|
||||
}
|
||||
|
@ -1309,7 +1312,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$pathPrefix = str_replace('{folder}', 'files', $pathPrefix);
|
||||
|
||||
$view = new View($rootPath);
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
Filesystem::mount($storage, [], '/');
|
||||
$this->assertTrue($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE));
|
||||
$view->lockFile($pathPrefix . '/foo/bar/asd', ILockingProvider::LOCK_SHARED);
|
||||
|
@ -1328,7 +1331,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix);
|
||||
|
||||
$view = new View($rootPath);
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
Filesystem::mount($storage, [], '/');
|
||||
$this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE));
|
||||
$this->assertFalse($view->lockFile($pathPrefix . '/foo/bar/asd', ILockingProvider::LOCK_SHARED));
|
||||
|
@ -1349,7 +1352,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$pathPrefix = str_replace('{folder}', 'files', $pathPrefix);
|
||||
|
||||
$view = new View($rootPath);
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
Filesystem::mount($storage, [], '/');
|
||||
$this->assertTrue($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_SHARED));
|
||||
$view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE);
|
||||
|
@ -1368,7 +1371,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix);
|
||||
|
||||
$view = new View($rootPath);
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
Filesystem::mount($storage, [], '/');
|
||||
$this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_SHARED));
|
||||
$this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE));
|
||||
|
@ -1516,7 +1519,7 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
public function testChangeLock() {
|
||||
$view = new View('/testuser/files/');
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
Filesystem::mount($storage, [], '/');
|
||||
|
||||
$view->lockFile('/test/sub', ILockingProvider::LOCK_SHARED);
|
||||
|
@ -1544,7 +1547,7 @@ class ViewTest extends \Test\TestCase {
|
|||
['/foo', '/files/foo', true],
|
||||
['/foo', 'filesfoo', false],
|
||||
['', '/foo/files', true],
|
||||
['', '/foo/files/bar.txt', true]
|
||||
['', '/foo/files/bar.txt', true],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1828,7 +1831,7 @@ class ViewTest extends \Test\TestCase {
|
|||
->setMethods([$operation])
|
||||
->getMock();
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
|
||||
// work directly on disk because mkdir might be mocked
|
||||
$realPath = $storage->getSourcePath('');
|
||||
|
@ -1852,7 +1855,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$this->connectMockHooks($hookType, $view, $lockedPath, $lockTypePre, $lockTypePost);
|
||||
|
||||
// do operation
|
||||
call_user_func_array(array($view, $operation), $operationArgs);
|
||||
call_user_func_array([$view, $operation], $operationArgs);
|
||||
|
||||
if ($hookType !== null) {
|
||||
$this->assertEquals($expectedLockBefore, $lockTypePre, 'File locked properly during pre-hook');
|
||||
|
@ -1878,7 +1881,7 @@ class ViewTest extends \Test\TestCase {
|
|||
->setMethods(['fopen'])
|
||||
->getMock();
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
$storage->mkdir('files');
|
||||
|
||||
$storage->expects($this->once())
|
||||
|
@ -1917,7 +1920,7 @@ class ViewTest extends \Test\TestCase {
|
|||
->setMethods(['fopen'])
|
||||
->getMock();
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
$storage->mkdir('files');
|
||||
|
||||
$storage->expects($this->once())
|
||||
|
@ -1972,7 +1975,7 @@ class ViewTest extends \Test\TestCase {
|
|||
->setMethods([$operation])
|
||||
->getMock();
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
|
||||
// work directly on disk because mkdir might be mocked
|
||||
$realPath = $storage->getSourcePath('');
|
||||
|
@ -1991,7 +1994,7 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
$thrown = false;
|
||||
try {
|
||||
call_user_func_array(array($view, $operation), $operationArgs);
|
||||
call_user_func_array([$view, $operation], $operationArgs);
|
||||
} catch (\Exception $e) {
|
||||
$thrown = true;
|
||||
$this->assertEquals('Simulated exception', $e->getMessage());
|
||||
|
@ -2005,7 +2008,7 @@ class ViewTest extends \Test\TestCase {
|
|||
|
||||
$storage = new Temporary([]);
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
|
||||
$storage->mkdir('files');
|
||||
$storage->mkdir('files/dir');
|
||||
|
@ -2054,7 +2057,7 @@ class ViewTest extends \Test\TestCase {
|
|||
->setMethods([$operation])
|
||||
->getMock();
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
$storage->mkdir('files');
|
||||
|
||||
Util::connectHook(
|
||||
|
@ -2064,7 +2067,7 @@ class ViewTest extends \Test\TestCase {
|
|||
'cancellingCallback'
|
||||
);
|
||||
|
||||
call_user_func_array(array($view, $operation), $operationArgs);
|
||||
call_user_func_array([$view, $operation], $operationArgs);
|
||||
|
||||
$this->assertNull($this->getFileLockType($view, $path), 'File got unlocked after exception');
|
||||
}
|
||||
|
@ -2100,7 +2103,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$sourcePath = 'original.txt';
|
||||
$targetPath = 'target.txt';
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
$storage->mkdir('files');
|
||||
$view->file_put_contents($sourcePath, 'meh');
|
||||
|
||||
|
@ -2152,7 +2155,7 @@ class ViewTest extends \Test\TestCase {
|
|||
$sourcePath = 'original.txt';
|
||||
$targetPath = 'target.txt';
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
$storage->mkdir('files');
|
||||
$view->file_put_contents($sourcePath, 'meh');
|
||||
|
||||
|
@ -2279,8 +2282,8 @@ class ViewTest extends \Test\TestCase {
|
|||
$sourcePath = 'original.txt';
|
||||
$targetPath = 'substorage/target.txt';
|
||||
|
||||
Filesystem::mount($storage, array(), $this->user . '/');
|
||||
Filesystem::mount($storage2, array(), $this->user . '/files/substorage');
|
||||
Filesystem::mount($storage, [], $this->user . '/');
|
||||
Filesystem::mount($storage2, [], $this->user . '/files/substorage');
|
||||
$storage->mkdir('files');
|
||||
$view->file_put_contents($sourcePath, 'meh');
|
||||
|
||||
|
@ -2513,7 +2516,7 @@ class ViewTest extends \Test\TestCase {
|
|||
public function testGetDirectoryContentMimeFilter($filter, $expected) {
|
||||
$storage1 = new Temporary();
|
||||
$root = self::getUniqueID('/');
|
||||
Filesystem::mount($storage1, array(), $root . '/');
|
||||
Filesystem::mount($storage1, [], $root . '/');
|
||||
$view = new View($root);
|
||||
|
||||
$view->file_put_contents('test1.txt', 'asd');
|
||||
|
@ -2532,10 +2535,10 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testFilePutContentsClearsChecksum() {
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
$scanner = $storage->getScanner();
|
||||
$storage->file_put_contents('foo.txt', 'bar');
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$scanner->scan('');
|
||||
|
||||
$view = new View('/test/foo.txt');
|
||||
|
@ -2552,11 +2555,11 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testDeleteGhostFile() {
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
$scanner = $storage->getScanner();
|
||||
$cache = $storage->getCache();
|
||||
$storage->file_put_contents('foo.txt', 'bar');
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$scanner->scan('');
|
||||
|
||||
$storage->unlink('foo.txt');
|
||||
|
@ -2575,12 +2578,12 @@ class ViewTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testDeleteGhostFolder() {
|
||||
$storage = new Temporary(array());
|
||||
$storage = new Temporary([]);
|
||||
$scanner = $storage->getScanner();
|
||||
$cache = $storage->getCache();
|
||||
$storage->mkdir('foo');
|
||||
$storage->file_put_contents('foo/foo.txt', 'bar');
|
||||
Filesystem::mount($storage, array(), '/test/');
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$scanner->scan('');
|
||||
|
||||
$storage->rmdir('foo');
|
||||
|
@ -2669,4 +2672,24 @@ class ViewTest extends \Test\TestCase {
|
|||
->willReturn(true);
|
||||
$this->assertFalse(self::invokePrivate($view, 'createParentDirectories', ['/file.txt/folder/structure']));
|
||||
}
|
||||
|
||||
public function testCacheExtension() {
|
||||
$storage = new Temporary([]);
|
||||
$scanner = $storage->getScanner();
|
||||
$storage->file_put_contents('foo.txt', 'bar');
|
||||
$scanner->scan('');
|
||||
|
||||
Filesystem::mount($storage, [], '/test/');
|
||||
$view = new View('/test');
|
||||
|
||||
$info = $view->getFileInfo('/foo.txt');
|
||||
$this->assertEquals(0, $info->getUploadTime());
|
||||
$this->assertEquals(0, $info->getCreationTime());
|
||||
|
||||
$view->putFileInfo('/foo.txt', ['upload_time' => 25]);
|
||||
|
||||
$info = $view->getFileInfo('/foo.txt');
|
||||
$this->assertEquals(25, $info->getUploadTime());
|
||||
$this->assertEquals(0, $info->getCreationTime());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ class HelperStorageTest extends \Test\TestCase {
|
|||
parent::setUp();
|
||||
|
||||
$this->user = $this->getUniqueID('user_');
|
||||
\OC_User::useBackend('dummy');
|
||||
\OC::$server->getUserManager()->createUser($this->user, $this->user);
|
||||
|
||||
$this->storage = \OC\Files\Filesystem::getStorage('/');
|
||||
|
|
Loading…
Reference in a new issue