Passed
Push — fix/media-validation ( 732083...34b116 )
by Ben
06:22
created

SavingFields::saveDocumentFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 2
1
<?php declare(strict_types=1);
2
3
namespace Thinktomorrow\Chief\Fields;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Str;
7
use Thinktomorrow\Chief\Fields\Types\Field;
8
use Thinktomorrow\Chief\Fields\Types\FieldType;
9
use Thinktomorrow\Chief\Fields\Types\FileField;
10
use Thinktomorrow\Chief\Fields\Types\ImageField;
11
use Thinktomorrow\Chief\Media\Application\FileFieldHandler;
12
use Thinktomorrow\Chief\Media\Application\ImageFieldHandler;
13
14
trait SavingFields
15
{
16
    // If there is a save<key>Field this has priority over the set<Key>Field methods
17
    protected $saveAssistantMethods = [];
18
    protected $saveMethods = [];
19
20
    protected $queued_translations = [];
21
22
    public function saveFields(Request $request)
23
    {
24
        foreach ($this->fieldsWithAssistantFields() as $field) {
0 ignored issues
show
Bug introduced by
It seems like fieldsWithAssistantFields() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

24
        foreach ($this->/** @scrutinizer ignore-call */ fieldsWithAssistantFields() as $field) {
Loading history...
25
26
            // Custom save methods
27
            if ($this->detectCustomSaveMethods($field)) {
28
                continue;
29
            }
30
31
            // Custom set methods - default is the generic setField() method.
32
            $methodName = 'set' . ucfirst(Str::camel($field->getKey())) . 'Field';
33
            (method_exists($this, $methodName))
34
                ? $this->$methodName($field, $request)
35
                : $this->setField($field, $request);
36
        }
37
38
        // Save the model
39
        $this->saveQueuedFields();
40
41
        $this->saveQueuedMethods($request);
42
43
        // Attach the updated model to our manager.
44
        $this->manage($this->model);
0 ignored issues
show
Bug introduced by
It seems like manage() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

44
        $this->/** @scrutinizer ignore-call */ 
45
               manage($this->model);
Loading history...
45
    }
46
47
    protected function detectCustomSaveMethods(Field $field): bool
48
    {
49
        $saveMethodByKey = 'save' . ucfirst(Str::camel($field->getKey())) . 'Field';
50
        $saveMethodByType = 'save' . ucfirst(Str::camel($field->getType()->get())) . 'Fields';
51
52
        foreach ([$saveMethodByKey, $saveMethodByType] as $saveMethod) {
53
54
            foreach ($this->assistants() as $assistant) {
0 ignored issues
show
Bug introduced by
It seems like assistants() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

54
            foreach ($this->/** @scrutinizer ignore-call */ assistants() as $assistant) {
Loading history...
55
                if (method_exists($assistant, $saveMethod)) {
56
                    $this->saveAssistantMethods[$field->getKey()] = ['field'     => $field,
57
                                                                     'method'    => $saveMethod,
58
                                                                     'assistant' => $assistant,
59
                    ];
60
61
                    return true;
62
                }
63
            }
64
65
            if (method_exists($this, $saveMethod)) {
66
                $this->saveMethods[$field->getKey()] = ['field' => $field, 'method' => $saveMethod];
67
68
                return true;
69
            }
70
        }
71
72
        return false;
73
    }
74
75
    private function saveQueuedMethods($request)
76
    {
77
        foreach ($this->saveAssistantMethods as $data) {
78
            $method = $data['method'];
79
            $data['assistant']->$method($data['field'], $request);
80
        }
81
82
        foreach ($this->saveMethods as $data) {
83
            $method = $data['method'];
84
            $this->$method($data['field'], $request);
85
        }
86
    }
87
88
    public function setField(Field $field, Request $request)
89
    {
90
        // Is field set as translatable?
91
        if ($field->isTranslatable()) {
0 ignored issues
show
Bug introduced by
The method isTranslatable() does not exist on Thinktomorrow\Chief\Fields\Types\Field. Since it exists in all sub-types, consider adding an abstract or default implementation to Thinktomorrow\Chief\Fields\Types\Field. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

91
        if ($field->/** @scrutinizer ignore-call */ isTranslatable()) {
Loading history...
92
            if (!$this->requestContainsTranslations($request)) {
0 ignored issues
show
Bug introduced by
It seems like requestContainsTranslations() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

92
            if (!$this->/** @scrutinizer ignore-call */ requestContainsTranslations($request)) {
Loading history...
93
                return;
94
            }
95
96
            // Make our media fields able to be translatable as well...
97
            if ($field->ofType(FieldType::FILE, FieldType::IMAGE)) {
98
                throw new \Exception('Cannot process the ' . $field->getKey() . ' media field. Currently no support for translatable media files. We should fix this!');
99
            }
100
101
            // Okay so this is a bit odd but since all translations are expected to be inside the trans
102
            // array, we can add all these translations at once. Just make sure to keep track of the
103
            // keys since this is what our translation engine requires as well for proper update.
104
            $this->queued_translations = $request->get('trans');
105
            $this->translation_columns[] = $field->getColumn();
0 ignored issues
show
Bug Best Practice introduced by
The property translation_columns does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
106
107
            return;
108
        }
109
110
        // By default we assume the key matches the attribute / column naming
111
        $this->model->{$field->getColumn()} = $request->get($field->getKey());
112
    }
113
114
    private function saveQueuedFields()
115
    {
116
        $this->model->save();
117
118
        // Translations
119
        if (!empty($this->queued_translations)) {
120
            $this->saveTranslations($this->queued_translations, $this->model, $this->translation_columns);
0 ignored issues
show
Bug introduced by
It seems like saveTranslations() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
            $this->/** @scrutinizer ignore-call */ 
121
                   saveTranslations($this->queued_translations, $this->model, $this->translation_columns);
Loading history...
121
        }
122
123
        return (new static($this->registration))->manage($this->model);
0 ignored issues
show
Unused Code introduced by
The call to Thinktomorrow\Chief\Fiel...ngFields::__construct() has too many arguments starting with $this->registration. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

123
        return (/** @scrutinizer ignore-call */ new static($this->registration))->manage($this->model);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
124
    }
125
126
    public function saveFileFields(FileField $field, Request $request)
127
    {
128
        app(FileFieldHandler::class)->handle($this->model, $field, $request);
129
    }
130
131
    public function saveImageFields(ImageField $field, Request $request)
132
    {
133
        app(ImageFieldHandler::class)->handle($this->model, $field, $request);
134
    }
135
}
136