Completed
Push — master ( 17909b...b957b5 )
by Mikaël
18:52 queued 08:52
created

TranslatablePivotObserver::created()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace BBSLab\NovaTranslation\Models\Observers;
4
5
use BBSLab\NovaTranslation\Models\Contracts\IsTranslatable;
6
use BBSLab\NovaTranslation\Models\Locale;
7
use BBSLab\NovaTranslation\Models\Relations\BelongsToMany;
8
use BBSLab\NovaTranslation\Models\Translation;
9
use BBSLab\NovaTranslation\NovaTranslation;
10
use Exception;
11
use Illuminate\Database\Eloquent\Model;
12
use Illuminate\Database\Eloquent\Relations\Pivot;
13
use Illuminate\Support\Collection;
14
use ReflectionClass;
15
use ReflectionMethod;
16
17
class TranslatablePivotObserver
18
{
19
    protected function isPivotParentTranslatable(Pivot $pivot): bool
20
    {
21
        return $pivot->pivotParent instanceof IsTranslatable;
22
    }
23
24
    protected function guessRelationship(Pivot $pivot): ?BelongsToMany
25
    {
26
        try {
27
            $class = new ReflectionClass($pivot->pivotParent);
28
        } catch (Exception $exception) {
29
            return null;
30
        }
31
32
        $method = Collection::make($class->getMethods())
33
            ->filter(function (ReflectionMethod $method) use ($pivot) {
34
                if (! method_exists($type = $method->getReturnType(), 'getName')) {
35
                    return false;
36
                }
37
38
                if ($type->getName() !== BelongsToMany::class) {
39
                    return false;
40
                }
41
42
                return $pivot->pivotParent->{$method->getName()}()->getTable() === $pivot->getTable();
43
            })->first();
44
45
        if (empty($method)) {
46
            return null;
47
        }
48
49
        return $pivot->pivotParent->{$method->getName()}();
50
    }
51
52
    protected function getTranslatedKeys(Model $related, Collection $locales): array
53
    {
54
        if (! $related instanceof IsTranslatable) {
55
            return $locales->mapWithKeys(function (Locale $locale) use ($related) {
56
                return [$locale->iso => $related->getKey()];
57
            })->toArray();
58
        }
59
60
        return $related->translations()
61
            ->with('locale')
62
            ->get()
63
            ->mapWithKeys(function (Translation $translation) {
64
                return [$translation->locale->iso => $translation->translatable_id];
65
            })->toArray();
66
    }
67
68
    /**
69
     * Handle the Translatable "created" event.
70
     *
71
     * @param  \Illuminate\Database\Eloquent\Relations\Pivot  $pivot
72
     * @return void
73
     * @throws \Exception
74
     */
75
    public function created(Pivot $pivot)
76
    {
77
        $this->handlePivot($pivot);
78
    }
79
80
    /**
81
     * Handle the Translatable "deleted" event.
82
     *
83
     * @param  \Illuminate\Database\Eloquent\Relations\Pivot  $pivot
84
     * @return void
85
     * @throws \Exception
86
     */
87
    public function deleted(Pivot $pivot)
88
    {
89
        $this->handlePivot($pivot, 'delete');
90
    }
91
92
    protected function handlePivot(Pivot $pivot, $method = 'save')
93
    {
94
        if (! $this->isPivotParentTranslatable($pivot)) {
95
            return;
96
        }
97
98
        /** @var \BBSLab\NovaTranslation\Models\Contracts\IsTranslatable $parent */
99
        $parent = $pivot->pivotParent;
100
        $relationship = $this->guessRelationship($pivot);
101
102
        if (empty($relationship)) {
103
            return;
104
        }
105
106
        $related = $relationship->getRelated()
107
            ->newQuery()
108
            ->with('translations.locale')
109
            ->find($pivot->{$relationship->getRelatedPivotKeyName()});
110
111
        if (empty($related)) {
112
            return;
113
        }
114
115
        $others = $this->getTranslatedKeys($related, NovaTranslation::otherLocales());
116
117
        $parent->translations()->with(['locale', 'translatable'])
0 ignored issues
show
Documentation Bug introduced by
The method with does not exist on object<BBSLab\NovaTransl...ls\TranslationRelation>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
118
            ->get()
119
            ->each(function (Translation $translation) use ($relationship, $others, $method) {
120
                if ($key = data_get($others, $translation->locale->iso)) {
121
                    $relationship->newPivot([
122
                        $relationship->getForeignPivotKeyName() => $translation->translatable_id,
123
                        $relationship->getRelatedPivotKeyName() => $key,
124
                    ])->{$method}();
125
                }
126
            });
127
    }
128
}
129