Selaa lähdekoodia

add BinaryColumn type, Count query support, and setFirstResult()

phpdevcommunity 1 kuukausi sitten
vanhempi
sitoutus
2b2b2ba460

+ 1 - 0
src/Debugger/SqlDebugger.php

@@ -26,6 +26,7 @@ class SqlDebugger
             'startTime' => microtime(true),
             'executionTime' => 0,
         ];
+
     }
 
     public function stopQuery(): void

+ 6 - 0
src/Mapper/EntityMapper.php

@@ -68,6 +68,12 @@ final class EntityMapper
     {
         if ($class instanceof ProxyInterface) {
             $class = $class->__getParentClass();
+        }elseif (is_subclass_of($class, ProxyInterface::class)) {
+            $reflector = new \ReflectionClass($class);
+            $parentClass = $reflector->getParentClass();
+            if ($parentClass) {
+                $class = $parentClass->getName();
+            }
         }
 
         $reflector = new \ReflectionClass($class);

+ 19 - 0
src/Mapping/Column/BinaryColumn.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Mapping\Column;
+
+use Attribute;
+use PhpDevCommunity\PaperORM\Types\BinaryType;
+use PhpDevCommunity\PaperORM\Types\StringType;
+
+#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)]
+final class BinaryColumn extends Column
+{
+    public function __construct(
+        string $name = null,
+        bool   $nullable = false
+    )
+    {
+        parent::__construct('', $name, BinaryType::class, $nullable);
+    }
+}

+ 5 - 0
src/Platform/MariaDBPlatform.php

@@ -4,6 +4,7 @@ namespace PhpDevCommunity\PaperORM\Platform;
 
 use InvalidArgumentException;
 use LogicException;
+use PhpDevCommunity\PaperORM\Mapping\Column\BinaryColumn;
 use PhpDevCommunity\PaperORM\Mapping\Column\BoolColumn;
 use PhpDevCommunity\PaperORM\Mapping\Column\Column;
 use PhpDevCommunity\PaperORM\Mapping\Column\DateColumn;
@@ -272,6 +273,10 @@ class MariaDBPlatform extends AbstractPlatform
                 'type' => 'VARCHAR',
                 'args' => [255]
             ],
+            BinaryColumn::class => [
+                'type' => 'BLOB',
+                'args' => []
+            ],
         ];
     }
 

+ 5 - 0
src/Platform/SqlitePlatform.php

@@ -4,6 +4,7 @@ namespace PhpDevCommunity\PaperORM\Platform;
 
 use InvalidArgumentException;
 use LogicException;
+use PhpDevCommunity\PaperORM\Mapping\Column\BinaryColumn;
 use PhpDevCommunity\PaperORM\Mapping\Column\BoolColumn;
 use PhpDevCommunity\PaperORM\Mapping\Column\Column;
 use PhpDevCommunity\PaperORM\Mapping\Column\DateColumn;
@@ -278,6 +279,10 @@ class SqlitePlatform extends AbstractPlatform
             TimestampColumn::class => [
                 'type' => 'DATETIME',
                 'args' => [],
+            ],
+            BinaryColumn::class => [
+                'type' => 'BLOB',
+                'args' => [],
             ]
         ];
     }

+ 21 - 12
src/Query/Fetcher.php

@@ -37,6 +37,11 @@ final class Fetcher
         return $this;
     }
 
