Skip to content

Commit

Permalink
TASK: Load stubs depending on TYPO3 version
Browse files Browse the repository at this point in the history
  • Loading branch information
sabbelasichon committed Feb 15, 2024
1 parent a30c83a commit aa9a9e4
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 62 deletions.
10 changes: 1 addition & 9 deletions extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,9 @@ parameters:
routeEnhancers: array
websiteTitle: string
stubFiles:
- stubs/DomainObjectInterface.stub
- stubs/EventDispatcher.stub
- stubs/ObjectStorage.stub
- stubs/QueryFactory.stub
- stubs/QueryInterface.stub
- stubs/QueryResultInterface.stub
- stubs/Repository.stub
# See SaschaEgerer\PhpstanTypo3\Stubs\StubFilesExtensionLoader
# GeneralUtility.stub is only used if TYPO3 version is < 12
#- stubs/GeneralUtility.stub
#- stubs/QueryResult.stub
# Some stubs are loaded depending on the TYPO3 version used. See SaschaEgerer\PhpstanTypo3\Stubs\StubFilesExtensionLoader
dynamicConstantNames:
- TYPO3_MODE
- TYPO3_REQUESTTYPE
Expand Down
7 changes: 6 additions & 1 deletion src/Stubs/StubFilesExtensionLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ public function getFiles(): array
$files[] = $stubsDir . '/GeneralUtility.stub';
}
if ($versionParser->parseConstraints($typo3Version->getVersion())->matches($versionParser->parseConstraints('<= 12.2.0'))) {
$files[] = $stubsDir . '/QueryResult.stub';
$files[] = $stubsDir . '/DomainObjectInterface.stub';
$files[] = $stubsDir . '/QueryFactory.stub';
$files[] = $stubsDir . '/QueryInterface.stub';
$files[] = $stubsDir . '/QueryResultInterface.stub';
$files[] = $stubsDir . '/Repository.stub';
$files[] = $stubsDir . '/RepositoryInterface.stub';
}

