TYPO3 v15 dev-main snapshot ()

This commit is contained in:
2026-08-10 22:31:09 +02:00
commit af8cc155b5
6818 changed files with 642608 additions and 0 deletions
@@ -0,0 +1,143 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Resource\Search\Result;
use TYPO3\CMS\Core\Resource\Driver\DriverInterface;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Utility\PathUtility;
/**
* Decorator for a search result with files, which filters
* the result based on given filters.
*/
class DriverFilteredSearchResult implements FileSearchResultInterface
{
private ?array $result = null;
public function __construct(
private readonly FileSearchResultInterface $searchResult,
private readonly DriverInterface $driver,
/**
* @var callable[]
*/
private readonly array $filters
) {}
/**
* @see Countable::count()
*/
public function count(): int
{
$this->initialize();
return count($this->result);
}
/**
* @see Iterator::current()
*/
public function current(): File
{
$this->initialize();
return current($this->result);
}
/**
* @see Iterator::key()
*/
public function key(): int
{
$this->initialize();
return key($this->result);
}
/**
* @see Iterator::next()
*/
public function next(): void
{
$this->initialize();
next($this->result);
}
/**
* @see Iterator::rewind()
*/
public function rewind(): void
{
$this->initialize();
reset($this->result);
}
/**
* @see Iterator::valid()
*/
public function valid(): bool
{
$this->initialize();
return current($this->result) !== false;
}
private function initialize(): void
{
if ($this->result === null) {
$this->result = $this->applyFilters(...iterator_to_array($this->searchResult));
}
}
/**
* Filter out identifiers by calling all attached filters
*
* @return array<int, File>
*/
private function applyFilters(File ...$files): array
{
$filteredFiles = [];
foreach ($files as $file) {
$itemIdentifier = $file->getIdentifier();
$itemName = PathUtility::basename($itemIdentifier);
$parentIdentifier = PathUtility::dirname($itemIdentifier);
$matches = true;
foreach ($this->filters as $filter) {
if (!is_callable($filter)) {
continue;
}
$result = $filter($itemName, $itemIdentifier, $parentIdentifier, [], $this->driver);
// We use -1 as the "don't include“ return value, for historic reasons,
// as call_user_func() used to return FALSE if calling the method failed.
if ($result === -1) {
$matches = false;
}
if ($result === false) {
throw new \RuntimeException(
'Could not apply file/folder name filter ' . $filter[0] . '::' . $filter[1],
1543617278
);
}
}
if ($matches) {
$filteredFiles[] = $file;
}
}
return $filteredFiles;
}
}
@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Resource\Search\Result;
/**
* Represents an empty search result (no matches found)
*/
class EmptyFileSearchResult implements FileSearchResultInterface
{
public function count(): int
{
return 0;
}
/**
* @phpstan-return null
*/
public function current(): mixed
{
// Noop
return null;
}
/**
* @phpstan-return null
*/
public function key(): mixed
{
// Noop
return null;
}
public function next(): void
{
// Noop
}
public function rewind(): void
{
// Noop
}
/**
* @return false
*/
public function valid(): bool
{
return false;
}
}
@@ -0,0 +1,128 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Resource\Search\Result;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Resource\Search\FileSearchDemand;
use TYPO3\CMS\Core\Resource\Search\FileSearchQuery;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Represents a search result for a given search query
* being an iterable and countable list of file objects.
*/
class FileSearchResult implements FileSearchResultInterface
{
/**
* @var FileSearchDemand
*/
private $searchDemand;
/**
* @var array
*/
private $result;
/**
* @var int
*/
private $resultCount;
public function __construct(FileSearchDemand $searchDemand)
{
$this->searchDemand = $searchDemand;
}
/**
* @see Countable::count()
*/
public function count(): int
{
if ($this->resultCount !== null) {
return $this->resultCount;
}
$this->resultCount = (int)FileSearchQuery::createCountForSearchDemand($this->searchDemand)->execute()->fetchOne();
return $this->resultCount;
}
/**
* @see Iterator::current()
*/
public function current(): File
{
$this->initialize();
return current($this->result);
}
/**
* @see Iterator::key()
*/
public function key(): int
{
$this->initialize();
return key($this->result);
}
/**
* @see Iterator::next()
*/
public function next(): void
{
$this->initialize();
next($this->result);
}
/**
* @see Iterator::rewind()
*/
public function rewind(): void
{
$this->initialize();
reset($this->result);
}
/**
* @see Iterator::valid()
*/
public function valid(): bool
{
$this->initialize();
return current($this->result) !== false;
}
/**
* Perform the SQL query and apply filters on the resulting identifiers
*/
private function initialize(): void
{
if ($this->result !== null) {
return;
}
$this->result = FileSearchQuery::createForSearchDemand($this->searchDemand)->execute()->fetchAllAssociative();
$this->resultCount = count($this->result);
$this->result = array_map(
static function (array $fileRow): File {
return GeneralUtility::makeInstance(ResourceFactory::class)->getFileObject($fileRow['uid'], $fileRow);
},
$this->result
);
}
}
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Core\Resource\Search\Result;
/**
* Representation of a result for a search for files performed by FileSearchQuery,
* which is a collection of matching files.
*/
interface FileSearchResultInterface extends \Countable, \Iterator {}