fullTextSearchDataComposerFactory = $fullTextSearchDataComposerFactory; $this->selectBuilderFactory = $selectBuilderFactory; } public function find(string $filter, int $offset, int $maxSize): stdClass { $entityTypeList = $this->config->get('globalSearchEntityList') ?? []; $hasFullTextSearch = false; $queryList = []; foreach ($entityTypeList as $i => $entityType) { $query = $this->getEntityTypeQuery( $entityType, $i, $filter, $offset, $maxSize, $hasFullTextSearch ); if (!$query) { continue; } $queryList[] = $query; } if (count($queryList) === 0) { return (object) [ 'total' => 0, 'list' => [], ]; } $builder = $this->entityManager->getQueryBuilder() ->union() ->all() ->limit($offset, $maxSize + 1); foreach ($queryList as $query) { $builder->query($query); } if ($hasFullTextSearch) { $builder->order('relevance', 'DESC'); } $builder->order('order', 'DESC'); $builder->order('name', 'ASC'); $unionQuery = $builder->build(); $sth = $this->entityManager->getQueryExecutor()->execute($unionQuery); $rows = $sth->fetchAll(PDO::FETCH_ASSOC) ?: []; $resultList = []; foreach ($rows as $row) { $entity = $this->entityManager ->getRDBRepository($row['entityType']) ->select(['id', 'name']) ->where(['id' => $row['id']]) ->findOne(); if (!$entity) { continue; } $itemData = $entity->getValueMap(); $itemData->_scope = $entity->getEntityType(); $resultList[] = $itemData; } $total = -2; if (count($resultList) > $maxSize) { $total = -1; unset($resultList[count($resultList) - 1]); } return (object) [ 'total' => $total, 'list' => $resultList, ]; } protected function getEntityTypeQuery( string $entityType, int $i, string $filter, int $offset, int $maxSize, bool &$hasFullTextSearch ): ?Select { if (!$this->acl->checkScope($entityType, 'read')) { return null; } if (!$this->metadata->get(['scopes', $entityType])) { return null; } $selectBuilder = $this->selectBuilderFactory ->create() ->from($entityType) ->withStrictAccessControl() ->withTextFilter($filter); $selectList = [ 'id', 'name', ['VALUE:' . $entityType, 'entityType'], [(string) $i, 'order'], ]; $fullTextSearchDataComposer = $this->fullTextSearchDataComposerFactory->create($entityType); $fullTextSearchData = $fullTextSearchDataComposer->compose( $filter, FullTextSearchDataComposerParams::create() ); $isPerson = $this->metadata ->get(['entityDefs', $entityType, 'fields', 'name', 'type']) === 'personName'; if ($isPerson) { $selectList[] = 'firstName'; $selectList[] = 'lastName'; } else { $selectList[] = ['VALUE:', 'firstName']; $selectList[] = ['VALUE:', 'lastName']; } $query = $selectBuilder->build(); $queryBuilder = $this->entityManager ->getQueryBuilder() ->select() ->clone($query) ->limit(0, $offset + $maxSize + 1) ->select($selectList) ->order([]); if ($fullTextSearchData) { $hasFullTextSearch = true; $expression = $fullTextSearchData->getExpression(); $queryBuilder ->select($expression, 'relevance') ->order($expression, Order::DESC); } else { $queryBuilder->select(Expr::value(1.1), 'relevance'); } $queryBuilder->order('name'); return $queryBuilder->build(); } }