interpreted as a sys_file reference UID to a FAL-stored YAML file (user-generated content) * - EXT:... -> interpreted as a NON-FAL extension-based file * - any string -> interpreted as FAL-based filename * * Note that we explicitly do NOT check for file existence here, * because we want to be able to reveal sys_refindex entries to files * that have been deleted meanwhile! * * @internal */ public function getReferencesByPersistenceIdentifier(string $persistenceIdentifier): array { if (empty($persistenceIdentifier)) { throw new \InvalidArgumentException('$persistenceIdentifier must not be empty.', 1472238493); } $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_refindex'); $constraints = [$queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier'))]; // Indicator whether the string-based lookup in sys_refindex shall be performed (true; non FAL-based) or not (false; FAL-based) $useStringReference = false; // Check what $persistenceIdentifier contains. if (PathUtility::isExtensionPath($persistenceIdentifier)) { // Uses "EXT:" notation, so it cannot be a FAL identifier. // We pass the whole "EXT:..." lookup through to the sys_refindex query // due to its constraint on softref_key=formPersistenceIdentifier, // we expect no false entries even with "weird" string notations. If sys_refindex // has it, we yield it. $useStringReference = true; } elseif (MathUtility::canBeInterpretedAsInteger($persistenceIdentifier)) { $constraints[] = $queryBuilder->expr()->or( $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($persistenceIdentifier)), $queryBuilder->expr()->eq('ref_uid', $queryBuilder->createNamedParameter($persistenceIdentifier, Connection::PARAM_INT)) ); } else { // Anything else would be either a notation like "/fileadmin/something.form.yaml" // or a numeric identifier for a sys_file. try { // We use this "bulk method" because this is the best-bet from resourceFactory // to resolve both an integer-ish input value or a FAL value. There is no // substitute for an "only get a file, not a directory" lookup. $file = $this->resourceFactory->retrieveFileOrFolderObject($persistenceIdentifier); if ($file === null) { // The associated identifier could (no longer) be retrieved via FAL. // However, we do want to see existing entries to such stale entries to // be able to reveal bad references, either by its ref_string or ref_uid $useStringReference = true; } elseif ($file instanceof File) { // We succeeded in retrieving the FAL file object. $constraints[] = $queryBuilder->expr()->eq('ref_uid', $queryBuilder->createNamedParameter($file->getUid(), Connection::PARAM_INT)); } else { // We might have retrieved a "Folder" object. Fall back to passthrough // with the intent, to retrieve all possible sys_refindex entries. // If that fails, it's ok to return an empty array. $useStringReference = true; } } catch (ResourceDoesNotExistException) { // This exception gets triggered when $persistenceIdentifier is not something // that could be resolved by the bulk-method. // As above, we want to retrieve all the possible sys_refindex entries, // so we fall back again to "ref_string". // This should happen when $persistenceIdentifier is set to a string like '/fileadmin/somefile.form.yaml', // and a FAL storage could be retrieved, but not the actual file. $useStringReference = true; } } if ($useStringReference) { $constraints[] = $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($persistenceIdentifier)); } return $queryBuilder ->select('*') ->from('sys_refindex') ->where(...$constraints) ->executeQuery() ->fetchAllAssociative(); } /** * Returns an array with all form definition persistenceIdentifiers * as keys and their reference counts as values. * * @internal */ public function getAllReferencesForPersistenceIdentifier(): array { $items = []; foreach ($this->getAllReferences('ref_string') as $item) { $items[$item['identifier']] = $item['items']; } return $items; } /** * Returns an array with all form definition file uids as keys * and their reference counts as values. * * @internal */ public function getAllReferencesForFileUid(): array { $items = []; foreach ($this->getAllReferences('ref_uid') as $item) { $items[$item['identifier']] = $item['items']; } return $items; } /** * Returns an array with all database-stored form definition UIDs as keys * and their reference counts as values. * * These are tracked in sys_refindex via ref_table='form_definition' and ref_uid=. * * @return array persistenceIdentifier (UID as string) => reference count * @internal */ public function getAllReferencesForFormDefinitionUid(): array { $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_refindex'); $rows = $queryBuilder ->select('ref_uid AS identifier') ->addSelectLiteral('COUNT(' . $queryBuilder->quoteIdentifier('ref_uid') . ') AS ' . $queryBuilder->quoteIdentifier('items')) ->from('sys_refindex') ->where( $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier')), $queryBuilder->expr()->eq('ref_table', $queryBuilder->createNamedParameter(FormDefinitionRepository::TABLE_NAME)), $queryBuilder->expr()->gt('ref_uid', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)) ) ->groupBy('ref_uid') ->executeQuery() ->fetchAllAssociative(); $items = []; foreach ($rows as $row) { $items[(string)$row['identifier']] = (int)$row['items']; } return $items; } protected function getAllReferences(string $column): array { if ($column !== 'ref_string' && $column !== 'ref_uid') { throw new \InvalidArgumentException('$column must be "ref_string" or "ref_uid".', 1535406600); } $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_refindex'); $constraints = [ $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier')), ]; if ($column === 'ref_string') { $constraints[] = $queryBuilder->expr()->neq('ref_string', $queryBuilder->createNamedParameter('')); } else { $constraints[] = $queryBuilder->expr()->gt('ref_uid', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)); } return $queryBuilder ->select($column . ' AS identifier') ->addSelectLiteral('COUNT(' . $queryBuilder->quoteIdentifier($column) . ') AS ' . $queryBuilder->quoteIdentifier('items')) ->from('sys_refindex') ->where(...$constraints) ->groupBy($column) ->executeQuery() ->fetchAllAssociative(); } }