Passed
Push — master ( 5655bd...d18046 )
by
unknown
02:33
created

FormGroupTrait::conditionalLogic()   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 0
1
<?php
2
3
namespace Charcoal\Ui\FormGroup;
4
5
use InvalidArgumentException;
6
7
// From 'charcoal-ui'
8
use Charcoal\Ui\Form\FormInterface;
9
use Charcoal\Ui\FormInput\FormInputBuilder;
10
use Charcoal\Ui\FormInput\FormInputInterface;
11
use Charcoal\Ui\PrioritizableInterface;
12
13
/**
14
 * Provides an implementation of {@see \Charcoal\Ui\FormGroup\FormGroupInterface}.
15
 */
16
trait FormGroupTrait
17
{
18
    /**
19
     * Store a reference to the parent form widget.
20
     *
21
     * @var FormInterface
22
     */
23
    protected $form;
24
25
    /**
26
     * The group's collection of fields.
27
     *
28
     * @var FormInputInterface[]
29
     */
30
    private $inputs = [];
31
32
    /**
33
     * The input callback; called on every input.
34
     *
35
     * Callable signature: `function(FormInputInterface $input)`
36
     *
37
     * @var callable
38
     */
39
    private $inputCallback;
40
41
    /**
42
     * Store the builder instance for the current class.
43
     *
44
     * @var FormInputBuilder
45
     */
46
    protected $formInputBuilder;
47
48
    /**
49
     * The L10N display mode.
50
     *
51
     * @var string
52
     */
53
    private $l10nMode;
54
55
    /**
56
     * The group's identifier.
57
     *
58
     * @var string
59
     */
60
    private $ident;
61
62
    /**
63
     * The required Acl permissions fetch from form group.
64
     *
65
     * @var string[] $requiredAclPermissions
66
     */
67
    private $requiredAclPermissions = [];
68
69
    /**
70
     * One or many CSS classes for tab form group.
71
     *
72
     * @var string
73
     */
74
    private $tabCssClasses;
75
76
    /**
77
     * @var boolean
78
     */
79
    private $isHidden;
80
81
    /**
82
     * @var array|null
83
     */
84
    private $conditionalLogic;
85
86
    /**
87
     * Comparison function used by {@see uasort()}.
88
     *
89
     * @param  PrioritizableInterface $a Sortable entity A.
90
     * @param  PrioritizableInterface $b Sortable entity B.
91
     * @return integer Sorting value: -1 or 1.
92
     */
93
    abstract protected function sortItemsByPriority(
94
        PrioritizableInterface $a,
95
        PrioritizableInterface $b
96
    );
97
98
    /**
99
     * @param FormInputBuilder $builder The builder, to create customized form input objects.
100
     * @return FormGroupInterface Chainable
101
     */
102
    protected function setFormInputBuilder(FormInputBuilder $builder)
103
    {
104
        $this->formInputBuilder = $builder;
105
106
        return $this;
107
    }
108
109
    /**
110
     * @param callable $cb The input callback.
111
     * @return FormGroupInterface Chainable
112
     */
113
    public function setInputCallback(callable $cb)
114
    {
115
        $this->inputCallback = $cb;
116
117
        return $this;
118
    }
119
120
    /**
121
     * @param FormInterface $form The parent form object.
122
     * @return FormGroupInterface Chainable
123
     */
124
    public function setForm(FormInterface $form)
125
    {
126
        $this->form = $form;
127
128
        return $this;
129
    }
130
131
    /**
132
     * @return FormInterface
133
     */
134
    public function form()
135
    {
136
        return $this->form;
137
    }
138
139
    /**
140
     * @param string $mode The l10n mode.
141
     * @return FormGroupInterface Chainable
142
     */
143
    public function setL10nMode($mode)
144
    {
145
        $this->l10nMode = $mode;
146
147
        return $this;
148
    }
149
150
    /**
151
     * @return string
152
     */
153
    public function l10nMode()
154
    {
155
        return $this->l10nMode;
156
    }
157
158
    /**
159
     * @param array $inputs The group inputs.
160
     * @return FormGroupInterface Chainable
161
     */
162
    public function setInputs(array $inputs)
163
    {
164
        $this->inputs = [];
165
        foreach ($inputs as $inputIdent => $input) {
166
            $this->addInput($inputIdent, $input);
167
        }
168
169
        return $this;
170
    }
171
172
    /**
173
     * @param string                   $inputIdent The input identifier.
174
     * @param array|FormInputInterface $input      The input object or structure.
175
     * @throws InvalidArgumentException If the ident argument is not a string or if the input is not valid.
176
     * @return FormGroupInterface Chainable
177
     */
178
    public function addInput($inputIdent, $input)
179
    {
180
        if (!is_string($inputIdent)) {
181
            throw new InvalidArgumentException(
182
                'Group ident must be a string'
183
            );
184
        }
185
186
        if (($input instanceof FormInputInterface)) {
187
            $input->setForm($this->form);
0 ignored issues
show
Bug introduced by
The method setForm() does not exist on Charcoal\Ui\FormInput\FormInputInterface. Did you maybe mean setFormGroup()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
188
            $input->setFormGroup($this);
189
            $this->inputs[$inputIdent] = $input;
190
        } elseif (is_array($input)) {
191
            $g                         = $this->formInputBuilder->build($input);
192
            $this->inputs[$inputIdent] = $g;
193
        } else {
194
            throw new InvalidArgumentException(
195
                'Group must be a Form Group object or an array of form group options'
196
            );
197
        }
198
199
        return $this;
200
    }
201
202
    /**
203
     * Form Input generator.
204
     *
205
     * @param callable $inputCallback Optional. Input callback.
206
     * @return FormGroupInterface[]|Generator
207
     */
208
    public function inputs(callable $inputCallback = null)
0 ignored issues
show
Coding Style introduced by
inputs uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
209
    {
210
        $groups = $this->groups;
0 ignored issues
show
Bug introduced by
The property groups does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
211
        uasort($groups, [ $this, 'sortItemsByPriority' ]);
212
213
        $inputCallback = isset($inputCallback) ? $inputCallback : $this->inputCallback;
214
        foreach ($inputs as $input) {
0 ignored issues
show
Bug introduced by
The variable $inputs does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
215
            if (!$input->l10nMode()) {
216
                $input->setL10nMode($this->l10nMode());
217
            }
218
            if ($inputCallback) {
219
                $inputCallback($input);
220
            }
221
            $GLOBALS['widget_template'] = $input->template();
222
            yield $input->ident() => $input;
223
            $GLOBALS['widget_template'] = '';
224
        }
225
    }
226
227
    /**
228
     * Wether this group contains any inputs.
229
     *
230
     * @return boolean
231
     */
232
    public function hasInputs()
233
    {
234
        return (count($this->inputs) > 0);
235
    }
236
237
    /**
238
     * Get the number of inputs in this group.
239
     *
240
     * @return integer
241
     */
242
    public function numInputs()
243
    {
244
        return count($this->inputs);
245
    }
246
247
    /**
248
     * Set the identifier of the group.
249
     *
250
     * @param string $ident The group identifier.
251
     * @return self
252
     */
253
    public function setIdent($ident)
254
    {
255
        $this->ident = $ident;
256
257
        return $this;
258
    }
259
260
    /**
261
     * Retrieve the idenfitier of the group.
262
     *
263
     * @return string
264
     */
265
    public function ident()
266
    {
267
        return $this->ident;
268
    }
269
270
    /**
271
     * @param string|\string[] $classes Class or Classes for tab form group.
272
     * @return self
273
     */
274
    public function setTabCssClasses($classes)
275
    {
276
        if (is_string($classes)) {
277
            $this->tabCssClasses = $classes;
278
        }
279
280
        if (is_array($classes)) {
281
            $this->tabCssClasses = implode(' ', $classes);
282
        }
283
284
        return $this;
285
    }
286
287
    /**
288
     * @return string
289
     */
290
    public function tabCssClasses()
291
    {
292
        return $this->tabCssClasses;
293
    }
294
295
    /**
296
     * @return boolean
297
     */
298
    public function isHidden()
299
    {
300
        return $this->isHidden;
301
    }
302
303
    /**
304
     * @param  boolean $isHidden Hidden (TRUE) or shown (FALSE).
305
     * @return self
306
     */
307
    public function setIsHidden($isHidden)
308
    {
309
        $this->isHidden = $isHidden;
310
311
        return $this;
312
    }
313
314
    /**
315
     * @return array|null
316
     */
317
    public function conditionalLogic()
318
    {
319
        return $this->conditionalLogic;
320
    }
321
322
    /**
323
     * @param array|null $conditionalLogic ConditionalLogic for FormGroupWidget.
324
     * @return self
325
     */
326
    public function setConditionalLogic($conditionalLogic)
327
    {
328
        if ($conditionalLogic && is_array($conditionalLogic)) {
329
            foreach ($conditionalLogic as &$condition) {
330
                $prop = $this->form()->formProperty($condition['property']);
0 ignored issues
show
Bug introduced by
The method formProperty() does not seem to exist on object<Charcoal\Ui\Form\FormInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
331
                $condition['input_id'] = $prop->input()->inputId();
332
            }
333
        }
334
335
        $this->conditionalLogic = [
336
            $this->widgetId() => $conditionalLogic
0 ignored issues
show
Bug introduced by
It seems like widgetId() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
337
        ];
338
339
        return $this;
340
    }
341
}
342