Issues (590)

src/Behaviors/SoftDeleteable.php (2 issues)

1
<?php
2
3
namespace Bdf\Prime\Behaviors;
4
5
use Bdf\Prime\Events;
6
use Bdf\Prime\Mapper\Builder\FieldBuilder;
7
use Bdf\Prime\Repository\EntityRepository;
8
use Bdf\Prime\Repository\RepositoryEventsSubscriberInterface;
9
use Bdf\Prime\Repository\RepositoryInterface;
10
use Bdf\Prime\Types\TypeInterface;
11
12
/**
13
 * Softdeleteable
14
 *
15
 * The soft deleteable behavior allows you to “soft delete” objects,
16
 * filtering them at SELECT time by marking them as with a timestamp,
17
 * but not explicitly removing them from the database.
18
 *
19
 * @template E as object
20
 * @implements BehaviorInterface<E>
21
 */
22
class SoftDeleteable implements BehaviorInterface
23
{
24
    /**
25
     * The deleted at info.
26
     * Contains keys 'name' and 'alias'
27
     *
28
     * @var array
29
     */
30
    protected $deleted;
31
32
    /**
33
     * The property type
34
     *
35
     * @var string
36
     */
37
    protected $type;
38
39
    /**
40
     * Softdeleteable constructor.
41
     *
42
     * Set deletedAt infos.
43
     * Could be a string: will be considered as the property name
44
     * Could be an array: should contains ['name', 'alias']
45
     *
46
     * @param bool|string|array $deleted
47
     * @param string            $type
48
     */
49 1
    public function __construct($deleted = true, $type = TypeInterface::DATETIME)
50
    {
51 1
        $this->type = $type;
52 1
        $this->deleted = $this->getFieldInfos($deleted);
53
    }
54
55
    /**
56
     * Get the field infos from option
57
     *
58
     * @param bool|string|array{0:string,1:string} $field
59
     *
60
     * @return array
61
     */
62 1
    private function getFieldInfos($field): array
63
    {
64 1
        if ($field === true) {
65 1
            return ['name' => 'deletedAt', 'alias' => 'deleted_at'];
66
        }
67
68 1
        if (is_string($field)) {
69 1
            return ['name'  => $field];
70
        }
71
72
        return [
73
            'name'  => $field[0],
74
            'alias' => $field[1],
75
        ];
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81 1
    public function changeSchema(FieldBuilder $builder): void
82
    {
83 1
        if (!isset($builder[$this->deleted['name']])) {
84 1
            $builder->add($this->deleted['name'], $this->type)->nillable();
85
86 1
            if (isset($this->deleted['alias'])) {
87 1
                $builder->alias($this->deleted['alias']);
88
            }
89
        }
90
    }
91
92
    /**
93
     * Before delete
94
     *
95
     * We stop the before delete event and update the deleted at date.
96
     *
97
     * @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...
98
     * @param EntityRepository<E> $repository
99
     *
100
     * @return bool
101
     */
102 4
    public function beforeDelete($entity, EntityRepository $repository): bool
103
    {
104
        // If the current delete is without constraints, we skip the soft delete management
105 4
        if ($repository->isWithoutConstraints()) {
106
            return true;
107
        }
108
109 4
        $now = $this->createDate($this->deleted['name'], $repository);
110
111 4
        $repository->mapper()->hydrateOne($entity, $this->deleted['name'], $now);
112 4
        $count = $repository->update($entity, [$this->deleted['name']]);
113
114 4
        $repository->notify(Events::POST_DELETE, [$entity, $repository, $count]);
115
116
        // Returns false to skip the delete management
117 4
        return false;
118
    }
119
120
    /**
121
     * Get the field infos from option
122
     *
123
     * @param string $name
124
     * @param RepositoryInterface<E> $repository
125
     *
126
     * @return \DateTimeInterface|int
127
     */
128 4
    private function createDate(string $name, RepositoryInterface $repository)
129
    {
130 4
        if ($this->type === TypeInterface::BIGINT) {
131
            return time();
132
        }
133
134
        /** @psalm-suppress UndefinedInterfaceMethod */
135 4
        $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

135
        $className = $repository->mapper()->info()->property($name)->/** @scrutinizer ignore-call */ phpType();
Loading history...
136 4
        return new $className();
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 1
    public function subscribe(RepositoryEventsSubscriberInterface $notifier): void
143
    {
144 1
        $notifier->deleting([$this, 'beforeDelete']);
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150 1
    public function constraints(): array
151
    {
152 1
        return [$this->deleted['name'] => null];
153
    }
154
}
155