Completed
Push — master ( 487926...07b583 )
by Mathieu
04:04
created

FormTrait::setFormGroupFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Charcoal\Ui\Form;
4
5
// Dependencies from `PHP`
6
use \Exception;
7
use \InvalidArgumentException;
8
9
use \Charcoal\Factory\FactoryInterface;
10
11
12
// Intra-module (`charcoal-ui`) dependencies
13
use \Charcoal\Ui\FormGroup\FormGroupInterface;
14
15
/**
16
 *
17
 */
18
trait FormTrait
19
{
20
    /**
21
     * @var string $action
22
     */
23
    private $action = '';
24
25
    /**
26
     * @var string $method
27
     */
28
    private $method = 'post';
29
30
    /**
31
     * @var string $l10nMode
32
     */
33
    private $l10nMode = 'loop_inputs';
34
35
    /**
36
     * @var FormGroupInterface[] $groups
37
     */
38
    protected $groups = [];
39
40
    /**
41
     * @var array $formData
42
     */
43
    private $formData = [];
44
45
    /**
46
     * @var MetadataInterface $metadata
47
     */
48
    private $metadata;
49
50
    /**
51
     * @var FactoryInterface $formGroupFactory
52
     */
53
    protected $formGroupFactory;
54
55
56
    /**
57
     * @var callable $groupCallback
58
     */
59
    private $groupCallback;
60
61
62
    /**
63
     * @param FormGroupFactory $factory A factory, to create customized form gorup objects.
64
     * @return FormInterface Chainable
65
     */
66
    public function setFormGroupFactory(FactoryInterface $factory)
67
    {
68
        $this->formGroupFactory = $factory;
69
        return $this;
70
    }
71
72
    /**
73
     * @throws Exception If the form group factory object was not set / injected.
74
     * @return FormGroupFactory
75
     */
76
    protected function formGroupFactory()
77
    {
78
        if ($this->formGroupFactory === null) {
79
            throw new Exception(
80
                'Form group factory was not set.'
81
            );
82
        }
83
        return $this->formGroupFactory;
84
    }
85
86
    /**
87
     * @param callable $cb The group callback.
88
     * @return FormInterface Chainable
89
     */
90
    public function setGroupCallback(callable $cb)
91
    {
92
        $this->groupCallback = $cb;
93
        return $this;
94
    }
95
96
    /**
97
     * @param string $action The "action" value, typically a URL.
98
     * @throws InvalidArgumentException If the action argument is not a string.
99
     * @return FormInterface Chainable
100
     */
101
    public function setAction($action)
102
    {
103
        if (!is_string($action)) {
104
            throw new InvalidArgumentException(
105
                'Action must be a string'
106
            );
107
        }
108
        $this->action = $action;
109
        return $this;
110
    }
111
112
    /**
113
     * @return string
114
     */
115
    public function action()
116
    {
117
        return $this->action;
118
    }
119
120
    /**
121
     * Set the method (forcing lowercase) to "post" or "get".
122
     *
123
     * @param string $method Either "post" or "get".
124
     * @throws InvalidArgumentException If the method is not post or get.
125
     * @return FormInterface Chainable
126
     */
127
    public function setMethod($method)
128
    {
129
        $method = strtolower($method);
130
        if (!in_array($method, ['post', 'get'])) {
131
            throw new InvalidArgumentException(
132
                'Method must be "post" or "get"'
133
            );
134
        }
135
        $this->method = $method;
136
        return $this;
137
    }
138
139
    /**
140
     * @return string Either "post" or "get".
141
     */
142
    public function method()
143
    {
144
        return $this->method;
145
    }
146
147
    /**
148
     * @param string $mode The l10n mode.
149
     * @return FormGroupInterface Chainable
150
     */
151
    public function setL10nMode($mode)
152
    {
153
        $this->l10nMode = $mode;
154
        return $this;
155
    }
156
157
    /**
158
     * @return string
159
     */
160
    public function l10nMode()
161
    {
162
        return $this->l10nMode;
163
    }
164
165
    /**
166
     * @param array $groups The groups structure.
167
     * @return FormInterface Chainable
168
     */
169
    public function setGroups(array $groups)
170
    {
171
        $this->groups = [];
172
        foreach ($groups as $groupIdent => $group) {
173
            $this->addGroup($groupIdent, $group);
174
        }
175
        return $this;
176
    }
177
178
    /**
179
     * @param string                   $groupIdent The group identifier.
180
     * @param array|FormGroupInterface $group      The group object or structure.
181
     * @throws InvalidArgumentException If the ident is not a string or the group not a valid object or structure.
182
     * @return FormInterface Chainable
183
     */
184
    public function addGroup($groupIdent, $group)
185
    {
186
        if (!is_string($groupIdent)) {
187
            throw new InvalidArgumentException(
188
                'Group ident must be a string'
189
            );
190
        }
191
192
        if (($group instanceof FormGroupInterface)) {
193
            $group->setForm($this);
194
            $group->setIdent($groupIdent);
195
            $this->groups[$groupIdent] = $group;
196
        } elseif (is_array($group)) {
197
            if (!isset($group['type'])) {
198
                $group['type'] = $this->defaultGroupType();
199
            }
200
            $g = $this->formGroupFactory()->create($group['type']);
201
            $g->setForm($this);
202
            $g->setData($group);
203
            $this->groups[$groupIdent] = $g;
204
        } else {
205
            throw new InvalidArgumentException(
206
                'Group must be a Form Group object or an array of form group options'
207
            );
208
        }
209
210
        return $this;
211
    }
212
213
    /**
214
     * @return string
215
     */
216
    public function defaultGroupType()
217
    {
218
        return 'charcoal/ui/form-group/generic';
219
    }
220
221
    /**
222
     * Form Group generator.
223
     *
224
     * @param callable $groupCallback Optional. Group callback.
225
     * @return FormGroupInterface[]
226
     */
227
    public function groups(callable $groupCallback = null)
0 ignored issues
show
Coding Style introduced by
groups 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...
228
    {
229
        $groups = $this->groups;
230
        uasort($groups, ['self', 'sortGroupsByPriority']);
231
232
        $groupCallback = isset($groupCallback) ? $groupCallback : $this->groupCallback;
233
234
        $i = 1;
235
        foreach ($groups as $group) {
236
            if (!$group->active()) {
237
                continue;
238
            }
239
240
            if (!$group->l10nMode()) {
241
                $group->setL10nMode($this->l10nMode());
242
            }
243
244
            if ($groupCallback) {
245
                $groupCallback($group);
246
            }
247
248
            $GLOBALS['widget_template'] = $group->template();
249
250
            if ($group->form()->isTab() && $i > 1) {
251
                $group->isHidden = true;
252
            }
253
            $i++;
254
255
            yield $group;
256
        }
257
258
    }
259
260
    /**
261
     * @return boolean
262
     */
263
    public function hasGroups()
264
    {
265
        return (count($this->groups) > 0);
266
    }
267
268
    /**
269
     * @return integer
270
     */
271
    public function numGroups()
272
    {
273
        return count($this->groups);
274
    }
275
276
    /**
277
     * @param array $formData The (pre-populated) form data, as [$key=>$val] array.
278
     * @return FormInterface Chainable
279
     */
280
    public function setFormData(array $formData)
281
    {
282
        $this->formData = $formData;
283
        return $this;
284
    }
285
286
    /**
287
     * @param string $key The form data key, or poperty identifier.
288
     * @param mixed  $val The form data value, for a given key.
289
     * @throws InvalidArgumentException If the key argument is not a string.
290
     * @return FormInterface Chainable
291
     */
292
    public function addFormData($key, $val)
293
    {
294
        if (!is_string($key)) {
295
            throw new InvalidArgumentException(
296
                'Can not add form data: Data key must be a string'
297
            );
298
        }
299
        $this->formData[$key] = $val;
300
        return $this;
301
    }
302
303
    /**
304
     * @return array
305
     */
306
    public function formData()
307
    {
308
        return $this->formData;
309
    }
310
311
    /**
312
     * To be called with uasort()
313
     *
314
     * @param FormGroupInterface $a First group object to sort.
315
     * @param FormGroupInterface $b Second group object to sort.
316
     * @return integer Sorting value: -1 or 1
317
     */
318 View Code Duplication
    protected static function sortGroupsByPriority(FormGroupInterface $a, FormGroupInterface $b)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
319
    {
320
        $a = $a->priority();
321
        $b = $b->priority();
322
323
        return ($a < $b) ? (-1) : 1;
324
    }
325
}
326