AbstractRepository::findOneBy()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 15
ccs 8
cts 8
cp 1
crap 3
rs 10
1
<?php
2
3
// ---------------------------------------------------------------------
4
//
5
//  Copyright (C) 2018-2024 Artem Rodygin
6
//
7
//  You should have received a copy of the MIT License along with
8
//  this file. If not, see <https://opensource.org/licenses/MIT>.
9
//
10
// ---------------------------------------------------------------------
11
12
namespace Linode\Internal;
13
14
use GuzzleHttp\Psr7\Response;
15
use Linode\Entity;
16
use Linode\EntityCollection;
17
use Linode\Exception\LinodeException;
18
use Linode\LinodeClient;
19
use Linode\RepositoryInterface;
20
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
21
22
/**
23
 * @internal An abstract Linode repository.
24
 */
25
abstract class AbstractRepository implements RepositoryInterface
26
{
27
    /**
28
     * @param LinodeClient $client Linode API client.
29
     */
30
    public function __construct(protected LinodeClient $client) {}
31
32 1
    public function find($id): ?Entity
33
    {
34 1
        $response = $this->client->get(sprintf('%s/%s', $this->getBaseUri(), $id));
35 1
        $contents = $response->getBody()->getContents();
36 1
        $json     = json_decode($contents, true);
37
38 1
        return $this->jsonToEntity($json);
39
    }
40
41 2
    public function findAll(string $orderBy = null, string $orderDir = self::SORT_ASC): EntityCollection
42
    {
43 2
        return $this->findBy([], $orderBy, $orderDir);
44
    }
45
46 2
    public function findBy(array $criteria, string $orderBy = null, string $orderDir = self::SORT_ASC): EntityCollection
47
    {
48 2
        if (null !== $orderBy) {
49 1
            $criteria['+order_by'] = $orderBy;
50 1
            $criteria['+order']    = $orderDir;
51
        }
52
53 2
        return new EntityCollection(
54 2
            fn (int $page) => $this->client->get($this->getBaseUri(), ['page' => $page], $criteria),
55 2
            fn (array $json) => $this->jsonToEntity($json)
56 2
        );
57
    }
58
59 3
    public function findOneBy(array $criteria): ?Entity
60
    {
61 3
        $collection = $this->findBy($criteria);
62
63 3
        if (0 === count($collection)) {
64 1
            return null;
65
        }
66
67 2
        if (1 !== count($collection)) {
68 1
            $errors = ['errors' => [['reason' => 'More than one entity was found']]];
69
70 1
            throw new LinodeException(new Response(LinodeClient::ERROR_BAD_REQUEST, [], json_encode($errors)));
71
        }
72
73 1
        return $collection->current();
74
    }
75
76 3
    public function query(string $query, array $parameters = [], string $orderBy = null, string $orderDir = self::SORT_ASC): EntityCollection
77
    {
78
        try {
79 3
            $parser   = new ExpressionLanguage();
80 3
            $compiler = new QueryCompiler();
81
82 3
            $query    = $compiler->apply($query, $parameters);
83 3
            $ast      = $parser->parse($query, $this->getSupportedFields())->getNodes();
84 3
            $criteria = $compiler->compile($ast);
85 1
        } catch (\Throwable $exception) {
86 1
            $errors = ['errors' => [['reason' => $exception->getMessage()]]];
87
88 1
            throw new LinodeException(new Response(LinodeClient::ERROR_BAD_REQUEST, [], json_encode($errors)));
89
        }
90
91 2
        return $this->findBy($criteria, $orderBy, $orderDir);
92
    }
93
94
    /**
95
     * Returns base URI to the repository-specific API.
96
     */
97
    abstract protected function getBaseUri(): string;
98
99
    /**
100
     * Returns list of all fields (entity properties) supported by the repository.
101
     *
102
     * @return string[]
103
     */
104
    abstract protected function getSupportedFields(): array;
105
106
    /**
107
     * Creates a repository-specific entity using specified JSON data.
108
     */
109
    abstract protected function jsonToEntity(array $json): Entity;
110
}
111