Skip to content

Commit

Permalink
Merge pull request #10287 from owncloud/fix_search_in_shared_files_st…
Browse files Browse the repository at this point in the history
…able7

Fix search in shared files stable7
  • Loading branch information
DeepDiver1975 committed Aug 8, 2014
2 parents 8c89263 + 41fe3f2 commit db117bd
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 62 deletions.
85 changes: 26 additions & 59 deletions apps/files_sharing/lib/cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,34 @@ public function getStatus($file) {
*/
public function search($pattern) {

$where = '`name` LIKE ? AND ';
$pattern = trim($pattern,'%');

// normalize pattern
$value = $this->normalize($pattern);
$normalizedPattern = $this->normalize($pattern);

return $this->searchWithWhere($where, $value);
$result = array();
$exploreDirs = array('');
while (count($exploreDirs) > 0) {
$dir = array_pop($exploreDirs);
$files = $this->getFolderContents($dir);
// no results?
if (!$files) {
// maybe it's a single shared file
$file = $this->get('');
if ($normalizedPattern === '' || stristr($file['name'], $normalizedPattern) !== false) {
$result[] = $file;
}
continue;
}
foreach ($files as $file) {
if ($normalizedPattern === '' || stristr($file['name'], $normalizedPattern) !== false) {
$result[] = $file;
}
if ($file['mimetype'] === 'httpd/unix-directory') {
$exploreDirs[] = ltrim($dir . '/' . $file['name'], '/');
}
}
}
return $result;

}

Expand All @@ -298,10 +320,6 @@ public function searchByMime($mimetype) {
$mimetype = null;
}

// note: searchWithWhere is currently broken as it doesn't
// recurse into subdirs nor returns the correct
// file paths, so using getFolderContents() for now

$result = array();
$exploreDirs = array('');
while (count($exploreDirs) > 0) {
Expand All @@ -327,57 +345,6 @@ public function searchByMime($mimetype) {
return $result;
}

/**
* The maximum number of placeholders that can be used in an SQL query.
* Value MUST be <= 1000 for oracle:
* see ORA-01795 maximum number of expressions in a list is 1000
* FIXME we should get this from doctrine as other DBs allow a lot more placeholders
*/
const MAX_SQL_CHUNK_SIZE = 1000;

/**
* 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();

$files = array();

// divide into 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']);
if ($row['encrypted'] or ($row['unencrypted_size'] > 0 and $row['mimetype'] === 'httpd/unix-directory')) {
$row['encrypted_size'] = $row['size'];
$row['size'] = $row['unencrypted_size'];
}
$files[] = $row;
}
}
return $files;
}

/**
* get the size of a folder and set it in the cache
*
Expand Down
78 changes: 75 additions & 3 deletions apps/files_sharing/tests/cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,80 @@ function tearDown() {
parent::tearDown();
}

function searchDataProvider() {
return array(
array('%another%',
array(
array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'),
array('name' => 'another.txt', 'path' => 'subdir/another.txt'),
)
),
array('%Another%',
array(
array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'),
array('name' => 'another.txt', 'path' => 'subdir/another.txt'),
)
),
array('%dir%',
array(
array('name' => 'emptydir', 'path' => 'emptydir'),
array('name' => 'subdir', 'path' => 'subdir'),
array('name' => 'shareddir', 'path' => ''),
)
),
array('%Dir%',
array(
array('name' => 'emptydir', 'path' => 'emptydir'),
array('name' => 'subdir', 'path' => 'subdir'),
array('name' => 'shareddir', 'path' => ''),
)
),
array('%txt%',
array(
array('name' => 'bar.txt', 'path' => 'bar.txt'),
array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'),
array('name' => 'another.txt', 'path' => 'subdir/another.txt'),
)
),
array('%Txt%',
array(
array('name' => 'bar.txt', 'path' => 'bar.txt'),
array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'),
array('name' => 'another.txt', 'path' => 'subdir/another.txt'),
)
),
array('%',
array(
array('name' => 'bar.txt', 'path' => 'bar.txt'),
array('name' => 'emptydir', 'path' => 'emptydir'),
array('name' => 'subdir', 'path' => 'subdir'),
array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'),
array('name' => 'another.txt', 'path' => 'subdir/another.txt'),
array('name' => 'not a text file.xml', 'path' => 'subdir/not a text file.xml'),
array('name' => 'shareddir', 'path' => ''),
)
),
array('%nonexistant%',
array(
)
),
);
}

/**
* we cannot use a dataProvider because that would cause the stray hook detection to remove the hooks
* that were added in setUpBeforeClass.
*/
function testSearch() {
foreach ($this->searchDataProvider() as $data) {
list($pattern, $expectedFiles) = $data;

$results = $this->sharedStorage->getCache()->search($pattern);

$this->verifyFiles($expectedFiles, $results);
}

}
/**
* Test searching by mime type
*/
Expand All @@ -115,8 +189,6 @@ function testSearchByMime() {
),
);
$this->verifyFiles($check, $results);

$this->verifyFiles($check, $results);
}

function testGetFolderContentsInRoot() {
Expand Down Expand Up @@ -245,7 +317,7 @@ private function verifyFiles($examples, $results) {
}
}
}
$this->assertTrue(empty($results));
$this->assertEquals(array(), $results);
}

/**
Expand Down

0 comments on commit db117bd

Please sign in to comment.