DocWidget   F
last analyzed

Complexity

Total Complexity 83

Size/Duplication

Total Lines 669
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 217
dl 0
loc 669
rs 2
c 0
b 0
f 0
wmc 83

32 Methods

Rating   Name   Duplication   Size   Complexity  
A formIdent() 0 3 1
A showHeader() 0 3 1
A widgetType() 0 3 1
A objData() 0 3 1
A defaultDataSources() 0 3 1
A showTitle() 0 3 1
A isTabbable() 0 3 1
A defaultGroupType() 0 3 1
A sidebars() 0 42 4
A setDependencies() 0 6 1
A displayOptions() 0 7 2
A setShowTitle() 0 5 1
A formProperty() 0 24 4
A setFormData() 0 18 2
A setNextUrl() 0 20 4
A setShowHeader() 0 5 1
A setDisplayOptions() 0 9 2
C dataFromObject() 0 48 12
A setData() 0 7 1
A setFormIdent() 0 11 2
A formData() 0 7 2
A acceptedRequestData() 0 5 1
B formProperties() 0 35 7
A createFormProperty() 0 8 2
A defaultBackToObjectLabel() 0 7 2
A defaultDataSourceFilters() 0 5 1
A formIdentFallback() 0 9 2
A resolveDataSourceFilter() 0 22 4
A defaultDisplayOptions() 0 6 1
A action() 0 14 3
B updateFormGroup() 0 26 7
B createFormGroup() 0 29 7

How to fix   Complexity   

Complex Class

Complex classes like DocWidget often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DocWidget, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Charcoal\Admin\Widget;
4
5
use InvalidArgumentException;
6
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
7
use UnexpectedValueException;
8
9
// From Pimple
10
use Pimple\Container;
11
12
// From 'charcoal-ui'
13
use Charcoal\Ui\FormGroup\FormGroupInterface;
14
15
// From 'charcoal-admin'
16
use Charcoal\Admin\Docs\Widget\DocFormPropertyWidget;
17
use Charcoal\Admin\Ui\FormSidebarInterface;
18
use Charcoal\Admin\Ui\ObjectContainerInterface;
19
use Charcoal\Admin\Ui\ObjectContainerTrait;
20
use Charcoal\Admin\Widget\FormWidget;
21
22
/**
23
 * Object Admin Form
24
 */
25
class DocWidget extends FormWidget implements
26
    ObjectContainerInterface
