19 declare(strict_types=1);
    38     protected \ilDBInterface 
$db;
    56         $paths_parser = $this->paths_parser_factory->forSearch();
    58         $quoted_table_alias = $this->
quoteIdentifier($paths_parser->getTableAliasForFilters());
    60         $query = $paths_parser->getSelectForQuery() . 
' GROUP BY ' . $quoted_table_alias . 
'.rbac_id, ' .
    61             $quoted_table_alias . 
'.obj_id, ' . $quoted_table_alias . 
'.obj_type HAVING ' . $where .
    65         foreach ($this->
queryDB($query) as $row) {
    66             yield $this->ressource_factory->ressourceID(
    67                 (
int) $row[
'rbac_id'],
    69                 (
string) $row[
'obj_type']
    75         string $quoted_table_alias,
    79         foreach ($filters as $filter) {
    82                 $filter_values[] = $quoted_table_alias . 
'.rbac_id = ' . $val;
    85                 $filter_values[] = $quoted_table_alias . 
'.obj_id = ' . $val;
    88                 $filter_values[] = $quoted_table_alias . 
'.obj_type = ' . $val;
    90             if (!empty($filter_values)) {
    91                 $filter_where[] = 
'(' . implode(
' AND ', $filter_values) . 
')';
    95         if (empty($filter_where)) {
    99         return ' AND (' . implode(
' OR ', $filter_where) . 
')';
   103         string $quoted_table_alias,
   106         if (is_int($value)) {
   109         if (is_string($value)) {
   114             case Placeholder::OBJ_ID:
   115                 return $quoted_table_alias . 
'.rbac_id';
   117             case Placeholder::SUB_ID:
   118                 return $quoted_table_alias . 
'.obj_id';
   120             case Placeholder::TYPE:
   121                 return $quoted_table_alias . 
'.obj_type';
   132         if (!is_null($limit) || !is_null($offset)) {
   133             $limit = is_null($limit) ? PHP_INT_MAX : $limit;
   137         if (!is_null($offset)) {
   138             $query_offset = 
' OFFSET ' . $this->
quoteInteger($offset);
   140         return $query_limit . $query_offset;
   149             throw new \ilMDRepositoryException(
'Search clause is nested to deep.');
   162         $sub_clauses_for_query = [];
   163         foreach ($join_props->subClauses() as $sub_clause) {
   167         switch ($join_props->operator()) {
   169                 $operator_for_query = 
'AND';
   173                 $operator_for_query = 
'OR';
   177                 throw new \ilMDRepositoryException(
'Invalid search operator.');
   185         return $negation . 
'(' . implode(
' ' . $operator_for_query . 
' ', $sub_clauses_for_query) . 
')';
   190         bool $is_clause_negated,
   193         switch ($basic_props->
mode()) {
   200                 $comparison = 
'LIKE ' .
   204             case Mode::STARTS_WITH:
   205                 $comparison = 
'LIKE ' .
   210                 $comparison = 
'LIKE ' .
   215                 throw new \ilMDRepositoryException(
'Invalid search mode.');
   220             $mode_negation = 
'NOT ';
   222         $clause_negation = 
'';
   223         if ($is_clause_negated) {
   224             $clause_negation = 
'NOT ';
   227         $needs_join_to_base_table = $basic_props->
value() === 
'' || $is_clause_negated;
   229         return $clause_negation . 
'COUNT(CASE WHEN ' . $mode_negation .
   231             ' ' . $comparison . 
' THEN 1 END) > 0';
   236         $result = $this->db->query($query);
   238         while ($row = $this->db->fetchAssoc($result)) {
   245         return $this->db->quoteIdentifier($identifier);