EntityWasSaved   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 4
dl 0
loc 110
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B handle() 0 49 8
A saveOrTrashValue() 0 13 4
A trashValue() 0 13 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Rinvex\Attributes\Events;
6
7
use Exception;
8
use Rinvex\Attributes\Models\Value;
9
use Rinvex\Attributes\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 \Rinvex\Attributes\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 \Rinvex\Attributes\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