aboutsummaryrefslogtreecommitdiffhomepage
path: root/WpfTest/Model.php
blob: 26a7b495c2bc2a5d1c4a6b52b74fc44f79955711 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
namespace WpfTest;

abstract class Model {
    private static function mangleName(string $name): string {
        if ($name == 'self')
            return 'uri';
        $chars = str_split($name);
        $chars[0] = strtolower($chars[0]);
        for ($i = 0; $i < count($chars); $i++) {
            $c = $chars[$i];
            if (ctype_upper($c)) {
                array_splice($chars, $i, 1, ['_', strtolower($c)]);
            }
        }
        return implode($chars);
    }

    private static function unmangleName(string $name): string {
        if ($name == 'uri')
            return 'self';
        $chars = str_split($name);
        for ($i = 0; $i < count($chars); $i++) {
            if ($chars[$i] == '_') {
                array_splice($chars, $i, 2, [strtoupper($chars[$i + 1])]);
            }
        }
        return implode($chars);
    }

    public function toDbRow(): array {
        $refl = new \ReflectionObject($this);
        $props = $refl->getProperties();
        $result = [];
        foreach ($props as $p) {
            $result[self::mangleName($p->getName())] = $p->getValue();
        }
        return $result;
    }

    public static function fromDbRow(array|false $columns): ?static {
        if ($columns === false)
            return null;
        $obj = new static();
        $refl = new \ReflectionObject($obj);
        foreach (array_keys($columns) as $name) {
            $value = $columns[$name];
            $name = self::unmangleName($name);
            try {
                $obj->{$name} = $value;
            } catch (\TypeError $e) {
                $type = $refl->getProperty($name)->getType();
                if ($type == null || !is_a($type, \ReflectionNamedType::class))
                    throw $e;
                $obj->{$name} = new ($type->getName())($value);
            }
        }
        return $obj;
    }

    public static function findWhere(string $whereClause, array $parameters): ?static {
        $classNameParts = explode('\\', static::class);
        $className = $classNameParts[count($classNameParts) - 1];
        $tableName = self::mangleName($className);
        $stmt = Db::getInstance()->getPdo()->prepare("SELECT * FROM $tableName WHERE $whereClause");
        $stmt->execute($parameters);
        return static::fromDbRow($stmt->fetch(\PDO::FETCH_ASSOC));
    }

    public static function find(int $id): ?static {
        return static::findWhere('id = ?', [$id]);
    }
}