27
{
28
    use ObjectContainerTrait;
29
30
    /**
31
     * @var string
32
     */
33
    protected $formIdent;
34
35
    /**
36
     * @var array
37
     */
38
    protected $formData;
39
40
    /**
41
     * @var boolean
42
     */
43
    protected $showHeader;
44
45
    /**
46
     * @var boolean
47
     */
48
    protected $showTitle;
49
50
    /**
51
     * Display options.
52
     *
53
     * @var array
54
     */
55
    private $displayOptions;
56
57
    /**
58
     * @param Container $container The DI container.
59
     * @return void
60
     */
61
    public function setDependencies(Container $container)
62
    {
63
        parent::setDependencies($container);
64
65
        // Fill ObjectContainerInterface dependencies
66
        $this->setModelFactory($container['model/factory']);
67
    }
68
69
    /**
70
     * For doc, disable tab view
71
     *
72
     * @return boolean
73
     */
74
    public function isTabbable()
75
    {
76
        return false;
77
    }
78
79
    /**
80
     * @return string
81
     */
82
    public function widgetType()
83
    {
84
        return 'charcoal/admin/widget/doc';
85
    }
86
87
    /**
88
     * Retrieve the default label for the form submission button.
89
     *
90
     * @return Translation|string|null
0 ignored issues
show
Bug introduced by
The type Charcoal\Admin\Widget\Translation was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
91
     */
92
    public function defaultBackToObjectLabel()
93
    {
94
        if ($this->objId()) {
95
            return $this->translator()->translation('Update');
96
        }
97
98
        return parent::defaultSubmitLabel();
99
    }
100
101
    /**
102
     * @param array $data The widget data.
103
     * @return ObjectForm Chainable
104
     */
105
    public function setData(array $data)
106
    {
107
        parent::setData($data);
108
109
        $this->mergeDataSources($data);
110
111
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Charcoal\Admin\Widget\DocWidget which is incompatible with the documented return type Charcoal\Admin\Widget\ObjectForm.
Loading history...
112
    }
113
114
    /**
115
     * @return FormSidebarInterface[]|\Generator
116
     */
117
    public function sidebars()
118
    {
119
        $objId = $this->obj()->id();
120
121
        if ($objId) {
122
            $translator = $this->translator();
123
124
            $template = 'charcoal/admin/widget/form.sidebar';
125
            $GLOBALS['widget_template'] = $template;
126
127
            $metadata = $this->obj()->metadata();
128
            $objType  = (isset($metadata['labels']['singular_name'])
129
                        ? $translator->translate($metadata['labels']['singular_name'])
130
                        : null);
131
132
            $label = $translator->translate('Back to {{name}} id: {{id}}');
133
            $label = strtr($label, [
134
                '{{name}}' => $objType ?: $this->obj()['obj_type'],
135
                '{{id}}'   => $this->obj()->id()
136
            ]);
137
138
            $url = 'object/edit?main_menu='.$this->obj()['main_menu'].'&obj_type={{obj_type}}&obj_id={{id}}';
139
140
            $out = [
141
                'title'       => $translator->translate('Actions'),
142
                'show_footer' => false,
143
                'actions'     => [
144
                    [
145
                        'label' => $label,
146
                        'url'   => $url
147
                    ]
148
                ]
149
            ];
150
151
            /** @var FormSidebarWidget $sidebar */
152
            $sidebar = $this->widgetFactory()->create(FormSidebarWidget::class);
153
            $sidebar->setViewController($this->viewController());
154
            $sidebar->setData($out);
155
156
            yield $sidebar;
157
158
            $GLOBALS['widget_template'] = '';
159
        }
160
    }
161
162
    /**
163
     * Set the key for the form structure to use.
164
     *
165
     * @param  string $formIdent The form identifier.
166
     * @throws InvalidArgumentException If the identifier is not a string.
167
     * @return self
168
     */
169
    public function setFormIdent($formIdent)
170
    {
171
        if (!is_string($formIdent)) {
0 ignored issues
show
introduced by
The condition is_string($formIdent) is always true.
Loading history...
172
            throw new InvalidArgumentException(
173
                'Form identifier must be a string'
174
            );
175
        }
176
177
        $this->formIdent = $formIdent;
178
179
        return $this;
180
    }
181
182
    /**
183
     * Retrieve a key for the form structure to use.
184
     *
185
     * If the form key is undefined, resolve a fallback.
186
     *
187
     * @return string
188
     */
189
    public function formIdentFallback()
190
    {
191
        $metadata = $this->obj()->metadata();
192
193
        if (isset($metadata['admin']['default_form'])) {
194
            return $metadata['admin']['default_form'];
195
        }
196
197
        return '';
198
    }
199
200
    /**
201
     * Retrieve the display options for the widget.
202
     *
203
     * @return array
204
     */
205
    public function displayOptions()
206
    {
207
        if (!$this->displayOptions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->displayOptions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
208
            $this->setDisplayOptions([]);
209
        }
210
211
        return $this->displayOptions;
212
    }
213
214
    /**
215
     * Set the display options for the widget.
216
     *
217
     * @param  array $options Display configuration.
218
     * @throws \RuntimeException If the display options are not an associative array.
219
     * @return self
220
     */
221
    public function setDisplayOptions(array $options)
222
    {
223
        if (!is_array($options)) {
0 ignored issues
show
introduced by
The condition is_array($options) is always true.
Loading history...
224
            throw new \RuntimeException('The display options must be an associative array.');
225
        }
226
227
        $this->displayOptions = array_merge($this->defaultDisplayOptions(), $options);
228
229
        return $this;
230
    }
231
232
    /**
233
     * Retrieve the default display options for the widget.
234
     *
235
     * @return array
236
     */
237
    public function defaultDisplayOptions()
238
    {
239
        return [
240
            'parented'    => false,
241
            'collapsible' => false,
242
            'collapsed'   => false
243
        ];
244
    }
245
246
    /**
247
     * Retrieve the key for the form structure to use.
248
     *
249
     * @return string
250
     */
251
    public function formIdent()
252
    {
253
        return $this->formIdent;
254
    }
255
256
    /**
257
     * @param string $url The next URL.
258
     * @throws InvalidArgumentException If argument is not a string.
259
     * @return ActionInterface Chainable
0 ignored issues
show
Bug introduced by
The type Charcoal\Admin\Widget\ActionInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
260
     */
261
    public function setNextUrl($url)
262
    {
263
        if (!is_string($url)) {
0 ignored issues
show
introduced by
The condition is_string($url) is always true.
Loading history...
264
            throw new InvalidArgumentException(
265
                'URL needs to be a string'
266
            );
267
        }
268
269
        if (!$this->obj()) {
270
            $this->nextUrl = $url;
0 ignored issues
show
Bug Best Practice introduced by
The property nextUrl does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
271
272
            return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Charcoal\Admin\Widget\DocWidget which is incompatible with the documented return type Charcoal\Admin\Widget\ActionInterface.
Loading history...
273
        }
274
275
        $obj = $this->obj();
276
        if ($obj->view()) {
0 ignored issues
show
Bug introduced by
The method view() does not exist on Charcoal\Model\ModelInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Charcoal\Queue\QueueItemInterface or Charcoal\Object\ContentInterface or Charcoal\Object\UserDataInterface or Charcoal\User\UserInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

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

276
        if ($obj->/** @scrutinizer ignore-call */ view()) {
Loading history...
277
            $this->nextUrl = $obj->render($url);
0 ignored issues
show
Bug introduced by
The method render() does not exist on Charcoal\Model\ModelInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Charcoal\Queue\QueueItemInterface or Charcoal\Object\ContentInterface or Charcoal\Object\UserDataInterface or Charcoal\User\UserInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

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

277
            /** @scrutinizer ignore-call */ 
278
            $this->nextUrl = $obj->render($url);
Loading history...
278
        }
279
280
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Charcoal\Admin\Widget\DocWidget which is incompatible with the documented return type Charcoal\Admin\Widget\ActionInterface.
Loading history...
281
    }
282
283
    /**
284
     * Form action (target URL)
285
     *
286
     * @return string Relative URL
287
     */
288
    public function action()
289
    {
290
        $action = parent::action();
291
292
        if (!$action) {
293
            $obj = $this->obj();
294
            $objId = $obj->id();
295
            if ($objId) {
296
                return 'object/edit';
297
            } else {
298
                return 'object/collection';
299
            }
300
        } else {
301
            return $action;
302
        }
303
    }
304
305
    /**
306
     * Retrieve the object's properties as form controls.
307
     *
308
     * @param  array $group An optional group to use.
309
     * @throws UnexpectedValueException If a property data is invalid.
310
     * @return DocFormPropertyWidget[]|Generator
311
     */
312
    public function formProperties(array $group = null)
313
    {
314
        $obj = $this->obj();
315
        $props = $obj->metadata()->properties();
316
317
        // We need to sort form properties by form group property order if a group exists
318
        if (!empty($group)) {
319
            $props = array_merge(array_flip($group), $props);
320
        }
321
322
        foreach ($props as $propertyIdent => $propertyMetadata) {
323
            if (method_exists($obj, 'filterPropertyMetadata')) {
324
                $propertyMetadata = $obj->filterPropertyMetadata($propertyMetadata, $propertyIdent);
325
            }
326
327
            if (!is_array($propertyMetadata)) {
328
                throw new UnexpectedValueException(sprintf(
329
                    'Invalid property data for "%1$s", received %2$s',
330
                    $propertyIdent,
331
                    (is_object($propertyMetadata) ? get_class($propertyMetadata) : gettype($propertyMetadata))
332
                ));
333
            }
334
335
            $propertyMetadata['display_options'] = $this->displayOptions();
336
337
            $formProperty = $this->createFormProperty();
338
            $formProperty->setViewController($this->viewController());
339
            $formProperty->setPropertyIdent($propertyIdent);
340
            $formProperty->setData($propertyMetadata);
341
            $formProperty->setPropertyVal($obj[$propertyIdent]);
342
343
            if ($formProperty->hidden()) {
344
                $this->hiddenProperties[$propertyIdent] = $formProperty;
345
            } else {
346
                yield $propertyIdent => $formProperty;
0 ignored issues
show
Bug Best Practice introduced by
The expression yield $propertyIdent => $formProperty returns the type Generator which is incompatible with the documented return type Charcoal\Admin\Docs\Widg...\Admin\Widget\Generator.
Loading history...
347
            }
348
        }
349
    }
350
351
    /**
352
     * Retrieve an object property as a form control.
353
     *
354
     * @param  string $propertyIdent An optional group to use.
355
     * @throws InvalidArgumentException If the property identifier is not a string.
356
     * @throws UnexpectedValueException If a property data is invalid.
357
     * @return DocFormPropertyWidget
358
     */
359
    public function formProperty($propertyIdent)
360
    {
361
        if (!is_string($propertyIdent)) {
0 ignored issues
show
introduced by
The condition is_string($propertyIdent) is always true.
Loading history...
362
            throw new InvalidArgumentException(
363
                'Property ident must be a string'
364
            );
365
        }
366
367
        $propertyMetadata = $this->obj()->metadata()->property($propertyIdent);
368
369
        if (!is_array($propertyMetadata)) {
370
            throw new UnexpectedValueException(sprintf(
371
                'Invalid property data for "%1$s", received %2$s',
372
                $propertyIdent,
373
                (is_object($propertyMetadata) ? get_class($propertyMetadata) : gettype($propertyMetadata))
374
            ));
375
        }
376
377
        $p = $this->createFormProperty();
378
        $p->setViewController($this->viewController());
379
        $p->setPropertyIdent($propertyIdent);
380
        $p->setData($propertyMetadata);
381
382
        return $p;
383
    }
384
385
    /**
386
     * @param array $data Optional. The form property data to set.
387
     * @return FormPropertyWidget
388
     */
389
    public function createFormProperty(array $data = null)
390
    {
391
        $p = $this->widgetFactory()->create(DocFormPropertyWidget::class);
392
        if ($data !== null) {
393
            $p->setData($data);
394
        }
395
396
        return $p;
397
    }
398
399
    /**
400
     * Set the form's auxiliary data.
401
     *
402
     * This method is called via {@see self::setData()} if a "form_data" parameter
403
     * is present on the HTTP request.
404
     *
405
     * @param array $data Data.
406
     * @return ObjectFormWidget Chainable.
407
     */
408
    public function setFormData(array $data)
409
    {
410
        $objData = $this->objData();
411
        $merged = array_replace_recursive($objData, $data);
412
413
        // Remove null values
414
        $merged = array_filter($merged, function ($val) {
415
            if ($val === null) {
416
                return false;
417
            }
418
419
            return true;
420
        });
421
422
        $this->formData = $merged;
423
        $this->obj()->setData($merged);
424
425
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Charcoal\Admin\Widget\DocWidget which is incompatible with the documented return type Charcoal\Admin\Widget\ObjectFormWidget.
Loading history...
426
    }
427
428
    /**
429
     * Retrieve the form's auxiliary  data.
430
     *
431
     * @return array
432
     */
433
    public function formData()
434
    {
435
        if (!$this->formData) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->formData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
436
            $this->formData = $this->objData();
437
        }
438
439
        return $this->formData;
440
    }
441
442
    /**
443
     * Object data.
444
     * @return array Object data.
445
     */
446
    public function objData()
447
    {
448
        return $this->obj()->data();
449
    }
450
451
    /**
452
     * @return boolean
453
     */
454
    public function showHeader()
455
    {
456
        return $this->showHeader;
457
    }
458
459
    /**
460
     * @param boolean $showHeader Is the Header to be shown.
461
     * @return self
462
     */
463
    public function setShowHeader($showHeader)
464
    {
465
        $this->showHeader = $showHeader;
466
467
        return $this;
468
    }
469
470
    /**
471
     * @return boolean
472
     */
473
    public function showTitle()
474
    {
475
        return $this->showTitle;
476
    }
477
478
    /**
479
     * @param boolean $showTitle Is the title to be shown.
480
     * @return self
481
     */
482
    public function setShowTitle($showTitle)
483
    {
484
        $this->showTitle = $showTitle;
485
486
        return $this;
487
    }
488
489
    /**
490
     * @return string
491
     */
492
    public function defaultGroupType()
493
    {
494
        return 'charcoal/admin/docs/widget/form-group/doc';
495
    }
496
497
    /**
498
     * Retrieve the default data sources (when setting data on an entity).
499
     *
500
     * @return string[]
501
     */
502
    protected function defaultDataSources()
503
    {
504
        return [ static::DATA_SOURCE_REQUEST, static::DATA_SOURCE_OBJECT ];
505
    }
506
507
    /**
508
     * Retrieve the default data source filters (when setting data on an entity).
509
     *
510
     * @return array
511
     */
512
    protected function defaultDataSourceFilters()
513
    {
514
        return [
515
            'request' => null,
516
            'object'  => 'array_replace_recursive'
517
        ];
518
    }
519
520
    /**
521
     * Retrieve the default data source filters (when setting data on an entity).
522
     *
523
     * Note: Adapted from {@see \Slim\CallableResolver}.
524
     *
525
     * @link   https://github.com/slimphp/Slim/blob/3.x/Slim/CallableResolver.php
526
     * @param  mixed $toResolve A callable used when merging data.
527
     * @return callable|null
528
     */
529
    protected function resolveDataSourceFilter($toResolve)
530
    {
531
        if (is_string($toResolve)) {
532
            $obj = $this->obj();
533
534
            $resolved = [ $obj, $toResolve ];
535
536
            // Check for Slim callable
537
            $callablePattern = '!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!';
538
            if (preg_match($callablePattern, $toResolve, $matches)) {
539
                $class = $matches[1];
540
                $method = $matches[2];
541
542
                if ($class === 'parent') {
543
                    $resolved = [ $obj, $class.'::'.$method ];
544
                }
545
            }
546
547
            $toResolve = $resolved;
548
        }
549
550
        return parent::resolveDataSourceFilter($toResolve);
551
    }
552
553
    /**
554
     * Retrieve the accepted metadata from the current request.
555
     *
556
     * @return array
557
     */
558
    protected function acceptedRequestData()
559
    {
560
        return array_merge(
561
            [ 'obj_type', 'obj_id', 'template' ],
562
            parent::acceptedRequestData()
563
        );
564
    }
565
566
    /**
567
     * Fetch metadata from the current object type.
568
     *
569
     * @return array
570
     */
571
    protected function dataFromObject()
572
    {
573
        $obj = $this->obj();
574
        $objMetadata = $obj->metadata();
575
        $adminMetadata = (isset($objMetadata['admin']) ? $objMetadata['admin'] : null);
576
577
        $formIdent = $this->formIdent();
578
        if (!$formIdent) {
579
            $formIdent = $this->formIdentFallback();
580
        }
581
582
        if ($formIdent && $obj->view()) {
583
            $formIdent = $obj->render($formIdent);
584
        }
585
586
        if (isset($adminMetadata['forms'][$formIdent])) {
587
            $objFormData = $adminMetadata['forms'][$formIdent];
588
        } else {
589
            $objFormData = [];
590
        }
591
592
        if (isset($objFormData['groups']) && isset($adminMetadata['form_groups'])) {
593
            $extraFormGroups = array_intersect(
594
                array_keys($adminMetadata['form_groups']),
595
                array_keys($objFormData['groups'])
596
            );
597
            foreach ($extraFormGroups as $groupIdent) {
598
                $objFormData['groups'][$groupIdent] = array_replace_recursive(
599
                    $adminMetadata['form_groups'][$groupIdent],
600
                    $objFormData['groups'][$groupIdent]
601
                );
602
            }
603
        }
604
605
        if (isset($objFormData['sidebars']) && isset($adminMetadata['form_sidebars'])) {
606
            $extraFormSidebars = array_intersect(
607
                array_keys($adminMetadata['form_sidebars']),
608
                array_keys($objFormData['sidebars'])
609
            );
610
            foreach ($extraFormSidebars as $sidebarIdent) {
611
                $objFormData['sidebars'][$sidebarIdent] = array_replace_recursive(
612
                    $adminMetadata['form_sidebars'][$sidebarIdent],
613
                    $objFormData['sidebars'][$sidebarIdent]
614
                );
615
            }
616
        }
617
618
        return $objFormData;
619
    }
620
621
    /**
622
     * Create a new form group widget.
623
     *
624
     * @see    \Charcoal\Ui\Form\FormTrait::createFormGroup()
625
     * @param  array|null $data Optional. The form group data to set.
626
     * @return FormGroupInterface
627
     */
628
    protected function createFormGroup(array $data = null)
629
    {
630
        $type = $this->defaultGroupType();
631
632
        if (isset($data['template'])) {
633
            unset($data['template']);
634
        }
635
636
        $group = $this->formGroupFactory()->create($type);
0 ignored issues
show
Bug introduced by
The method create() does not exist on Charcoal\Ui\Form\FormInterface. ( Ignorable by Annotation )

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

636
        $group = $this->formGroupFactory()->/** @scrutinizer ignore-call */ create($type);

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...
637
        $group->setForm($this);
638
639
        if ($group instanceof ObjectContainerInterface) {
640
            if (empty($group->objType())) {
641
                $group->setObjType($this->objType());
642
            }
643
644
            if (empty($group->objId()) && !empty($this->objId())) {
645
                $group->setObjId($this->objId());
646
            }
647
        }
648
649
        if ($data !== null) {
650
            $group->setData($data);
651
        }
652
653
        $group['show_header'] = $this->showHeader();
654
        $group['show_title'] = $this->showTitle();
655
656
        return $group;
657
    }
658
659
    /**
660
     * Update the given form group widget.
661
     *
662
     * @see    \Charcoal\Ui\Form\FormTrait::updateFormGroup()
663
     * @param  FormGroupInterface $group      The form group to update.
664
     * @param  array|null         $groupData  Optional. The new group data to apply.
665
     * @param  string|null        $groupIdent Optional. The new group identifier.
666
     * @return FormGroupInterface
667
     */
668
    protected function updateFormGroup(
669
        FormGroupInterface $group,
670
        array $groupData = null,
671
        $groupIdent = null
672
    ) {
673
        $group->setForm($this);
674
675
        if ($groupIdent !== null) {
676
            $group->setIdent($groupIdent);
677
        }
678
679
        if ($group instanceof ObjectContainerInterface) {
680
            if (empty($group->objType())) {
681
                $group->setObjType($this->objType());
682
            }
683
684
            if (empty($group->objId()) && !empty($this->objId())) {
685
                $group->setObjId($this->objId());
686
            }
687
        }
688
689
        if ($groupData !== null) {
690
            $group->setData($groupData);
691
        }
692
693
        return $group;
694
    }
695
}
696