Passed
Push — master ( 807ca0...642002 )
by Midori
01:31
created

AbstractRepository::getSetter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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 = '';
25
    protected array $foreignKeys = [];
26
    protected string $tableName = '';
27
    protected string $className = '';
28
29
    public function __construct(Database $db)
30
    {
31
        $this->db = $db;
32
    }
33
34
    /**
35
     * @throws ReflectionException
36
     */
37
    public function read(string $id): Item
38
    {
39
        if ($id) {
40
            $this->db->select($this->tableName)->where('id', $id)->execute();
41
        } else {
42
            $this->db->select($this->tableName)->execute();
43
        }
44
        return $this->className::fromArray($this->db->fetch());
45
    }
46
47
    public function readResultSet(QueryInterface $query): array
48
    {
49
        return ResultSet::getResultArray($this->db, $query);
50
    }
51
52
    /**
53
     * @return Item[]
54
     */
55
    public function readAll(?QueryInterface $query = null): array
56
    {
57
        if ($query !== null) {
58
            $db = $this->db->query($query);
59
        } else {
60
            $db = $this->db->select($this->tableName);
61
        }
62
63
        $db->execute();
64
        $items = $db->fetchAll();
65
        return array_map(function ($item) {
66
            $object = $this->className::fromArray($item);
67
            if (array_key_exists($this->primaryKey, $item)) {
68
                $object->{self::getSetter($this->primaryKey)}($item[$this->primaryKey]);
69
            }
70
71
            foreach ($this->foreignKeys as $key) {
72
                if (array_key_exists($key, $item)) {
73
                    $object->{self::getSetter($key)}($item[$key]);
74
                }
75
            }
76
77
            return $object;
78
        }, $items);
79
    }
80
81
    /**
82
     * @param Item $item
83
     * @throws ReflectionException
84
     */
85
    public function save($item): Item
86
    {
87
        $itemData = array_filter($item->toArray(), fn($item) => !is_array($item) && $item);
88
89
        if ($item->getId() !== null) {
90
            $id = $itemData['id'];
91
92
            unset($itemData['id']);
93
94
            $this->db->update($this->tableName, $itemData)->where('id', $id)->execute();
95
96
            return $this->read($id);
97
        }
98
99
        if ($this->db->insert($this->tableName, $itemData)->execute() === false) {
100
            throw new Exception('Not Found.');
101
        }
102
103
        $lastInsertId = $this->db->lastInsertId();
104
        $updatedItem = $this->db->select($this->tableName)->where('id', $lastInsertId)->fetch();
105
106
        $item = $this->className::fromArray($updatedItem);
107
        $item->setFromArray($updatedItem);
108
        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('id', $id)->execute();
116
            return $this->db->rowCount();
117
        }
118
        return 0;
119
    }
120
121
    private static function getSetter(string $arrayKey): string
122
    {
123
        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
    private static function makeCamel($kebab, $capitalizeFirstCharacter = false)
132
    {
133
        $str = str_replace('-', '', ucwords($kebab, '-'));
134
135
        if (!$capitalizeFirstCharacter) {
136
            $str = lcfirst($str);
137
        }
138
139
        return $str;
140
    }
141
}
142