Completed
Push — develop ( 168e99...0122be )
by
unknown
18:37 queued 07:11
created

Container::setForm()   C

Complexity

Conditions 7
Paths 48

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 23
rs 6.7272
cc 7
eloc 15
nc 48
nop 3
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
7
 * @license   MIT
8
 */
9
10
/** Core forms */
11
namespace Core\Form;
12
13
use Zend\Form\Element;
14
use Zend\Form\Exception;
15
use Zend\Form\FieldsetInterface;
16
use Zend\ServiceManager\ServiceLocatorAwareInterface;
17
use Zend\Stdlib\PriorityList;
18
use Zend\View\Renderer\PhpRenderer as Renderer;
19
use Core\Entity\EntityInterface;
20
use Zend\ServiceManager\ServiceLocatorInterface;
21
22
/**
23
 * Manages a group of formulars.
24
 *
25
 * The container is responsible for creating, populating and binding the formulars from or to
26
 * the corresponding entities.
27
 *
28
 * Formulars are lazy loaded. So it is possible to only retrieve one formular from the container
29
 * for asynchronous saving using ajax calls.
30
 *
31
 * @author Mathias Gelhausen <[email protected]>
32
 */
33
class Container extends Element implements
34
    DisableElementsCapableInterface,
35
    ServiceLocatorAwareInterface,
36
    FormParentInterface,
37
    \IteratorAggregate,
38
    \Countable
