diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index a2b7e22d1b3e..baa632ec9c18 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -20,6 +20,7 @@ */ namespace OC\Files\Cache; +use OCP\Share_Backend_Collection; /** * Metadata cache for shared files @@ -218,31 +219,86 @@ public function getStatus($file) { * @return array of file data */ public function search($pattern) { - // TODO + + $where = '`name` LIKE ? AND '; + + // normalize pattern + $value = $this->normalize($pattern); + + // we have one ? in our where clause + $chunksize = self::MAX_SQL_CHUNK_SIZE - 1; + + return $this->searchWithWhere($where, $value, $chunksize); + } /** * search for files by mimetype * - * @param string $part1 - * @param string $part2 + * @param string $mimetype * @return array */ public function searchByMime($mimetype) { + if (strpos($mimetype, '/')) { - $where = '`mimetype` = ?'; + $where = '`mimetype` = ? AND '; } else { - $where = '`mimepart` = ?'; + $where = '`mimepart` = ? AND '; } - $mimetype = $this->getMimetypeId($mimetype); + + $value = $this->getMimetypeId($mimetype); + + // we have one ? in our where clause + $chunksize = self::MAX_SQL_CHUNK_SIZE - 1; + + return $this->searchWithWhere($where, $value, $chunksize); + + } + + /** + * The maximum number of placeholders that can be used in an SQL query. + * Value MUST be < 1000. + * Also see ORA-01795 maximum number of expressions in a list is 1000 + */ + const MAX_SQL_CHUNK_SIZE = 999; + + /** + * search for files with a custom where clause and value + * the $wherevalue will be array_merge()d with the file id chunks + * + * @param string $sqlwhere + * @param string $wherevalue + * @return array + */ + private function searchWithWhere($sqlwhere, $wherevalue, $chunksize = self::MAX_SQL_CHUNK_SIZE) { + $ids = $this->getAll(); - $placeholders = join(',', array_fill(0, count($ids), '?')); - $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` - FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `fileid` IN (' . $placeholders . ')' - ); - $result = $query->execute(array_merge(array($mimetype), $ids)); - return $result->fetchAll(); + + $files = array(); + + // divide into 1k chunks + $chunks = array_chunk($ids, $chunksize); + + foreach ($chunks as $chunk) { + $placeholders = join(',', array_fill(0, count($chunk), '?')); + $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, + `encrypted`, `unencrypted_size`, `etag` + FROM `*PREFIX*filecache` WHERE ' . $sqlwhere . ' `fileid` IN (' . $placeholders . ')'; + + $stmt = \OC_DB::prepare($sql); + + $result = $stmt->execute(array_merge(array($wherevalue), $chunk)); + + while ($row = $result->fetchRow()) { + if (substr($row['path'], 0, 6) === 'files/') { + $row['path'] = substr($row['path'], 6); // remove 'files/' from path as it's relative to '/Shared' + } + $row['mimetype'] = $this->getMimetype($row['mimetype']); + $row['mimepart'] = $this->getMimetype($row['mimepart']); + $files[] = $row; + } + } + return $files; } /** @@ -264,7 +320,20 @@ public function calculateFolderSize($path) { * @return int[] */ public function getAll() { - return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_ALL); + $ids = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_ALL); + $folderBackend = \OCP\Share::getBackend('folder'); + if ($folderBackend instanceof Share_Backend_Collection) { + foreach ($ids as $file) { + /** @var $folderBackend Share_Backend_Collection */ + $children = $folderBackend->getChildren($file); + foreach ($children as $child) { + $ids[] = (int)$child['source']; + } + + } + } + + return $ids; } } diff --git a/lib/public/share.php b/lib/public/share.php index d75699334584..7ba5fa502469 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -760,10 +760,10 @@ public static function setExpirationDate($itemType, $itemSource, $date) { /** * @brief Get the backend class for the specified item type - * @param string Item type - * @return Sharing backend object + * @param string $itemType + * @return Share_Backend */ - private static function getBackend($itemType) { + public static function getBackend($itemType) { if (isset(self::$backends[$itemType])) { return self::$backends[$itemType]; } else if (isset(self::$backendTypes[$itemType]['class'])) {