Add template typing to the QBMapper

The QBMapper is kind of a generic type, though this concept does not
exist in php. Hence you have a lot of type coercion in subtypes (mappers
in the individual apps) because you suddenly don't expect an Entity[]
but your specific type.

Luckily Psalm lets us type those. Then in the subclass you can
psalm-implement the mapper with a concrete type and psalm will do all
the magic to ensure types are used correctly.

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
Christoph Wurst 2020-10-09 14:27:59 +02:00 committed by backportbot[bot]
parent e58134e0c9
commit a1856176d5
1 changed files with 17 additions and 2 deletions

View File

@ -39,13 +39,15 @@ use OCP\IDBConnection;
* may be subject to change in the future * may be subject to change in the future
* *
* @since 14.0.0 * @since 14.0.0
*
* @template T of Entity
*/ */
abstract class QBMapper { abstract class QBMapper {
/** @var string */ /** @var string */
protected $tableName; protected $tableName;
/** @var string */ /** @var string|class-string<T> */
protected $entityClass; protected $entityClass;
/** @var IDBConnection */ /** @var IDBConnection */
@ -54,7 +56,8 @@ abstract class QBMapper {
/** /**
* @param IDBConnection $db Instance of the Db abstraction layer * @param IDBConnection $db Instance of the Db abstraction layer
* @param string $tableName the name of the table. set this to allow entity * @param string $tableName the name of the table. set this to allow entity
* @param string $entityClass the name of the entity that the sql should be * @param string|null $entityClass the name of the entity that the sql should be
* @psalm-param class-string<T>|null $entityClass the name of the entity that the sql should be
* mapped to queries without using sql * mapped to queries without using sql
* @since 14.0.0 * @since 14.0.0
*/ */
@ -84,7 +87,9 @@ abstract class QBMapper {
/** /**
* Deletes an entity from the table * Deletes an entity from the table
* @param Entity $entity the entity that should be deleted * @param Entity $entity the entity that should be deleted
* @psalm-param T $entity the entity that should be deleted
* @return Entity the deleted entity * @return Entity the deleted entity
* @psalm-return T the deleted entity
* @since 14.0.0 * @since 14.0.0
*/ */
public function delete(Entity $entity): Entity { public function delete(Entity $entity): Entity {
@ -104,7 +109,9 @@ abstract class QBMapper {
/** /**
* Creates a new entry in the db from an entity * Creates a new entry in the db from an entity
* @param Entity $entity the entity that should be created * @param Entity $entity the entity that should be created
* @psalm-param T $entity the entity that should be created
* @return Entity the saved entity with the set id * @return Entity the saved entity with the set id
* @psalm-return T the saved entity with the set id
* @since 14.0.0 * @since 14.0.0
*/ */
public function insert(Entity $entity): Entity { public function insert(Entity $entity): Entity {
@ -141,7 +148,9 @@ abstract class QBMapper {
* by the database * by the database
* *
* @param Entity $entity the entity that should be created/updated * @param Entity $entity the entity that should be created/updated
* @psalm-param T $entity the entity that should be created/updated
* @return Entity the saved entity with the (new) id * @return Entity the saved entity with the (new) id
* @psalm-return T the saved entity with the (new) id
* @throws \InvalidArgumentException if entity has no id * @throws \InvalidArgumentException if entity has no id
* @since 15.0.0 * @since 15.0.0
*/ */
@ -157,7 +166,9 @@ abstract class QBMapper {
* Updates an entry in the db from an entity * Updates an entry in the db from an entity
* @throws \InvalidArgumentException if entity has no id * @throws \InvalidArgumentException if entity has no id
* @param Entity $entity the entity that should be created * @param Entity $entity the entity that should be created
* @psalm-param T $entity the entity that should be created
* @return Entity the saved entity with the set id * @return Entity the saved entity with the set id
* @psalm-return T the saved entity with the set id
* @since 14.0.0 * @since 14.0.0
*/ */
public function update(Entity $entity): Entity { public function update(Entity $entity): Entity {
@ -207,6 +218,7 @@ abstract class QBMapper {
* of the $entity * of the $entity
* *
* @param Entity $entity The entity to get the types from * @param Entity $entity The entity to get the types from
* @psalm-param T $entity
* @param string $property The property of $entity to get the type for * @param string $property The property of $entity to get the type for
* @return int * @return int
* @since 16.0.0 * @since 16.0.0
@ -288,6 +300,7 @@ abstract class QBMapper {
* *
* @param array $row the row which should be converted to an entity * @param array $row the row which should be converted to an entity
* @return Entity the entity * @return Entity the entity
* @psalm-return T the entity
* @since 14.0.0 * @since 14.0.0
*/ */
protected function mapRowToEntity(array $row): Entity { protected function mapRowToEntity(array $row): Entity {
@ -300,6 +313,7 @@ abstract class QBMapper {
* *
* @param IQueryBuilder $query * @param IQueryBuilder $query
* @return Entity[] all fetched entities * @return Entity[] all fetched entities
* @psalm-return T[] all fetched entities
* @since 14.0.0 * @since 14.0.0
*/ */
protected function findEntities(IQueryBuilder $query): array { protected function findEntities(IQueryBuilder $query): array {
@ -325,6 +339,7 @@ abstract class QBMapper {
* @throws DoesNotExistException if the item does not exist * @throws DoesNotExistException if the item does not exist
* @throws MultipleObjectsReturnedException if more than one item exist * @throws MultipleObjectsReturnedException if more than one item exist
* @return Entity the entity * @return Entity the entity
* @psalm-return T the entity
* @since 14.0.0 * @since 14.0.0
*/ */
protected function findEntity(IQueryBuilder $query): Entity { protected function findEntity(IQueryBuilder $query): Entity {