Issues (590)

src/Behaviors/Timestampable.php (2 issues)

1
<?php
2
3
namespace Bdf\Prime\Behaviors;
4
5
use Bdf\Prime\Mapper\Builder\FieldBuilder;
6
use Bdf\Prime\Repository\RepositoryEventsSubscriberInterface;
7
use Bdf\Prime\Repository\RepositoryInterface;
8
use Bdf\Prime\Types\TypeInterface;
9
10
/**
11
 * Timestampable
12
 *
13
 * The timestampable behavior allows you to keep track of the date of creation and last update of your model objects.
14
 *
15
 * @template E as object
16
 * @extends Behavior<E>
17
 */
18
final class Timestampable extends Behavior
19
{
20
    /**
21
     * The created at info.
22
     * Contains keys 'name' and 'alias'
23
     *
24
     * @var array
25
     */
26
    private $createdAt;
27
28
    /**
29
     * The updated at info.
30
     * Contains keys 'name' and 'alias'
31
     *
32
     * @var array
33
     */
34
    private $updatedAt;
35
36
    /**
37
     * The property type
38
     *
39
     * @var string
40
     */
41
    private $type;
42
43
    /**
44
     * Timestampable constructor.
45
     *
46
     * Set createdAt and updatedAt infos.
47
     * Could be a string: will be considered as the property name
48
     * Could be an array: should contains ['name', 'alias']
49
     *
50
     * Set to 'null|false' to deactivate the field management.
51
     *
52
     * @param bool|string|array $createdAt
53
     * @param bool|string|array $updatedAt
54
     * @param string            $type
55
     */
56 2
    public function __construct($createdAt = true, $updatedAt = true, $type = TypeInterface::DATETIME)
57
    {
58 2
        $this->type = $type;
59
60 2
        $this->createdAt = $this->getFieldInfos($createdAt, [
61 2
            'name'  => 'createdAt',
62 2
            'alias' => 'created_at',
63 2
        ]);
64
65 2
        $this->updatedAt = $this->getFieldInfos($updatedAt, [
66 2
            'name'  => 'updatedAt',
67 2
            'alias' => 'updated_at',
68 2
        ]);
69
    }
70
71
    /**
72
     * Get the field infos from option
73
     *
74
     * @param bool|string|array{0:string,1:string} $field
75
     * @param array $default
76
     *
77
     * @return null|array
78
     */
79 2
    private function getFieldInfos($field, array $default): ?array
80
    {
81 2
        if ($field === true) {
82 1
            return $default;
83
        }
84
85 1
        if (!$field) {
86
            return null;
87
        }
88
89 1
        if (is_string($field)) {
90 1
            return ['name'  => $field];
91
        }
92
93 1
        return [
94 1
            'name'  => $field[0],
95 1
            'alias' => $field[1],
96 1
        ];
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 2
    public function changeSchema(FieldBuilder $builder): void
103
    {
104 2
        if ($this->createdAt !== null && !isset($builder[$this->createdAt['name']])) {
105 2
            $builder->add($this->createdAt['name'], $this->type)->nillable();
106
107 2
            if (isset($this->createdAt['alias'])) {
108 2
                $builder->alias($this->createdAt['alias']);
109
            }
110
        }
111
112 2
        if ($this->updatedAt !== null && !isset($builder[$this->updatedAt['name']])) {
113 1
            $builder->add($this->updatedAt['name'], $this->type)->nillable();
114
115 1
            if (isset($this->updatedAt['alias'])) {
116 1
                $builder->alias($this->updatedAt['alias']);
117
            }
118
        }
119
    }
120
121
    /**
122
     * Before insert
123
     *
124
     * we set the new date created on the entity
125
     *
126
     * @param E $entity
0 ignored issues
show
The type Bdf\Prime\Behaviors\E was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
127
     * @param RepositoryInterface<E> $repository
128
     *
129
     * @return void
130
     */
131 4
    public function beforeInsert($entity, RepositoryInterface $repository): void
132
    {
133 4
        $now = $this->createDate($this->createdAt['name'], $repository);
134 4
        $repository->mapper()->hydrateOne($entity, $this->createdAt['name'], $now);
135
    }
136
137
    /**
138
     * Before update
139
     *
140
     * we set the new date updated on entity
141
     *
142
     * @param E $entity
143
     * @param RepositoryInterface<E> $repository
144
     * @param null|\ArrayObject $attributes
145
     *
146
     * @return void
147
     */
148 4
    public function beforeUpdate($entity, RepositoryInterface $repository, $attributes): void
149
    {
150 4
        if ($attributes !== null) {
151 1
            $attributes[] = $this->updatedAt['name'];
152
        }
153
154 4
        $now = $this->createDate($this->updatedAt['name'], $repository);
155 4
        $repository->mapper()->hydrateOne($entity, $this->updatedAt['name'], $now);
156
    }
157
158
    /**
159
     * Get the field infos from option
160
     *
161
     * @param string $name
162
     * @param RepositoryInterface<E> $repository
163
     *
164
     * @return int|\DateTimeInterface
165
     */
166 5
    private function createDate(string $name, RepositoryInterface $repository)
167
    {
168 5
        if ($this->type === TypeInterface::BIGINT) {
169
            return time();
170
        }
171
172
        /** @psalm-suppress UndefinedInterfaceMethod */
173 5
        $className = $repository->mapper()->info()->property($name)->phpType();
0 ignored issues
show
The method phpType() does not exist on Bdf\Prime\Mapper\Info\InfoInterface. It seems like you code against a sub-type of Bdf\Prime\Mapper\Info\InfoInterface such as Bdf\Prime\Mapper\Info\PropertyInfo. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

173
        $className = $repository->mapper()->info()->property($name)->/** @scrutinizer ignore-call */ phpType();
Loading history...
174 5
        return new $className();
175
    }
176
177
    /**
178
     * {@inheritdoc}
179
     */
180 2
    public function subscribe(RepositoryEventsSubscriberInterface $notifier): void
181
    {
182 2
        if ($this->createdAt !== null) {
183 2
            $notifier->inserting([$this, 'beforeInsert']);
184
        }
185
186 2
        if ($this->updatedAt !== null) {
187 2
            $notifier->updating([$this, 'beforeUpdate']);
188
        }
189
    }
190
}
191