AbstractRepository::save()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4.0058

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 4
eloc 13
nc 3
nop 1
dl 0
loc 24
ccs 13
cts 14
cp 0.9286
crap 4.0058
rs 9.8333
c 2
b 0
f 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace midorikocak\nanodb;
6
7
use Exception;
8
use midorikocak\querymaker\QueryInterface;
9
use ReflectionException;
10
11
use function array_filter;
12
use function array_key_exists;
13
use function array_map;
14
use function is_array;
15
use function lcfirst;
16
use function preg_replace;
17
use function str_replace;
18
use function strtolower;
19
use function ucwords;
20
21
abstract class AbstractRepository implements RepositoryInterface
22
{
23
    protected Database $db;
24
    protected string $primaryKey = 'id';
25
    protected array $foreignKeys = [];
26
    protected string $tableName = '';
27
    protected string $className = '';
28
29 3
    public function __construct(Database $db)
30
    {
31 3
        $this->db = $db;
32 3
    }
33
34
    /**
35
     * @throws ReflectionException
36
     */
37 2
    public function read(string $id): Item
38
    {
39 2
        if ($id) {
40 2
            $this->db->select($this->tableName)->where($this->primaryKey, $id)->execute();
41
        } else {
42
            $this->db->select($this->tableName)->execute();
43
        }
44 2
        return $this->className::fromArray($this->db->fetch());
45
    }
46
47 1
    public function readResultSet(QueryInterface $query): array
48
    {
49 1
        return ResultSet::getResultArray($this->db, $query);
50
    }
51
52
    /**
53
     * @return Item[]
54
     */
55 1
    public function readAll(?QueryInterface $query = null): array
56
    {
57 1
        if ($query !== null) {
58
            $db = $this->db->query($query);
59
        } else {
60 1
            $db = $this->db->select($this->tableName);
61
        }
62
63 1
        $db->execute();
64 1
        $items = $db->fetchAll();
65 1
        return array_map(function ($item) {
66 1
            $object = $this->className::fromArray($item);
67 1
            if (array_key_exists($this->primaryKey, $item)) {
68 1
                $object->{self::getSetter($this->primaryKey)}($item[$this->primaryKey]);
69
            }
70
71 1
            foreach ($this->foreignKeys as $key) {
72 1
                if (array_key_exists($key, $item)) {
73
                    $object->{self::getSetter($key)}($item[$key]);
74
                }
75
            }
76
77 1
            return $object;
78 1
        }, $items);
79
    }
80
81
    /**
82
     * @param Item $item
83
     * @throws ReflectionException
84
     */
85 3
    public function save($item): Item
86
    {
87 3
        $itemData = array_filter($item->toArray(), fn($item) => !is_array($item) && $item);
88
89 3
        if ($item->getId() !== null) {
90 2
            $id = $itemData[$this->primaryKey];
91
92 2
            unset($itemData[$this->primaryKey]);
93
94 2
            $this->db->update($this->tableName, $itemData)->where($this->primaryKey, $id)->execute();
95
96 2
            return $this->read($id);
97
        }
98
99 3
        if ($this->db->insert($this->tableName, $itemData)->execute() === false) {
100
            throw new Exception('Not Found.');
101
        }
102
103 3
        $lastInsertId = $this->db->lastInsertId();
104 3
        $updatedItem = $this->db->select($this->tableName)->where($this->primaryKey, $lastInsertId)->fetch();
105
106 3
        $item = $this->className::fromArray($updatedItem);
107 3
        $item->setFromArray($updatedItem);
108 3
        return $item;
109
    }
110
111
    public function remove($item): int
112
    {
113
        $id = $item->getId();
114
        if ($id !== null) {
115
            $this->db->delete($this->tableName)->where($this->primaryKey, $id)->execute();
116
            return $this->db->rowCount();
117
        }
118
        return 0;
119
    }
120
121 1
    private static function getSetter(string $arrayKey): string
122
    {
123 1
        return 'set' . lcfirst(self::makeCamel($arrayKey));
124
    }
125
126
    private static function makeKebab($camel): string
127
    {
128
        return strtolower(preg_replace('%([A-Z])([a-z])%', '_\1\2', $camel));
129
    }
130
131 1
    private static function makeCamel($kebab, $capitalizeFirstCharacter = false): string
132
    {
133 1
        $str = str_replace('-', '', ucwords($kebab, '-'));
134 1
        $str = str_replace('_', '', ucwords($str, '_'));
135
136 1
        if (!$capitalizeFirstCharacter) {
137 1
            $str = lcfirst($str);
138
        }
139
140 1
        return $str;
141
    }
142
}
143