From cc0976aaa0fe0b77aec19d3420eb5d35299fdfec Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Fri, 9 Oct 2020 14:27:59 +0200 Subject: [PATCH] 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 --- lib/public/AppFramework/Db/QBMapper.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php index ebbe92e787..ae2956987f 100644 --- a/lib/public/AppFramework/Db/QBMapper.php +++ b/lib/public/AppFramework/Db/QBMapper.php @@ -39,13 +39,15 @@ use OCP\IDBConnection; * may be subject to change in the future * * @since 14.0.0 + * + * @template T of Entity */ abstract class QBMapper { /** @var string */ protected $tableName; - /** @var string */ + /** @var string|class-string */ protected $entityClass; /** @var IDBConnection */ @@ -54,7 +56,8 @@ abstract class QBMapper { /** * @param IDBConnection $db Instance of the Db abstraction layer * @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|null $entityClass the name of the entity that the sql should be * mapped to queries without using sql * @since 14.0.0 */ @@ -84,7 +87,9 @@ abstract class QBMapper { /** * Deletes an entity from the table * @param Entity $entity the entity that should be deleted + * @psalm-param T $entity the entity that should be deleted * @return Entity the deleted entity + * @psalm-return T the deleted entity * @since 14.0.0 */ public function delete(Entity $entity): Entity { @@ -104,7 +109,9 @@ abstract class QBMapper { /** * Creates a new entry in the db from an entity * @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 + * @psalm-return T the saved entity with the set id * @since 14.0.0 * @suppress SqlInjectionChecker */ @@ -142,7 +149,9 @@ abstract class QBMapper { * by the database * * @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 + * @psalm-return T the saved entity with the (new) id * @throws \InvalidArgumentException if entity has no id * @since 15.0.0 * @suppress SqlInjectionChecker @@ -159,7 +168,9 @@ abstract class QBMapper { * Updates an entry in the db from an entity * @throws \InvalidArgumentException if entity has no id * @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 + * @psalm-return T the saved entity with the set id * @since 14.0.0 * @suppress SqlInjectionChecker */ @@ -210,6 +221,7 @@ abstract class QBMapper { * of the $entity * * @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 * @return int * @since 16.0.0 @@ -291,6 +303,7 @@ abstract class QBMapper { * * @param array $row the row which should be converted to an entity * @return Entity the entity + * @psalm-return T the entity * @since 14.0.0 */ protected function mapRowToEntity(array $row): Entity { @@ -303,6 +316,7 @@ abstract class QBMapper { * * @param IQueryBuilder $query * @return Entity[] all fetched entities + * @psalm-return T[] all fetched entities * @since 14.0.0 */ protected function findEntities(IQueryBuilder $query): array { @@ -328,6 +342,7 @@ abstract class QBMapper { * @throws DoesNotExistException if the item does not exist * @throws MultipleObjectsReturnedException if more than one item exist * @return Entity the entity + * @psalm-return T the entity * @since 14.0.0 */ protected function findEntity(IQueryBuilder $query): Entity {