/** * Return the query parameters to select the records from a table $table with pid = $this->pidList * * @param string $table Table name * @param int $pageId Page id Only used to build the search constraints, $this->pidList is used for restrictions * @param string[] $fieldList List of fields to select from the table * @param string[] $additionalConstraints Additional part for where clause * @return array */ protected function buildQueryParameters(string $table, int $pageId, array $fieldList = ['*'], array $additionalConstraints = []) : array { $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table)->expr(); $parameters = ['table' => $table, 'fields' => $fieldList, 'groupBy' => null, 'orderBy' => null, 'firstResult' => $this->firstElementNumber ?: null, 'maxResults' => $this->iLimit ? $this->iLimit : null]; if ($this->sortField && in_array($this->sortField, $this->makeFieldList($table, 1))) { $parameters['orderBy'][] = $this->sortRev ? [$this->sortField, 'DESC'] : [$this->sortField, 'ASC']; } else { $orderBy = $GLOBALS['TCA'][$table]['ctrl']['sortby'] ?: $GLOBALS['TCA'][$table]['ctrl']['default_sortby']; $parameters['orderBy'] = QueryHelper::parseOrderBy((string) $orderBy); } // Build the query constraints $constraints = ['pidSelect' => $this->getPageIdConstraint($table), 'search' => $this->makeSearchString($table, $pageId)]; // Filtering on displayable pages (permissions): if ($table === 'pages' && $this->perms_clause) { $constraints['pagePermsClause'] = $this->perms_clause; } // Filter out records that are translated, if TSconfig mod.web_list.hideTranslations is set if ((GeneralUtility::inList($this->hideTranslations, $table) || $this->hideTranslations === '*') && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) && $table !== 'pages_language_overlay') { $constraints['transOrigPointerField'] = $expressionBuilder->eq($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], 0); } $parameters['where'] = array_merge($constraints, $additionalConstraints); $hookName = DatabaseRecordList::class; if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$hookName]['buildQueryParameters'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$hookName]['buildQueryParameters'] as $classRef) { $hookObject = GeneralUtility::getUserObj($classRef); if (method_exists($hookObject, 'buildQueryParametersPostProcess')) { $hookObject->buildQueryParametersPostProcess($parameters, $table, $pageId, $additionalConstraints, $fieldList, $this); } } } // array_unique / array_filter used to eliminate empty and duplicate constraints // the array keys are eliminated by this as well to facilitate argument unpacking // when used with the querybuilder. $parameters['where'] = array_unique(array_filter(array_values($parameters['where']))); return $parameters; }
/** * @test * @dataProvider parseOrderByDataProvider * @param string $input * @param array $expectedResult */ public function parseOrderByTest(string $input, array $expectedResult) { $this->assertSame($expectedResult, QueryHelper::parseOrderBy($input)); }
/** * Getting the tree data: Selecting/Initializing data pointer to items for a certain parent id. * For tables: This will make a database query to select all children to "parent" * For arrays: This will return key to the ->dataLookup array * * @param int $parentId parent item id * * @return mixed Data handle (Tables: An sql-resource, arrays: A parentId integer. -1 is returned if there were NO subLevel.) * @access private */ public function getDataInit($parentId) { if (is_array($this->data)) { if (!is_array($this->dataLookup[$parentId][$this->subLevelID])) { $parentId = -1; } else { reset($this->dataLookup[$parentId][$this->subLevelID]); } return $parentId; } else { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class))->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $queryBuilder->select(...$this->fieldArray)->from($this->table)->where($queryBuilder->expr()->eq($this->parentField, $queryBuilder->createNamedParameter($parentId, \PDO::PARAM_INT)), QueryHelper::stripLogicalOperatorPrefix($this->clause)); foreach (QueryHelper::parseOrderBy($this->orderByFields) as $orderPair) { list($fieldName, $order) = $orderPair; $queryBuilder->addOrderBy($fieldName, $order); } return $queryBuilder->execute(); } }
/** * Returns an array of file mount records, taking workspaces and user home and group home directories into account * Needs to be called AFTER the groups have been loaded. * * @return array * @internal */ public function getFileMountRecords() { static $fileMountRecordCache = []; if (!empty($fileMountRecordCache)) { return $fileMountRecordCache; } $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); // Processing file mounts (both from the user and the groups) $fileMounts = array_unique(GeneralUtility::intExplode(',', $this->dataLists['filemount_list'], true)); // Limit file mounts if set in workspace record if ($this->workspace > 0 && !empty($this->workspaceRec['file_mountpoints'])) { $workspaceFileMounts = GeneralUtility::intExplode(',', $this->workspaceRec['file_mountpoints'], true); $fileMounts = array_intersect($fileMounts, $workspaceFileMounts); } if (!empty($fileMounts)) { $orderBy = $GLOBALS['TCA']['sys_filemounts']['ctrl']['default_sortby'] ?? 'sorting'; $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_filemounts'); $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class))->add(GeneralUtility::makeInstance(HiddenRestriction::class))->add(GeneralUtility::makeInstance(RootLevelRestriction::class)); $queryBuilder->select('*')->from('sys_filemounts')->where($queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($fileMounts, Connection::PARAM_INT_ARRAY))); foreach (QueryHelper::parseOrderBy($orderBy) as $fieldAndDirection) { $queryBuilder->addOrderBy(...$fieldAndDirection); } $fileMountRecords = $queryBuilder->execute()->fetchAll(\PDO::FETCH_ASSOC); if ($fileMountRecords !== false) { foreach ($fileMountRecords as $fileMount) { $fileMountRecordCache[$fileMount['base'] . $fileMount['path']] = $fileMount; } } } // Read-only file mounts $readOnlyMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.folderTree.altElementBrowserMountPoints')); if ($readOnlyMountPoints) { // We cannot use the API here but need to fetch the default storage record directly // to not instantiate it (which directly applies mount points) before all mount points are resolved! $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_file_storage'); $defaultStorageRow = $queryBuilder->select('uid')->from('sys_file_storage')->where($queryBuilder->expr()->eq('is_default', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)))->setMaxResults(1)->execute()->fetch(\PDO::FETCH_ASSOC); $readOnlyMountPointArray = GeneralUtility::trimExplode(',', $readOnlyMountPoints); foreach ($readOnlyMountPointArray as $readOnlyMountPoint) { $readOnlyMountPointConfiguration = GeneralUtility::trimExplode(':', $readOnlyMountPoint); if (count($readOnlyMountPointConfiguration) === 2) { // A storage is passed in the configuration $storageUid = (int) $readOnlyMountPointConfiguration[0]; $path = $readOnlyMountPointConfiguration[1]; } else { if (empty($defaultStorageRow)) { throw new \RuntimeException('Read only mount points have been defined in User TsConfig without specific storage, but a default storage could not be resolved.', 1404472382); } // Backwards compatibility: If no storage is passed, we use the default storage $storageUid = $defaultStorageRow['uid']; $path = $readOnlyMountPointConfiguration[0]; } $fileMountRecordCache[$storageUid . $path] = ['base' => $storageUid, 'title' => $path, 'path' => $path, 'read_only' => true]; } } // Personal or Group filemounts are not accessible if file mount list is set in workspace record if ($this->workspace <= 0 || empty($this->workspaceRec['file_mountpoints'])) { // If userHomePath is set, we attempt to mount it if ($GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath']) { list($userHomeStorageUid, $userHomeFilter) = explode(':', $GLOBALS['TYPO3_CONF_VARS']['BE']['userHomePath'], 2); $userHomeStorageUid = (int) $userHomeStorageUid; $userHomeFilter = '/' . ltrim($userHomeFilter, '/'); if ($userHomeStorageUid > 0) { // Try and mount with [uid]_[username] $path = $userHomeFilter . $this->user['uid'] . '_' . $this->user['username'] . $GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir']; $fileMountRecordCache[$userHomeStorageUid . $path] = ['base' => $userHomeStorageUid, 'title' => $this->user['username'], 'path' => $path, 'read_only' => false, 'user_mount' => true]; // Try and mount with only [uid] $path = $userHomeFilter . $this->user['uid'] . $GLOBALS['TYPO3_CONF_VARS']['BE']['userUploadDir']; $fileMountRecordCache[$userHomeStorageUid . $path] = ['base' => $userHomeStorageUid, 'title' => $this->user['username'], 'path' => $path, 'read_only' => false, 'user_mount' => true]; } } // Mount group home-dirs if ((is_array($this->user) && $this->user['options'] & Permission::PAGE_EDIT) == 2 && $GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'] != '') { // If groupHomePath is set, we attempt to mount it list($groupHomeStorageUid, $groupHomeFilter) = explode(':', $GLOBALS['TYPO3_CONF_VARS']['BE']['groupHomePath'], 2); $groupHomeStorageUid = (int) $groupHomeStorageUid; $groupHomeFilter = '/' . ltrim($groupHomeFilter, '/'); if ($groupHomeStorageUid > 0) { foreach ($this->userGroups as $groupData) { $path = $groupHomeFilter . $groupData['uid']; $fileMountRecordCache[$groupHomeStorageUid . $path] = ['base' => $groupHomeStorageUid, 'title' => $groupData['title'], 'path' => $path, 'read_only' => false, 'user_mount' => true]; } } } } return $fileMountRecordCache; }
/** * Prepares the clause by which the result elements are sorted. See description of ORDER BY in * SQL standard for reference. * * @return void */ protected function prepareOrderByStatement() { if (empty($this->config['orderBy'])) { $this->queryBuilder->addOrderBy($GLOBALS['TCA'][$this->table]['ctrl']['label']); } else { foreach (QueryHelper::parseOrderBy($this->config['orderBy']) as $orderPair) { list($fieldName, $order) = $orderPair; $this->queryBuilder->addOrderBy($fieldName, $order); } } }
/** * Find records by given table name. * * @param string $tableName Database table name * @param string $pageIdList Comma separated list of page IDs * @param int $firstResult * @param int $maxResults * @return array Records found in the database matching the searchQuery * @see getRecordArray() * @see makeQuerySearchByTable() * @see extractSearchableFieldsFromTable() */ protected function findByTable($tableName, $pageIdList, $firstResult, $maxResults) { $fieldsToSearchWithin = $this->extractSearchableFieldsFromTable($tableName); $getRecordArray = []; if (!empty($fieldsToSearchWithin)) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName); $queryBuilder->select('*')->from($tableName)->where($queryBuilder->expr()->in('pid', $queryBuilder->createNamedParameter($pageIdList, Connection::PARAM_INT_ARRAY)), $this->makeQuerySearchByTable($queryBuilder, $tableName, $fieldsToSearchWithin))->setFirstResult($firstResult)->setMaxResults($maxResults); if ($tableName === 'pages' && $this->userPermissions) { $queryBuilder->andWhere($this->userPermissions); } $orderBy = $GLOBALS['TCA'][$tableName]['ctrl']['sortby'] ?: $GLOBALS['TCA'][$tableName]['ctrl']['default_sortby']; foreach (QueryHelper::parseOrderBy((string) $orderBy) as $orderPair) { list($fieldName, $order) = $orderPair; $queryBuilder->addOrderBy($fieldName, $order); } $getRecordArray = $this->getRecordArray($queryBuilder, $tableName); } return $getRecordArray; }
/** * Will select all records from the "category table", $table, and return them in an array. * * @param string $table The name of the category table to select from. * @param int $pid The page from where to select the category records. * @param string $whereClause Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string. * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string. * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string. * @return array The array with the category records in. */ public function pi_getCategoryTableContents($table, $pid, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); $queryBuilder->select('*')->from($table)->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)), QueryHelper::stripLogicalOperatorPrefix($whereClause)); if (!empty($orderBy)) { foreach (QueryHelper::parseOrderBy($orderBy) as $fieldNameAndSorting) { list($fieldName, $sorting) = $fieldNameAndSorting; $queryBuilder->addOrderBy($fieldName, $sorting); } } if (!empty($groupBy)) { $queryBuilder->groupBy(...QueryHelper::parseGroupBy($groupBy)); } if (!empty($limit)) { $limitValues = GeneralUtility::intExplode(',', $limit, true); if (count($limitValues) === 1) { $queryBuilder->setMaxResults($limitValues[0]); } else { $queryBuilder->setFirstResult($limitValues[0])->setMaxResults($limitValues[1]); } } $result = $queryBuilder->execute(); $outArr = []; while ($row = $result->fetch()) { $outArr[$row['uid']] = $row; } return $outArr; }
/** * Helper function for getQuery(), creating the WHERE clause of the SELECT query * * @param string $table The table name * @param array $conf The TypoScript configuration properties * @return array Associative array containing the prepared data for WHERE, ORDER BY and GROUP BY fragments * @throws \InvalidArgumentException * @see getQuery() */ protected function getQueryConstraints(string $table, array $conf) : array { // Init: $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); $expressionBuilder = $queryBuilder->expr(); $tsfe = $this->getTypoScriptFrontendController(); $constraints = []; $pid_uid_flag = 0; $enableFieldsIgnore = []; $queryParts = ['where' => null, 'groupBy' => null, 'orderBy' => null]; $considerMovePlaceholders = $tsfe->sys_page->versioningPreview && $table !== 'pages' && !empty($GLOBALS['TCA'][$table]['ctrl']['versioningWS']); if (trim($conf['uidInList'])) { $listArr = GeneralUtility::intExplode(',', str_replace('this', $tsfe->contentPid, $conf['uidInList'])); // If move placeholder shall be considered, select via t3ver_move_id if ($considerMovePlaceholders) { $constraints[] = (string) $expressionBuilder->orX($expressionBuilder->in($table . '.uid', $listArr), $expressionBuilder->andX($expressionBuilder->eq($table . '.t3ver_state', (int) (string) VersionState::cast(VersionState::MOVE_PLACEHOLDER)), $expressionBuilder->in($table . '.t3ver_move_id', $listArr))); } else { $constraints[] = (string) $expressionBuilder->in($table . '.uid', $listArr); } $pid_uid_flag++; } // Static_* tables are allowed to be fetched from root page if (strpos($table, 'static_') === 0) { $pid_uid_flag++; } if (trim($conf['pidInList'])) { $listArr = GeneralUtility::intExplode(',', str_replace('this', $tsfe->contentPid, $conf['pidInList'])); // Removes all pages which are not visible for the user! $listArr = $this->checkPidArray($listArr); if (GeneralUtility::inList($conf['pidInList'], 'root')) { $listArr[] = 0; } if (GeneralUtility::inList($conf['pidInList'], '-1')) { $listArr[] = -1; $enableFieldsIgnore['pid'] = true; } if (!empty($listArr)) { $constraints[] = $expressionBuilder->in($table . '.pid', array_map('intval', $listArr)); $pid_uid_flag++; } else { // If not uid and not pid then uid is set to 0 - which results in nothing!! $pid_uid_flag = 0; } } // If not uid and not pid then uid is set to 0 - which results in nothing!! if (!$pid_uid_flag) { $constraints[] = $expressionBuilder->eq($table . '.uid', 0); } $where = isset($conf['where.']) ? trim($this->stdWrap($conf['where'], $conf['where.'])) : trim($conf['where']); if ($where) { $constraints[] = QueryHelper::stripLogicalOperatorPrefix($where); } // Check if the table is translatable, and set the language field by default from the TCA information $languageField = ''; if (!empty($conf['languageField']) || !isset($conf['languageField'])) { if (isset($conf['languageField']) && !empty($GLOBALS['TCA'][$table]['columns'][$conf['languageField']])) { $languageField = $conf['languageField']; } elseif (!empty($GLOBALS['TCA'][$table]['ctrl']['languageField']) && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'])) { $languageField = $table . '.' . $GLOBALS['TCA'][$table]['ctrl']['languageField']; } } if (!empty($languageField)) { // The sys_language record UID of the content of the page $sys_language_content = (int) $tsfe->sys_language_content; if ($tsfe->sys_language_contentOL && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'])) { // Sys language content is set to zero/-1 - and it is expected that whatever routine processes the output will // OVERLAY the records with localized versions! $languageQuery = $expressionBuilder->in($languageField, [0, -1]); // Use this option to include records that don't have a default translation // (originalpointerfield is 0 and the language field contains the requested language) $includeRecordsWithoutDefaultTranslation = isset($conf['includeRecordsWithoutDefaultTranslation.']) ? $this->stdWrap($conf['includeRecordsWithoutDefaultTranslation'], $conf['includeRecordsWithoutDefaultTranslation.']) : $conf['includeRecordsWithoutDefaultTranslation']; if (trim($includeRecordsWithoutDefaultTranslation) !== '') { $languageQuery = $expressionBuilder->orX($languageQuery, $expressionBuilder->andX($expressionBuilder->eq($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], 0), $expressionBuilder->eq($languageField, $sys_language_content))); } } else { $languageQuery = $expressionBuilder->eq($languageField, $sys_language_content); } $constraints[] = $languageQuery; } // Enablefields if ($table === 'pages') { $constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->where_hid_del); $constraints[] = QueryHelper::stripLogicalOperatorPrefix($tsfe->sys_page->where_groupAccess); } else { $constraints[] = QueryHelper::stripLogicalOperatorPrefix($this->enableFields($table, false, $enableFieldsIgnore)); } // MAKE WHERE: if (count($constraints) !== 0) { $queryParts['where'] = $expressionBuilder->andX(...$constraints); } // GROUP BY if (trim($conf['groupBy'])) { $groupBy = isset($conf['groupBy.']) ? trim($this->stdWrap($conf['groupBy'], $conf['groupBy.'])) : trim($conf['groupBy']); $queryParts['groupBy'] = QueryHelper::parseGroupBy($groupBy); } // ORDER BY if (trim($conf['orderBy'])) { $orderByString = isset($conf['orderBy.']) ? trim($this->stdWrap($conf['orderBy'], $conf['orderBy.'])) : trim($conf['orderBy']); $queryParts['orderBy'] = QueryHelper::parseOrderBy($orderByString); } // Return result: return $queryParts; }
/** * Get select query * * @param string $qString * @return bool|\mysqli_result|object */ public function getSelectQuery($qString = '') { $backendUserAuthentication = $this->getBackendUserAuthentication(); $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table); if ($this->getModule()->MOD_SETTINGS['show_deleted']) { $queryBuilder->getRestrictions()->removeAll(); } else { $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); } $fieldList = GeneralUtility::trimExplode(',', $this->extFieldLists['queryFields'] . ',pid' . ($GLOBALS['TCA'][$this->table]['ctrl']['delete'] ? ',' . $GLOBALS['TCA'][$this->table]['ctrl']['delete'] : '')); $queryBuilder->select(...$fieldList)->from($this->table); if ($this->extFieldLists['queryGroup']) { $queryBuilder->groupBy(...QueryHelper::parseGroupBy($this->extFieldLists['queryGroup'])); } if ($this->extFieldLists['queryOrder']) { foreach (QueryHelper::parseOrderBy($this->extFieldLists['queryOrder_SQL']) as $orderPair) { list($fieldName, $order) = $orderPair; $queryBuilder->addOrderBy($fieldName, $order); } } if ($this->extFieldLists['queryLimit']) { $queryBuilder->setMaxResults((int) $this->extFieldLists['queryLimit']); } if (!$backendUserAuthentication->isAdmin() && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts']) { $webMounts = $backendUserAuthentication->returnWebmounts(); $perms_clause = $backendUserAuthentication->getPagePermsClause(1); $webMountPageTree = ''; $webMountPageTreePrefix = ''; foreach ($webMounts as $webMount) { if ($webMountPageTree) { $webMountPageTreePrefix = ','; } $webMountPageTree .= $webMountPageTreePrefix . $this->getTreeList($webMount, 999, $begin = 0, $perms_clause); } if ($this->table === 'pages') { $queryBuilder->where(QueryHelper::stripLogicalOperatorPrefix($perms_clause), $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter(GeneralUtility::intExplode(',', $webMountPageTree), Connection::PARAM_INT_ARRAY))); } else { $queryBuilder->where($queryBuilder->expr()->in('pid', $queryBuilder->createNamedParameter(GeneralUtility::intExplode(',', $webMountPageTree), Connection::PARAM_INT_ARRAY))); } } if (!$qString) { $qString = $this->getQuery($this->queryConfig); } $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($qString)); return $queryBuilder->getSQL(); }
/** * Selects records based on matching a field (ei. other than UID) with a value * * @param string $theTable The table name to search, eg. "pages" or "tt_content * @param string $theField The fieldname to match, eg. "uid" or "alias * @param string $theValue The value that fieldname must match, eg. "123" or "frontpage * @param string $whereClause Optional additional WHERE clauses put in the end of the query. DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! * @param string $groupBy Optional GROUP BY field(s). If none, supply blank string. * @param string $orderBy Optional ORDER BY field(s). If none, supply blank string. * @param string $limit Optional LIMIT value ([begin,]max). If none, supply blank string. * @return mixed Returns array (the record) if found, otherwise nothing (void) */ public function getRecordsByField($theTable, $theField, $theValue, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') { if (is_array($GLOBALS['TCA'][$theTable])) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($theTable); $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class)); $queryBuilder->select('*')->from($theTable)->where($queryBuilder->expr()->eq($theField, $queryBuilder->createNamedParameter($theValue))); if ($whereClause !== '') { $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($whereClause)); } if ($groupBy !== '') { $queryBuilder->groupBy(QueryHelper::parseGroupBy($groupBy)); } if ($orderBy !== '') { foreach (QueryHelper::parseOrderBy($orderBy) as $orderPair) { list($fieldName, $order) = $orderPair; $queryBuilder->addOrderBy($fieldName, $order); } } if ($limit !== '') { if (strpos($limit, ',')) { $limitOffsetAndMax = GeneralUtility::intExplode(',', $limit); $queryBuilder->setFirstResult((int) $limitOffsetAndMax[0]); $queryBuilder->setMaxResults((int) $limitOffsetAndMax[1]); } else { $queryBuilder->setMaxResults((int) $limit); } } $rows = $queryBuilder->execute()->fetchAll(); if (!empty($rows)) { return $rows; } } return null; }