Issues (590)

src/Behaviors/Blameable.php (1 issue)

Labels
Severity
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
 * Blameable
12
 *
13
 * The blameable behavior automates the update of username or user reference fields on the entities or documents.
14
 * It works similar to timestampable behavior.
15
 * It simply inserts the current user id into the fields created_by and updated_by.
16
 * That way every time a model gets created, updated or deleted, you can see who did it (or who blame for that).
17
 *
18
 * @template E as object
19
 * @extends Behavior<E>
20
 */
21
class Blameable extends Behavior
22
{
23
    /**
24
     * The user resolver
25
     *
26
     * @var callable
27
     */
28
    protected $userResolver;
29
30
    /**
31
     * The created by info.
32
     * Contains keys 'name' and 'alias'
33
     *
34
     * @var array
35
     */
36
    protected $createdBy;
37
38
    /**
39
     * The updated by info.
40
     * Contains keys 'name' and 'alias'
41
     *
42
     * @var array
43
     */
44
    protected $updatedBy;
45
46
    /**
47
     * The property type
48
     *
49
     * @var string
50
     */
51
    protected $type;
52
53
    /**
54
     * Blameable constructor.
55
     *
56
     * Set createdBy and updatedBy infos.
57
     * Could be a string: will be considered as the property name
58
     * Could be an array: should contains ['name', 'alias']
59
     *
60
     * Set to 'null|false' to deactivate the field management.
61
     *
62
     * @param callable $userResolver  The user name/identifier resolver
63
     * @param bool|string|array $createdBy
64
     * @param bool|string|array $updatedBy
65
     * @param string            $type
66
     */
67 1
    public function __construct(callable $userResolver, $createdBy = true, $updatedBy = true, $type = TypeInterface::STRING)
68
    {
69 1
        $this->userResolver = $userResolver;
70 1
        $this->type = $type;
71
72 1
        $this->createdBy = $this->getFieldInfos($createdBy, [
73 1
            'name'  => 'createdBy',
74 1
            'alias' => 'created_by',
75 1
        ]);
76
77 1
        $this->updatedBy = $this->getFieldInfos($updatedBy, [
78 1
            'name'  => 'updatedBy',
79 1
            'alias' => 'updated_by',
80 1
        ]);
81
    }
82
83
    /**
84
     * Get the field infos from option
85
     *
86
     * @param bool|string|array{0:string,1:string} $field
87
     * @param array $default
88
     *
89
     * @return null|array
90
     */
91 1
    private function getFieldInfos($field, array $default): ?array
92
    {
93 1
        if ($field === true) {
94 1
            return $default;
95
        }
96
97
        if (!$field) {
98
            return null;
99
        }
100
101
        if (is_string($field)) {
102
            return ['name'  => $field];
103
        }
104
105
        return [
106
            'name'  => $field[0],
107
            'alias' => $field[1],
108
        ];
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 1
    public function changeSchema(FieldBuilder $builder): void
115
    {
116 1
        if ($this->createdBy !== null && !isset($builder[$this->createdBy['name']])) {
117 1
            $builder->add($this->createdBy['name'], $this->type)->nillable();
118
119 1
            if (isset($this->createdBy['alias'])) {
120 1
                $builder->alias($this->createdBy['alias']);
121
            }
122
        }
123
124 1
        if ($this->updatedBy !== null && !isset($builder[$this->updatedBy['name']])) {
125 1
            $builder->add($this->updatedBy['name'], $this->type)->nillable();
126
127 1
            if (isset($this->updatedBy['alias'])) {
128 1
                $builder->alias($this->updatedBy['alias']);
129
            }
130
        }
131
    }
132
133
    /**
134
     * Before insert
135
     *
136
     * we set the user that created the entity
137
     *
138
     * @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...
139
     * @param RepositoryInterface<E> $repository
140
     *
141
     * @return void
142
     */
143 2
    public function beforeInsert($entity, RepositoryInterface $repository): void
144
    {
145 2
        $resolver = $this->userResolver;
146 2
        $repository->mapper()->hydrateOne($entity, $this->createdBy['name'], $resolver());
147
    }
148
149
    /**
150
     * Before update
151
     *
152
     * we set the user that updated the entity
153
     *
154
     * @param E $entity
155
     * @param RepositoryInterface<E> $repository
156
     * @param null|\ArrayObject $attributes
157
     *
158
     * @return void
159
     */
160 2
    public function beforeUpdate($entity, RepositoryInterface $repository, $attributes): void
161
    {
162 2
        if ($attributes !== null) {
163 1
            $attributes[] = $this->updatedBy['name'];
164
        }
165
166 2
        $resolver = $this->userResolver;
167 2
        $repository->mapper()->hydrateOne($entity, $this->updatedBy['name'], $resolver());
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173 1
    public function subscribe(RepositoryEventsSubscriberInterface $notifier): void
174
    {
175 1
        if ($this->createdBy !== null) {
176 1
            $notifier->inserting([$this, 'beforeInsert']);
177
        }
178
179 1
        if ($this->updatedBy !== null) {
180 1
            $notifier->updating([$this, 'beforeUpdate']);
181
        }
182
    }
183
}
184