+    public function offset(?int $offset): Fetcher
+    {
+        $this->queryBuilder->setFirstResult($offset);
+        return $this;
+    }
     public function limit(?int $limit): Fetcher
     {
         $this->queryBuilder->setMaxResults($limit);
@@ -68,29 +73,33 @@ final class Fetcher
 
     public function toArray(): ?array
     {
-        if ($this->collection) {
-            return $this->queryBuilder->getResult($this->arguments, QueryBuilder::HYDRATE_ARRAY);
-        }
-
-        return $this->queryBuilder->getOneOrNullResult($this->arguments, QueryBuilder::HYDRATE_ARRAY);
+        return $this->getResult(QueryBuilder::HYDRATE_ARRAY);
     }
 
     public function toObject()
     {
-        if ($this->collection) {
-            return $this->queryBuilder->getResult($this->arguments);
-        }
-
-        return $this->queryBuilder->getOneOrNullResult($this->arguments);
+       return $this->getResult(QueryBuilder::HYDRATE_OBJECT);
     }
 
     public function toReadOnlyObject()
     {
+        return $this->getResult(QueryBuilder::HYDRATE_OBJECT_READONLY)  ;
+    }
+
+    public function toCount(): int
+    {
+        return $this->queryBuilder->getCountResult();
+    }
+
+    private function getResult(string $hydrationMode)
+    {
+        $this->queryBuilder->setParams($this->arguments);
         if ($this->collection) {
-            return $this->queryBuilder->getResult($this->arguments, QueryBuilder::HYDRATE_OBJECT_READONLY);
+            return $this->queryBuilder->getResult($hydrationMode);
         }
 
-        return $this->queryBuilder->getOneOrNullResult($this->arguments,QueryBuilder::HYDRATE_OBJECT_READONLY);
+        return $this->queryBuilder->getOneOrNullResult($hydrationMode);
+
     }
 
     private function joinRelation(string $type, string $expression): void

+ 53 - 10
src/Query/QueryBuilder.php

@@ -37,9 +37,11 @@ final class QueryBuilder
 
     private array $joins = [];
     private array $joinsAlreadyAdded = [];
-
+    private ?int $firstResult = null;
     private ?int $maxResults = null;
 
+    private array $params = [];
+
     public function __construct(EntityManagerInterface $em, string $primaryKey = 'id')
     {
         $this->platform = $em->getPlatform();
@@ -49,27 +51,32 @@ final class QueryBuilder
         $this->primaryKey = $primaryKey;
     }
 
-    public function getResultIterator(array $parameters = [], string $hydrationMode = self::HYDRATE_OBJECT): iterable
+    public function getResultIterator(string $hydrationMode = self::HYDRATE_OBJECT): iterable
     {
-        foreach ($this->buildSqlQuery()->getResultIterator($parameters) as $item) {
+        foreach ($this->buildSqlQuery()->getResultIterator() as $item) {
             yield $this->hydrate([$item], $hydrationMode)[0];
         }
     }
 
-    public function getResult(array $parameters = [],  string $hydrationMode = self::HYDRATE_OBJECT): array
+    public function getResult(string $hydrationMode = self::HYDRATE_OBJECT): array
     {
-        return $this->hydrate($this->buildSqlQuery()->getResult($parameters), $hydrationMode);
+        return $this->hydrate($this->buildSqlQuery()->getResult(), $hydrationMode);
     }
 
-    public function getOneOrNullResult(array $parameters = [], string $hydrationMode = self::HYDRATE_OBJECT)
+    public function getOneOrNullResult(string $hydrationMode = self::HYDRATE_OBJECT)
     {
-        $item = $this->buildSqlQuery()->getOneOrNullResult($parameters);
+        $item = $this->buildSqlQuery()->getOneOrNullResult();
         if ($item === null) {
             return null;
         }
         return $this->hydrate([$item], $hydrationMode)[0];
     }
 
+    public function getCountResult(): int
+    {
+        return $this->buildSqlQuery()->count();
+    }
+
     public function select(string $entityName, array $properties = []): self
     {
         $this->select = [
@@ -115,6 +122,18 @@ final class QueryBuilder
         return $this;
     }
 
+    public function setParams(array $params): self
+    {
+        $this->params = $params;
+        return $this;
+    }
+
+    public function setParam(string $name, $value): self
+    {
+        $this->params[$name] = $value;
+        return $this;
+    }
+
     public function resetWhere(): self
     {
         $this->where = [];
@@ -127,6 +146,12 @@ final class QueryBuilder
         return $this;
     }
 
+    public function resetParams(): self
+    {
+        $this->params = [];
+        return $this;
+    }
+
     public function leftJoin(string $fromAliasOrEntityName, string $targetEntityName, ?string $property = null): self
     {
         return $this->join('LEFT', $fromAliasOrEntityName, $targetEntityName, $property);
@@ -137,6 +162,17 @@ final class QueryBuilder
         return $this->join('INNER', $fromAliasOrEntityName, $targetEntityName, $property);
     }
 
+    public function setFirstResult(?int $firstResult): self
+    {
+        if ($this->select === []) {
+            throw new LogicException(
+                'You must call the select() method first to define the main table for the query '
+            );
+        }
+        $this->firstResult = $firstResult;
+        return $this;
+    }
+
     public function setMaxResults(?int $maxResults): self
     {
         if ($this->select === []) {
@@ -332,9 +368,16 @@ final class QueryBuilder
             $joinQl->orderBy($this->resolveExpression($orderBy['sort']), $orderBy['order']);
         }
 
+        foreach ($this->params as $key => $value) {
+            $joinQl->setParam($key, $value);
+        }
+
         if ($this->maxResults) {
             $joinQl->setMaxResults($this->maxResults);
         }
+        if ($this->firstResult) {
+            $joinQl->setFirstResult($this->firstResult);
+        }
         return $joinQl;
     }
 
@@ -378,12 +421,12 @@ final class QueryBuilder
 
     private function hydrate(array $data, string $hydrationMode): array
     {
-        if ($hydrationMode === self::HYDRATE_ARRAY) {
-            $hydrator = new ArrayHydrator();
+        if ($hydrationMode === self::HYDRATE_OBJECT) {
+            $hydrator = new EntityHydrator($this->cache);
         } elseif ($hydrationMode === self::HYDRATE_OBJECT_READONLY) {
             $hydrator = new ReadOnlyEntityHydrator();
         } else {
-            $hydrator = new EntityHydrator($this->cache);
+            $hydrator = new ArrayHydrator();
         }
         $collection = [];
         foreach ($data as $item) {

+ 1 - 2
src/Types/BlobType.php → src/Types/BinaryType.php

@@ -2,7 +2,7 @@
 
 namespace PhpDevCommunity\PaperORM\Types;
 
-final class BlobType extends Type
+final class BinaryType extends Type
 {
     public function convertToDatabase($value): ?string
     {
@@ -28,6 +28,5 @@ final class BlobType extends Type
         }
 
         throw new \LogicException('Blob must be a binary string, got '.gettype($value));
-
     }
 }

+ 2 - 0
tests/Helper/DataBaseHelperTest.php

@@ -153,6 +153,8 @@ class DataBaseHelperTest
                 $lastId = $connection->getPdo()->lastInsertId();
                 $connection->executeStatement('UPDATE user SET last_post_id = ' . $lastId . ' WHERE id = ' . $post['user_id']);
             }
+
+
             $nbTags = $nbPosts * 2;
             for ($i = 0; $i < $nbTags; $i++) {
                 $id = uniqid('tag_', true);

+ 37 - 0
tests/RepositoryTest.php

@@ -222,12 +222,48 @@ class RepositoryTest extends TestCase
         }
 
         $em->clear();
+
+
+        $countUsers = $userRepository->findBy()
+            ->orderBy('id', 'DESC')
+            ->has('posts.tags')
+            ->has('posts.comments')
+            ->toCount();
+        $this->assertStrictEquals(4, $countUsers);
+
+
         $users = $userRepository->findBy()
             ->orderBy('id', 'DESC')
             ->has('posts.tags')
             ->has('posts.comments')
+            ->limit(2)
             ->toArray();
 
+        $this->assertEquals(4, $users[0]['id']);
+        $this->assertEquals(1, count($users[0]['posts']));
+        $this->assertEquals(3, $users[1]['id']);
+        $this->assertEquals(2, count($users[1]['posts']));
+
+        $users = $userRepository->findBy()
+            ->orderBy('id', 'DESC')
+            ->has('posts.tags')
+            ->has('posts.comments')
+            ->offset(2)
+            ->limit(2)
+            ->toArray();
+
+        $this->assertEquals(2, $users[0]['id']);
+        $this->assertEquals(2, count($users[0]['posts']));
+        $this->assertEquals(1, $users[1]['id']);
+        $this->assertEquals(2, count($users[1]['posts']));
+
+        $users = $userRepository->findBy()
+            ->orderBy('id', 'DESC')
+            ->has('posts.tags')
+            ->has('posts.comments')
+            ->toArray();
+
+
         $this->assertStrictEquals(4, count($users));
         foreach ($users as $user) {
             $this->assertTrue(is_array( $user['posts'] ));
@@ -317,6 +353,7 @@ class RepositoryTest extends TestCase
             ->with(PostTest::class)
             ->toObject();
 
+
         $this->assertStrictEquals( 5, $user->getId() );
         $this->assertEmpty($user->getPosts()->toArray());
         $this->assertNull($user->getLastPost());