@ -119,6 +119,7 @@ class FileSearchBackend implements ISearchBackend {
new SearchPropertyDefinition ( FilesPlugin :: SIZE_PROPERTYNAME , true , true , true , SearchPropertyDefinition :: DATATYPE_NONNEGATIVE_INTEGER ),
new SearchPropertyDefinition ( TagsPlugin :: FAVORITE_PROPERTYNAME , true , true , true , SearchPropertyDefinition :: DATATYPE_BOOLEAN ),
new SearchPropertyDefinition ( FilesPlugin :: INTERNAL_FILEID_PROPERTYNAME , true , true , false , SearchPropertyDefinition :: DATATYPE_NONNEGATIVE_INTEGER ),
new SearchPropertyDefinition ( FilesPlugin :: OWNER_ID_PROPERTYNAME , true , true , false ),
// select only properties
new SearchPropertyDefinition ( '{DAV:}resourcetype' , false , true , false ),
@ -126,7 +127,6 @@ class FileSearchBackend implements ISearchBackend {
new SearchPropertyDefinition ( FilesPlugin :: CHECKSUMS_PROPERTYNAME , false , true , false ),
new SearchPropertyDefinition ( FilesPlugin :: PERMISSIONS_PROPERTYNAME , false , true , false ),
new SearchPropertyDefinition ( FilesPlugin :: GETETAG_PROPERTYNAME , false , true , false ),
new SearchPropertyDefinition ( FilesPlugin :: OWNER_ID_PROPERTYNAME , false , true , false ),
new SearchPropertyDefinition ( FilesPlugin :: OWNER_DISPLAY_NAME_PROPERTYNAME , false , true , false ),
new SearchPropertyDefinition ( FilesPlugin :: DATA_FINGERPRINT_PROPERTYNAME , false , true , false ),
new SearchPropertyDefinition ( FilesPlugin :: HAS_PREVIEW_PROPERTYNAME , false , true , false , SearchPropertyDefinition :: DATATYPE_BOOLEAN ),
@ -169,10 +169,12 @@ class FileSearchBackend implements ISearchBackend {
return new SearchResult ( $davNode , $path );
}, $results );
// Sort again, since the result from multiple storages is appended and not sorted
usort ( $nodes , function ( SearchResult $a , SearchResult $b ) use ( $search ) {
return $this -> sort ( $a , $b , $search -> orderBy );
});
if ( ! $query -> limitToHome ()) {
// Sort again, since the result from multiple storages is appended and not sorted
usort ( $nodes , function ( SearchResult $a , SearchResult $b ) use ( $search ) {
return $this -> sort ( $a , $b , $search -> orderBy );
});
}
// If a limit is provided use only return that number of files
if ( $search -> limit -> maxResults !== 0 ) {
@ -267,11 +269,29 @@ class FileSearchBackend implements ISearchBackend {
* @ param Query $query
* @ return ISearchQuery
*/
private function transformQuery ( Query $query ) {
private function transformQuery ( Query $query ) : ISearchQuery {
// TODO offset
$limit = $query -> limit ;
$orders = array_map ([ $this , 'mapSearchOrder' ], $query -> orderBy );
return new SearchQuery ( $this -> transformSearchOperation ( $query -> where ), ( int ) $limit -> maxResults , 0 , $orders , $this -> user );
$limitHome = false ;
$ownerProp = $this -> extractWhereValue ( $query -> where , FilesPlugin :: OWNER_ID_PROPERTYNAME , Operator :: OPERATION_EQUAL );
if ( $ownerProp !== null ) {
if ( $ownerProp === $this -> user -> getUID ()) {
$limitHome = true ;
} else {
throw new \InvalidArgumentException ( " Invalid search value for ' { http://owncloud.org/ns}owner-id', only the current user id is allowed " );
}
}
return new SearchQuery (
$this -> transformSearchOperation ( $query -> where ),
( int ) $limit -> maxResults ,
0 ,
$orders ,
$this -> user ,
$limitHome
);
}
/**
@ -360,4 +380,52 @@ class FileSearchBackend implements ISearchBackend {
return $value ;
}
}
/**
* Get a specific property from the were clause
*/
private function extractWhereValue ( Operator & $operator , string $propertyName , string $comparison , bool $acceptableLocation = true ) : ? string {
switch ( $operator -> type ) {
case Operator :: OPERATION_AND :
case Operator :: OPERATION_OR :
case Operator :: OPERATION_NOT :
foreach ( $operator -> arguments as & $argument ) {
$value = $this -> extractWhereValue ( $argument , $propertyName , $comparison , $acceptableLocation && $operator -> type === Operator :: OPERATION_AND );
if ( $value !== null ) {
return $value ;
}
}
return null ;
case Operator :: OPERATION_EQUAL :
case Operator :: OPERATION_GREATER_OR_EQUAL_THAN :
case Operator :: OPERATION_GREATER_THAN :
case Operator :: OPERATION_LESS_OR_EQUAL_THAN :
case Operator :: OPERATION_LESS_THAN :
case Operator :: OPERATION_IS_LIKE :
if ( $operator -> arguments [ 0 ] -> name === $propertyName ) {
if ( $operator -> type === $comparison ) {
if ( $acceptableLocation ) {
if ( $operator -> arguments [ 1 ] instanceof Literal ) {
$value = $operator -> arguments [ 1 ] -> value ;
// to remove the comparison from the query, we replace it with an empty AND
$operator = new Operator ( Operator :: OPERATION_AND );
return $value ;
} else {
throw new \InvalidArgumentException ( " searching by ' $propertyName ' is only allowed with a literal value " );
}
} else {
throw new \InvalidArgumentException ( " searching by ' $propertyName ' is not allowed inside a ' { DAV:}or' or ' { DAV:}not' " );
}
} else {
throw new \InvalidArgumentException ( " searching by ' $propertyName ' is only allowed inside a ' $comparison ' " );
}
} else {
return null ;
}
default :
return null ;
}
}
}