1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Audit\Events; |
6
|
|
|
|
7
|
|
|
use Exception; |
8
|
|
|
use Pedreiro\Models\Value; |
9
|
|
|
use Pedreiro\Support\ValueCollection; |
10
|
|
|
use Illuminate\Database\Eloquent\Model as Entity; |
11
|
|
|
|
12
|
|
|
class EntityWasSaved |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* The trash collection. |
16
|
|
|
* |
17
|
|
|
* @var \Illuminate\Support\Collection |
18
|
|
|
*/ |
19
|
|
|
protected $trash; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Save values when an entity is saved. |
23
|
|
|
* |
24
|
|
|
* @param \Illuminate\Database\Eloquent\Model $entity |
25
|
|
|
* |
26
|
|
|
* @throws \Exception |
27
|
|
|
* |
28
|
|
|
* @return void |
29
|
|
|
*/ |
30
|
|
|
public function handle(Entity $entity): void |
31
|
|
|
{ |
32
|
|
|
$this->trash = $entity->getEntityAttributeValueTrash(); |
33
|
|
|
|
34
|
|
|
// Wrap the whole process inside database transaction |
35
|
|
|
$connection = $entity->getConnection(); |
36
|
|
|
$connection->beginTransaction(); |
37
|
|
|
|
38
|
|
|
try { |
39
|
|
|
foreach ($entity->getEntityAttributes() as $attribute) { |
40
|
|
|
if ($entity->relationLoaded($relation = $attribute->getAttribute('slug'))) { |
41
|
|
|
$relationValue = $entity->getRelationValue($relation); |
42
|
|
|
|
43
|
|
|
if ($relationValue instanceof ValueCollection) { |
|
|
|
|
44
|
|
|
foreach ($relationValue as $value) { |
45
|
|
|
// Set attribute value's entity_id since it's always null, |
46
|
|
|
// because when RelationBuilder::build is called very early |
47
|
|
|
$value->setAttribute('entity_id', $entity->getKey()); |
48
|
|
|
$this->saveOrTrashValue($value); |
49
|
|
|
} |
50
|
|
|
} elseif (! is_null($relationValue)) { |
51
|
|
|
// Set attribute value's entity_id since it's always null, |
52
|
|
|
// because when RelationBuilder::build is called very early |
53
|
|
|
$relationValue->setAttribute('entity_id', $entity->getKey()); |
54
|
|
|
$this->saveOrTrashValue($relationValue); |
55
|
|
|
} |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
if ($this->trash->count()) { |
60
|
|
|
// Fetch the first item's class to know the model used for deletion |
61
|
|
|
$class = get_class($this->trash->first()); |
62
|
|
|
|
63
|
|
|
// Let's batch delete all the values based on their ids |
64
|
|
|
$class::whereIn('id', $this->trash->pluck('id'))->delete(); |
65
|
|
|
|
66
|
|
|
// Now, empty the trash |
67
|
|
|
$this->trash = collect([]); |
68
|
|
|
} |
69
|
|
|
} catch (Exception $e) { |
70
|
|
|
// Rollback transaction on failure |
71
|
|
|
$connection->rollBack(); |
72
|
|
|
|
73
|
|
|
throw $e; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
// Commit transaction on success |
77
|
|
|
$connection->commit(); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Save or trash the given value according to it's content. |
82
|
|
|
* |
83
|
|
|
* @param \Pedreiro\Models\Value $value |
84
|
|
|
* |
85
|
|
|
* @return void |
86
|
|
|
*/ |
87
|
|
|
protected function saveOrTrashValue(Value $value): void |
88
|
|
|
{ |
89
|
|
|
// In order to provide flexibility and let the values have their own |
90
|
|
|
// relationships, here we'll check if a value should be completely |
91
|
|
|
// saved with its relations or just save its own current state. |
92
|
|
|
if (! is_null($value) && ! $this->trashValue($value)) { |
93
|
|
|
if ($value->shouldPush()) { |
94
|
|
|
$value->push(); |
95
|
|
|
} else { |
96
|
|
|
$value->save(); |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Trash the given value. |
103
|
|
|
* |
104
|
|
|
* @param \Pedreiro\Models\Value $value |
105
|
|
|
* |
106
|
|
|
* @return bool |
107
|
|
|
*/ |
108
|
|
|
protected function trashValue(Value $value): bool |
109
|
|
|
{ |
110
|
|
|
if (! is_null($value->getAttribute('content'))) { |
111
|
|
|
return false; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
if ($value->exists) { |
115
|
|
|
// Push value to the trash |
116
|
|
|
$this->trash->push($value); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return true; |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.