return $files;
Expand Down
7 changes: 4 additions & 3 deletions src/Type/QueryResultToArrayDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ public function getTypeFromMethodCall(
if ($resultType instanceof GenericObjectType) {
$modelType = $resultType->getTypes()[0] ?? new ErrorType();
} else {
$modelType = $methodReflection->getDeclaringClass()
->getPossiblyIncompleteActiveTemplateTypeMap()
->getType('ModelType') ?? new ErrorType();
$declaringClass = $methodReflection->getDeclaringClass();
$possibleTypes = $declaringClass->getPossiblyIncompleteActiveTemplateTypeMap();
$type = $possibleTypes->getType('TValue');
$modelType = $type ?? new ErrorType();
}

return new ArrayType(new IntegerType(), $modelType);
Expand Down
11 changes: 7 additions & 4 deletions stubs/QueryFactory.stub
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
<?php
namespace TYPO3\CMS\Extbase\Persistence\Generic;

use TYPO3\CMS\Extbase\Persistence\QueryInterface;

class QueryFactory
{
/**
* @template TEntityClass
* @param class-string<TEntityClass> $className The class name
* @return \TYPO3\CMS\Extbase\Persistence\QueryInterface<TEntityClass>
* @param string $className The class name
* @template T of object
* @phpstan-param class-string<T> $className
* @phpstan-return QueryInterface<T>
*/
public function create($className): \TYPO3\CMS\Extbase\Persistence\QueryInterface;
public function create($className): QueryInterface;
}
15 changes: 7 additions & 8 deletions stubs/QueryInterface.stub
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,26 @@
namespace TYPO3\CMS\Extbase\Persistence;

/**
* @template ModelType
* @template T of object
*/
interface QueryInterface
{
public const ORDER_ASCENDING = 'ASC';
public const ORDER_DESCENDING = 'DESC';

/**
* @param bool $returnRawQueryResult
* @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface<ModelType>|array<string, mixed>
* @param bool $returnRawQueryResult avoids the object mapping by the persistence
* @phpstan-return ($returnRawQueryResult is true ? list<T> : QueryResultInterface<T>)
*/
public function execute($returnRawQueryResult = false);

/**
* @param mixed $constraint
* @return \TYPO3\CMS\Extbase\Persistence\QueryInterface<ModelType>
* @return QueryInterface
* @phpstan-return QueryInterface<T>
*/
public function matching($constraint);

/**
* @return class-string<ModelType>
* @return string
* @phpstan-return class-string<T>
*/
public function getType();
}
6 changes: 3 additions & 3 deletions stubs/QueryResult.stub
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ namespace TYPO3\CMS\Extbase\Persistence\Generic;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;

/**
* @template ModelType
* @implements QueryResultInterface<ModelType>
* @template TValue of object
* @implements QueryResultInterface<int,TValue>
*/
class QueryResult implements QueryResultInterface
{
/**
* @return null|ModelType
* @return null|TValue
*/
public function getFirst();
}
12 changes: 6 additions & 6 deletions stubs/QueryResultInterface.stub
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
namespace TYPO3\CMS\Extbase\Persistence;

/**
* @template ModelType
* @extends \ArrayAccess<string, ModelType>
* @extends \Iterator<string, ModelType>
* @template TValue of object
* @extends \Iterator<string,TValue>
* @extends \ArrayAccess<string,TValue>
*/
interface QueryResultInterface extends \Countable, \Iterator, \ArrayAccess
{
/**
* @return \TYPO3\CMS\Extbase\Persistence\QueryInterface<ModelType>
* @phpstan-return QueryInterface<TValue>
*/
public function getQuery();

/**
* @return null|ModelType
* @phpstan-return TValue|null
*/
public function getFirst();

/**
* @return ModelType[]
* @phpstan-return TValue[]
*/
public function toArray();
}
41 changes: 19 additions & 22 deletions stubs/Repository.stub
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
<?php
namespace TYPO3\CMS\Extbase\Persistence;

use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface;

/**
* @template TEntityClass of \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface
* @template T of DomainObjectInterface
* @implements RepositoryInterface<T>
*/
class Repository
class Repository implements RepositoryInterface
{
/**
* @var class-string<TEntityClass>
* @phpstan-var class-string<T>
*/
protected $objectType;

/**
* @phpstan-param TEntityClass $object
* @phpstan-return void
* @phpstan-param T $object
* @return void
*/
public function add($object);

/**
* @phpstan-param TEntityClass $object
* @phpstan-return void
* @phpstan-param T $object
* @return void
*/
public function remove($object);

/**
* @phpstan-param TEntityClass $modifiedObject
* @phpstan-return void
* @phpstan-param T $modifiedObject
* @return void
*/
public function update($modifiedObject);

/**
* @phpstan-return QueryResultInterface<TEntityClass>|list<TEntityClass>
* @phpstan-return QueryResultInterface<T>|list<T>
*/
public function findAll();

/**
* @phpstan-param int $uid
* @phpstan-return TEntityClass|null
* @param int $uid The identifier of the object to find
* @phpstan-return T|null
*/
public function findByUid($uid);

/**
* @phpstan-param int $identifier
* @phpstan-return TEntityClass|null
* @param mixed $identifier The identifier of the object to find
* @phpstan-return T|null
*/
public function findByIdentifier($identifier);

Expand All @@ -53,19 +56,13 @@ class Repository
public function setDefaultOrderings($defaultOrderings);

/**
* @phpstan-return QueryInterface<TEntityClass>
* @return QueryInterface
* @phpstan-return QueryInterface<T>
*/
public function createQuery();

/**
* @phpstan-return class-string<static>
*/
protected function getRepositoryClassName();

/**
* @phpstan-param array<non-empty-string, mixed> $criteria
* @phpstan-param array<non-empty-string, QueryInterface::ORDER_*>|null $orderBy
* @phpstan-return QueryResultInterface<TEntityClass>|list<TEntityClass>
*/
public function findBy(array $criteria, array $orderBy = null, int $limit = null, int $offset = null);
}
50 changes: 50 additions & 0 deletions stubs/RepositoryInterface.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
namespace TYPO3\CMS\Extbase\Persistence;

/**
* Contract for a repository
* @template T of object
*/
interface RepositoryInterface
{
/**
* @phpstan-param T $object
* @return void
*/
public function add($object);

/**
* @phpstan-param T $object
* @return void
*/
public function remove($object);

/**
* @phpstan-param T $modifiedObject
* @return void
*/
public function update($modifiedObject);

/**
* @phpstan-return iterable<T>
*/
public function findAll();

/**
* @param int $uid The identifier of the object to find
* @phpstan-return T|null
*/
public function findByUid($uid);

/**
* @param mixed $identifier The identifier of the object to find
* @phpstan-return T|null
*/
public function findByIdentifier($identifier);

/**
* @return QueryInterface
* @phpstan-return QueryInterface<T>
*/
public function createQuery();
}
7 changes: 1 addition & 6 deletions tests/Unit/Type/data/repository-stub-files.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,9 @@ class FindAllWithoutReturnTestRepository extends \TYPO3\CMS\Extbase\Persistence\
public function myTests(): void
{
assertType(
'array<int, RepositoryStubFiles\My\Test\Extension\Domain\Model\MyModel>|TYPO3\CMS\Extbase\Persistence\QueryResultInterface<RepositoryStubFiles\My\Test\Extension\Domain\Model\MyModel>',
'iterable<RepositoryStubFiles\My\Test\Extension\Domain\Model\MyModel>',
$this->findAll()
);

assertType(
'array<int, RepositoryStubFiles\My\Test\Extension\Domain\Model\MyModel>|TYPO3\CMS\Extbase\Persistence\QueryResultInterface<RepositoryStubFiles\My\Test\Extension\Domain\Model\MyModel>',
$this->findBy(['foo' => 'baz'])
);
}

public function findAll() // phpcs:ignore SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint
Expand Down

0 comments on commit aa9a9e4

Please sign in to comment.