39
{
40
    /**
41
     * Available/Loaded forms or specification.
42
     * @var array
43
     */
44
    protected $forms = array();
45
    
46
    /**
47
     * Active formulars keys.
48
     *
49
     * Formulars which key is herein are included in the iterator.
50
     * @see getIterator()
51
     * @var array
52
     */
53
    protected $activeForms = array();
54
    
55
    /**
56
     * The form element manager.
57
     * @var \Zend\Form\FormElementManager
58
     */
59
    protected $formElementManager;
60
    
61
    /**
62
     * Entity to bind to the formulars.
63
     *
64
     * @var \Core\Entity\EntityInterface[]
65
     */
66
    protected $entities;
67
    
68
    /**
69
     * Parameters to pass to the formulars.
70
     *
71
     * @var array
72
     */
73
    protected $params = array();
74
75
    protected $parent;
76
77
    /**
78
     * {@inheritDoc}
79
     * @return Container
80
     * @see \Zend\ServiceManager\ServiceLocatorAwareInterface::setServiceLocator()
81
     */
82
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
83
    {
84
        $this->formElementManager = $serviceLocator;
0 ignored issues
show
Documentation Bug introduced by
$serviceLocator is of type object<Zend\ServiceManag...erviceLocatorInterface>, but the property $formElementManager was declared to be of type object<Zend\Form\FormElementManager>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
85
        return $this;
86
    }
87
88
    /**
89
     * Gets the FormElementManager
90
     *
91
     * @return \Zend\Form\FormElementManager
92
     */
93
    public function getServiceLocator()
94
    {
95
        return $this->formElementManager;
96
    }
97
98
    /**
99
     * Gets an iterator to iterate over the enabled formulars.
100
     *
101
     * @return \ArrayIterator
0 ignored issues
show
Documentation introduced by
Should the return type not be PriorityList?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
102
     * @see IteratorAggregate::getIterator()
103
     */
104
    public function getIterator()
105
    {
106
        $iterator = new PriorityList();
107
        $iterator->isLIFO(false);
108
109
        foreach ($this->activeForms as $key) {
110
            $spec = $this->forms[$key];
111
            $priority = isset($spec['priority']) ? $spec['priority'] : 0;
112
113
            $iterator->insert($key, $this->getForm($key), $priority);
114
        }
115
116
        return $iterator;
117
    }
118
    
119
    /**
120
     * Gets the count of enabled formulars
121
     *
122
     * @return int
123
     * @see Countable::count()
124
     */
125
    public function count()
126
    {
127
        return count($this->activeForms);
128
    }
129
130
    /**
131
     * @param bool $flag
132
     * @return $this
133
     */
134
    public function setIsDisableCapable($flag)
135
    {
136
        $this->options['is_disable_capable'] = $flag;
137
138
        return $this;
139
    }
140
141
    /**
142
     * @return bool
143
     */
144
    public function isDisableCapable()
145
    {
146
        return isset($this->options['is_disable_capable'])
147
               ? $this->options['is_disable_capable'] : true;
148
    }
149
150
    /**
151
     * @param bool $flag
152
     * @return $this
153
     */
154
    public function setIsDisableElementsCapable($flag)
155
    {
156
        $this->options['is_disable_elements_capable'] = $flag;
157
158
        return $this;
159
    }
160
161
    /**
162
     * @return bool
163
     */
164
    public function isDisableElementsCapable()
165
    {
166
        return isset($this->options['is_disable_elements_capable'])
167
               ? $this->options['is_disable_elements_capable'] : true;
168
    }
169
170
    /**
171
     * @param array $map
172
     */
173
    public function disableElements(array $map)
174
    {
175
        foreach ($map as $key => $name) {
176
            if (is_numeric($key)) {
177
                if (isset($this->forms[$name])) {
178
                    $form = $this->getForm($name);
179
                    if (false !== $form->getOption('is_disable_capable')) {
180
                        $this->disableForm($name);
181
                    }
182
                }
183
                continue;
184
            }
185
186
            if (!isset($this->forms[$key])) {
187
                continue;
188
            }
189
190
            if (isset($this->forms[$key]['__instance__'])) {
191
                $form = $this->forms[$key]['__instance__'];
192
193
                if ($form instanceof DisableElementsCapableInterface
194
                    && $form->isDisableElementsCapable()
195
                ) {
196
                    $form->disableElements($name);
197
                }
198
            }
199
            $this->forms[$key]['disable_elements'] = $name;
200
        }
201
    }
202
203
    public function setOptions($options)
204
    {
205
        parent::setOptions($options);
206
207
        if (isset($this->options['forms'])) {
208
            $this->setForms($this->options['forms']);
209
        }
210
211
        return $this;
212
    }
213
214
    /**
215
     * Sets formular parameters.
216
     *
217
     * @param array $params
218
     * @return \Core\Form\Container
219
     */
220
    public function setParams(array $params)
221
    {
222
        $this->params = array_merge($this->params, $params);
223
        
224
        foreach ($this->forms as $form) {
225
            if (isset($form['__instance__'])
226
                && is_object($form['__instance__'])
227
                && method_exists($form['__instance__'], 'setParams')
228
            ) {
229
                $form['__instance__']->setParams($params);
230
            }
231
        }
232
        return $this;
233
    }
234
    
235
    /**
236
     * Gets the formular parameters.
237
     *
238
     * @return array:
0 ignored issues
show
Documentation introduced by
The doc-type array: could not be parsed: Unknown type name "array:" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
239
     */
240
    public function getParams()
241
    {
242
        return $this->params;
243
    }
244
    
245
    /**
246
     * Sets a formular parameter.
247
     *
248
     * @param string $key
249
     * @param mixed $value
250
     * @return \Core\Form\Container
251
     */
252
    public function setParam($key, $value)
253
    {
254
        $this->params[$key] = $value;
255
        
256
        foreach ($this->forms as $form) {
257
            if (isset($form['__instance__'])
258
                && is_object($form['__instance__'])
259
                && method_exists($form['__instance__'], 'setParam')
260
            ) {
261
                $form['__instance__']->setParam($key, $value);
262
            }
263
        }
264
        return $this;
265
    }
266
    
267
    /**
268
     * Gets the value of a formular parameter.
269
     *
270
     * Returns the provided <b>$default</b> value or null, if parameter does
271
     * not  exist.
272
     *
273
     * @param string $key
274
     * @param mixed $default
275
     * @return mixed
276
     */
277
    public function getParam($key, $default = null)
278
    {
279
        return isset($this->params[$key]) ? $this->params[$key] : $default;
280
    }
281
282
    /**
283
     * Gets a specific formular.
284
     *
285
     * This formular will be created upon the first retrievement.
286
     * If created, the formular gets passed the formular parameters set in this container.
287
     *
288
     * @param string $key
289
     * @param bool $asInstance if set to false, the specification array is returned, and no instance created.
290
     *
291
     * @return null|\Core\Form\Container|\Zend\Form\FormInterface
292
     * @since 0,25 added $asInstance parameter
293
     */
294
    public function getForm($key, $asInstance = true)
295
    {
296
        if (false !== strpos($key, '.')) {
297
            list($key, $childKey) = explode('.', $key, 2);
298
            $container = $this->getForm($key);
299
            return $container->getForm($childKey);
0 ignored issues
show
Bug introduced by
The method getForm does only exist in Core\Form\Container, but not in Zend\Form\FormInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
300
        }
301
        
302
        if (!isset($this->forms[$key])) {
303
            return null;
304
        }
305
        
306
        $form = $this->forms[$key];
307
308
        if (!$asInstance) {
309
            return $form;
310
        }
311
312
        if (isset($form['__instance__']) && is_object($form['__instance__'])) {
313
            return $form['__instance__'];
314
        }
315
316
        $options = isset($form['options']) ? $form['options'] : array();
317 View Code Duplication
        if (!isset($options['name'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
318
            $options['name'] = isset($form['name']) ? $form['name'] : $key;
319
        }
320
        if (!isset($options['use_post_array'])) {
321
            $options['use_post_array'] = true;
322
        }
323
        if (!isset($options['use_files_array'])) {
324
            $options['use_files_array'] = false;
325
        }
326
327
        $formInstance = $this->formElementManager->get($form['type'], $options);
328
        $formInstance->setParent($this);
329
        if (isset($form['attributes'])) {
330
            $formInstance->setAttributes($form['attributes']);
331
        }
332
333
        $formName = '';
334
        if (!empty($this->parent)) {
335
            $name = $this->getName();
336
            if (!empty($name)) {
337
                $formName .= $name . '.';
338
            }
339
        }
340
        $formName .= $form['name'];
341
        $formInstance->setName($formName);
342
        $formAction = $formInstance->getAttribute('action');
343
344
        if (empty($formAction)) {
345
            $formInstance->setAttribute('action', '?form=' . $formName);
346
        }
347
348
        if (isset($form['label'])) {
349
            $formInstance->setLabel($form['label']);
350
        }
351
352
        if (isset($form['disable_elements'])
353
            && $formInstance instanceof DisableElementsCapableInterface
354
            && $formInstance->isDisableElementsCapable()
355
        ) {
356
            $formInstance->disableElements($form['disable_elements']);
357
        }
358
359
        $entity = $this->getEntity($form['entity']);
360
        if ($entity) {
361
            $this->mapEntity($formInstance, $entity, isset($form['property']) ? $form['property'] : $key);
0 ignored issues
show
Documentation introduced by
$formInstance is of type object|array, but the function expects a object<Zend\Form\FormInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
362
        }
363
364
        $formInstance->setParams($this->getParams());
365
366
        $this->forms[$key]['__instance__'] = $formInstance;
367
        $this->forms[$key]['options'] = $options;
368
        return $formInstance;
369
    }
370
371
    /**
372
     * Sets a form or form specification.
373
     *
374
     * if <b>$spec</b> is a string, it is used as form type, name is set to <b>$key</b>
375
     *
376
     * @param string       $key
377
     * @param string|array $spec
378
     * @param boolean      $enabled Should the formular be enabled or not
379
     *
380
     * @return self
381
     */
382
    public function setForm($key, $spec, $enabled = true)
383
    {
384
        if (!is_array($spec)) {
385
            $spec = array('type' => $spec, 'name' => $key);
386
        }
387
        if (!isset($spec['name'])) {
388
            $spec['name'] = $key;
389
        }
390
        if (!isset($spec['entity'])) {
391
            $spec['entity'] = '*';
392
        }
393
        
394
        $this->forms[$key] = $spec;
395
        if ($spec instanceof FormParentInterface) {
396
            $spec->setParent($this);
397
        }
398
        if ($enabled) {
399
            $this->enableForm($key);
400
        } elseif (true === $this->activeForms) {
401
            $this->activeForms = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type array of property $activeForms.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
402
        }
403
        return $this;
404
    }
405
    
406
    /**
407
     * Sets formulars or specifications.
408
     *
409
     * <b>$forms</b> must be in the format:
410
     * <pre>
411
     *    'name' => [spec]
412
     * </pre>
413
     *
414
     * <b>$spec</b> must be compatible with {@link setForm}.
415
     * Additionally you can include a key 'enabled' in the spec, which will override
416
     * <b>$enabled</b> only for the current formular.
417
     *
418
     * @param array $forms
419
     * @param boolean $enabled
420
     * @return \Core\Form\Container
421
     */
422
    public function setForms(array $forms, $enabled = true)
423
    {
424
        foreach ($forms as $key => $spec) {
425
            if (is_array($spec) && isset($spec['enabled'])) {
426
                $currentEnabled = $spec['enabled'];
427
                unset($spec['enabled']);
428
            } else {
429
                $currentEnabled = $enabled;
430
            }
431
            $this->setForm($key, $spec, $currentEnabled);
432
        }
433
        return $this;
434
    }
435
    
436
    /**
437
     * Enables a formular.
438
     *
439
     * Enabled formulars are included in the {@link getIterator()}
440
     *
441
     * Traverses in child containers through .dot-Notation.
442
     *
443
     * @param string $key
0 ignored issues
show
Documentation introduced by
Should the type for parameter $key not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
444
     * @return \Core\Form\Container
445
     */
446
    public function enableForm($key = null)
447
    {
448
        if (null === $key) {
449
            $this->activeForms = array_keys($this->forms);
450
            return $this;
451
        }
452
        
453
        if (!is_array($key)) {
454
            $key = array($key);
455
        }
456
        
457
        foreach ($key as $k) {
458
            if (false !== strpos($k, '.')) {
459
                // this seems not to be childkey.childform but actualkey.childkey
460
                list($childKey, $childForm) = explode('.', $k, 2);
461
                $child = $this->getForm($childKey);
462
                $child->enableForm($childForm);
0 ignored issues
show
Bug introduced by
The method enableForm does only exist in Core\Form\Container, but not in Zend\Form\FormInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
463
            } else {
464
                if (isset($this->forms[$k]) && !in_array($k, $this->activeForms)) {
465
                    $this->activeForms[] = $k;
466
                }
467
            }
468
        }
469
        
470
        return $this;
471
    }
472
473
    /**
474
     * Disables a formular.
475
     *
476
     * @param string $key
0 ignored issues
show
Documentation introduced by
Should the type for parameter $key not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
477
     *
478
     * @return self
479
     */
480
    public function disableForm($key = null)
481
    {
482
        if (null === $key) {
483
            $this->activeForms = array();
484
            return $this;
485
        }
486
        
487
        if (!is_array($key)) {
488
            $key = array($key);
489
        }
490
        
491
        foreach ($key as $k) {
492
            if (false !== strpos($k, '.')) {
493
                list($childKey, $childForm) = explode('.', $k, 2);
494
                $child = $this->getForm($childKey);
495
                $child->disableForm($childForm);
0 ignored issues
show
Bug introduced by
The method disableForm does only exist in Core\Form\Container, but not in Zend\Form\FormInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
496
            } elseif (isset($this->forms[$k]['__instance__'])) {
497
                unset($this->forms[$k]['__instance__']);
498
            }
499
        }
500
        $this->activeForms = array_filter(
501
            $this->activeForms,
502
            function ($item) use ($key) {
503
                return !in_array($item, $key);
504
            }
505
        );
506
        
507
        return $this;
508
    }
509
    
510
    /**
511
     * Sets the entity for formular binding.
512
     *
513
     * @param EntityInterface $entity
514
     * @return self
515
     */
516
    public function setEntity(EntityInterface $entity, $key='*')
517
    {
518
        $this->entities[$key] = $entity;
519
        
520
        foreach ($this->forms as $formKey => $form) {
521
            if (isset($form['__instance__']) && is_object($form['__instance__']) && $key == $form['entity']) {
522
                $this->mapEntity($form['__instance__'], $entity, isset($form['property']) ? $form['property'] : $formKey);
523
            }
524
        }
525
        return $this;
526
    }
527
528
529
    /**
530
     * Gets the entity.
531
     *
532
     * @return \Core\Entity\EntityInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be EntityInterface|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
533
     */
534
    public function getEntity($key='*')
535
    {
536
        return isset($this->entities[$key]) ? $this->entities[$key] : null;
537
    }
538
    
539
    /**
540
     * Maps entity property to forms or child containers.
541
     *
542
     * @param \Zend\Form\FormInterface $form
543
     * @param \Core\Entity\EntityInterface $entity
544
     * @param string $property
545
     * @return void
546
     */
547
    protected function mapEntity($form, $entity, $property)
548
    {
549
        if (false === $property) {
550
            return;
551
        }
552
553
        if (true === $property) {
554
            $mapEntity = $entity;
555
        } else if ($entity->notEmpty($property)) {
556
            $getter = "get$property";
557
            $mapEntity = $entity->$getter();
558
        } else {
559
            return;
560
        }
561
        
562
        if ($form instanceof Container) {
563
            $form->setEntity($mapEntity);
564
        } else {
565
            $form->bind($mapEntity);
566
        }
567
    }
568
569
    /**
570
     * Return isValid
571
     *
572
     * @return bool
573
     */
574
    public function isValid()
575
    {
576
        $isValid = true;
577
        foreach ($this->activeForms as $activeFormKey) {
578
            $activeForm = $this->getForm($activeFormKey);
579
            $isValid &= $activeForm->isValid();
580
        }
581
        return $isValid;
582
    }
583
584
    /**
585
     * if fieldsets there is get method to have access to any element by name
586
     * this method is similar
587
     * get('form') gets a form
588
     * get('element') gets an element, if an element has the same name as a form, the form get's first access
589
     * get('form.element') gets an element of a form, this is more efficent because it doesn't expand all forms in the container,
590
     *      but just the one adressed
591
     * @param $key string
592
     * @return null|\Zend\Form\ElementInterface
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null|\Zend\Form\ElementInterface?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
593
     */
594
    public function get($key)
595
    {
596
        $return   = null;
597
        $lastKey  = null;
598
        $searchIn = $this->activeForms;
599
        $keySplit = explode('.', $key);
600
601
        while (0 < count($keySplit)) {
602
            $lastKey = array_shift($keySplit);
603
            foreach ($searchIn as $activeFormKey) {
0 ignored issues
show
Bug introduced by
The expression $searchIn of type null|object<Core\Form\Co...rm\FormInterface>|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
604
                if ($lastKey == $activeFormKey) {
605
                    $searchIn = $this->getForm($activeFormKey);
606
                    unset($lastKey);
607
                    break;
608
                }
609
            }
610
        }
611
        if (!isset($lastKey) && !empty($keySplit)) {
612
            $lastKey = array_shift($keySplit);
613
        }
614
        if (isset($lastKey) && empty($keySplit)) {
615
            if ($searchIn instanceof FieldsetInterface) {
616
                // has reached a fieldset to search in
617
                $return = $searchIn->get($lastKey);
618
                unset($lastKey);
619
            } elseif (is_array($searchIn) || $searchIn instanceof Traversable) {
0 ignored issues
show
Bug introduced by
The class Core\Form\Traversable does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
620
                // is probably still in the container
621
                foreach ($searchIn as $activeKey) {
622
                    $activeForm = $this->getForm($activeKey);
623
                    if ($activeForm instanceof FieldsetInterface) {
624
                        $return = $activeForm->get($lastKey);
625
                    }
626
                }
627
            }
628
        }
629
        if (!isset($lastKey) && empty($keySplit) && !isset($return)) {
630
            $return = $searchIn;
631
        }
632
        return $return;
633
    }
634
635
    /**
636
     * @param $data
637
     * @return $this
638
     */
639
    public function setData($data)
640
    {
641
        $filteredData = array();
642
        foreach ($data as $key => $elem) {
643
            if (!array_key_exists($key, $this->params) && $key != 'formName') {
644
                $filteredData[$key] = $elem;
645
            }
646
            if ($key == 'formName' && is_string($elem)) {
647
                // you can activate a specific form with postData
648
                foreach ($this->activeForms as $activeFormKey) {
649
                    if ($activeFormKey == $elem) {
650
                        $this->enableForm($activeFormKey);
651
                    } else {
652
                        $this->disableForm($activeFormKey);
653
                    }
654
                }
655
            }
656
        }
657
        foreach ($this->activeForms as $activeFormKey) {
658
            $activeForm = $this->getForm($activeFormKey);
659
            $activeForm->setData($filteredData);
660
        }
661
        return $this;
662
    }
663
664
    /**
665
     * @param $parent
666
     * @return $this
667
     */
668
    public function setParent($parent)
669
    {
670
        $this->parent = $parent;
671
        return $this;
672
    }
673
674
    /**
675
     * @return mixed
676
     */
677
    public function getParent()
678
    {
679
        return $this->parent;
680
    }
681
682
683
    /**
684
     * @return bool
685
     */
686
    public function hasParent()
687
    {
688
        return isset($this->parent);
689
    }
690
691
    /**
692
     * @param Renderer $renderer
693
     * @return string
694
     */
695
    public function renderPre(Renderer $renderer)
0 ignored issues
show
Unused Code introduced by
The parameter $renderer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
696
    {
697
        return '';
698
    }
699
700
    /**
701
     * @param Renderer $renderer
702
     * @return string
703
     */
704
    public function renderPost(Renderer $renderer)
705
    {
706
        return '';
707
    }
708
709
    /**
710
     * get the actual active Form
711
     * @param bool $setDefault
712
     * @return mixed|null
713
     */
714
    public function getActiveFormActual($setDefault = true)
715
    {
716
        $key = null;
717
        if (!empty($this->activeForms)) {
718
            $key = $this->activeForms[0];
719
        }
720
        if (!isset($key) && $setDefault) {
721
            $formsAvailable = array_keys($this->forms);
722
            $key = array_shift($formsAvailable);
723
        }
724
        return $key;
725
    }
726
727
    /**
728
     * get the form before the actual active
729
     * @return null
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
730
     */
731 View Code Duplication
    public function getActiveFormPrevious()
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...
732
    {
733
        $key = null;
734
        $actualKey = $this->getActiveFormActual();
735
        if (isset($actualKey)) {
736
            $forms = array_keys($this->forms);
737
            $formsFlip =  array_flip($forms);
738
            $index = $formsFlip[$actualKey];
739
            if (0 < $index) {
740
                $key = $forms[$index-1];
741
            }
742
        }
743
        return $key;
744
    }
745
746
747
    /**
748
     * Gets the form after the actual active
749
     * @return null
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
750
     */
751 View Code Duplication
    public function getActiveFormNext()
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...
752
    {
753
        $key = null;
754
        $actualKey = $this->getActiveFormActual();
755
        if (isset($actualKey)) {
756
            $forms = array_keys($this->forms);
757
            $formsFlip =  array_flip($forms);
758
            $index = $formsFlip[$actualKey];
759
            if ($index < count($forms) - 1) {
760
                $key = $forms[$index+1];
761
            }
762
        }
763
        return $key;
764
    }
765
766
    /**
767
     * @param $key
768
     * @return string
769
     */
770
    public function getActionFor($key)
771
    {
772
        $form               = $this->forms[$key];
773
        $options            = isset($form['options']) ? $form['options'] : array();
774
775
        if (!isset($options['use_post_array'])) {
776
            $options['use_post_array'] = true;
777
        }
778
        if (!isset($options['use_files_array'])) {
779
            $options['use_files_array'] = false;
780
        }
781
782
        $formName     = (($name = $this->getName()) ? $name . '.' : '') . $form['name'];
783
        $action = '?form=' . $formName;
784
785
        return $action;
786
    }
787
}