• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mimmi20 / laminasviewrenderer-bootstrap-form / 12160906017

04 Dec 2024 01:37PM UTC coverage: 97.314%. Remained the same
12160906017

push

github

web-flow
Merge pull request #310 from mimmi20/updates

upgrade to PHP 8.3

60 of 61 new or added lines in 40 files covered. (98.36%)

38 existing lines in 7 files now uncovered.

2174 of 2234 relevant lines covered (97.31%)

25.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.77
/src/FormCollection.php
1
<?php
2

3
/**
4
 * This file is part of the mimmi20/laminasviewrenderer-bootstrap-form package.
5
 *
6
 * Copyright (c) 2021-2024, Thomas Mueller <mimmi20@live.de>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types = 1);
13

14
namespace Mimmi20\LaminasView\BootstrapForm;
15

16
use Laminas\Form\Element\Collection as CollectionElement;
17
use Laminas\Form\ElementInterface;
18
use Laminas\Form\Exception\DomainException;
19
use Laminas\Form\Exception\InvalidArgumentException;
20
use Laminas\Form\FieldsetInterface;
21
use Laminas\Form\FormInterface;
22
use Laminas\Form\LabelAwareInterface;
23
use Laminas\Form\View\Helper\FormCollection as BaseFormCollection;
24
use Laminas\View\Exception\RuntimeException;
25
use Laminas\View\Helper\HelperInterface;
26
use Override;
27

28
use function array_key_exists;
29
use function array_merge;
30
use function array_unique;
31
use function assert;
32
use function explode;
33
use function get_debug_type;
34
use function implode;
35
use function is_array;
36
use function is_string;
37
use function sprintf;
38
use function trim;
39

40
use const PHP_EOL;
41

42
final class FormCollection extends BaseFormCollection implements FormCollectionInterface
43
{
44
    use FormTrait;
45
    use HtmlHelperTrait;
46

47
    /**
48
     * Render a collection by iterating through all fieldsets and elements
49
     *
50
     * @throws DomainException
51
     * @throws RuntimeException
52
     * @throws InvalidArgumentException
53
     */
54
    #[Override]
22✔
55
    public function render(ElementInterface $element): string
56
    {
57
        if (!$element instanceof FieldsetInterface) {
22✔
58
            throw new InvalidArgumentException(
1✔
59
                sprintf(
1✔
60
                    '%s requires that the element is of type %s, but was %s',
1✔
61
                    __METHOD__,
1✔
62
                    FieldsetInterface::class,
1✔
63
                    get_debug_type($element),
1✔
64
                ),
1✔
65
            );
1✔
66
        }
67

68
        $markup         = '';
21✔
69
        $templateMarkup = '';
21✔
70
        $indent         = $this->getIndent();
21✔
71
        $baseIndent     = $indent;
21✔
72
        $asCard         = $element->getOption('as-card');
21✔
73

74
        if ($this->shouldWrap && $asCard) {
21✔
75
            $indent .= $this->getWhitespace(8);
4✔
76
        }
77

78
        if ($element instanceof CollectionElement && $element->shouldCreateTemplate()) {
21✔
UNCOV
79
            $templateMarkup = $this->renderTemplate($element, $indent);
×
80
        }
81

82
        $form     = $element->getOption('form');
21✔
83
        $layout   = $element->getOption('layout');
21✔
84
        $floating = $element->getOption('floating');
21✔
85

86
        try {
87
            $elementHelper = $this->getElementHelper();
21✔
88
        } catch (\RuntimeException $e) {
×
UNCOV
89
            throw new RuntimeException($e->getMessage(), 0, $e);
×
90
        }
91

92
        $fieldsetHelper = $this->getFieldsetHelper();
21✔
93

94
        foreach ($element->getIterator() as $elementOrFieldset) {
21✔
95
            assert($elementOrFieldset instanceof ElementInterface);
18✔
96

97
            $elementOrFieldset->setOption('was-validated', $element->getOption('was-validated'));
18✔
98

99
            if ($form !== null && !$elementOrFieldset->getOption('form')) {
18✔
100
                $elementOrFieldset->setOption('form', $form);
18✔
101
            }
102

103
            if ($layout !== null && !$elementOrFieldset->getOption('layout')) {
18✔
104
                $elementOrFieldset->setOption('layout', $layout);
18✔
105
            }
106

107
            if ($floating) {
18✔
108
                $elementOrFieldset->setOption('floating', true);
1✔
109
            }
110

111
            if (
112
                $element->getOption('show-required-mark')
18✔
113
                && $element->getOption('field-required-mark')
18✔
114
            ) {
115
                $elementOrFieldset->setOption('show-required-mark', true);
11✔
116
                $elementOrFieldset->setOption(
11✔
117
                    'field-required-mark',
11✔
118
                    $element->getOption('field-required-mark'),
11✔
119
                );
11✔
120
            }
121

122
            if ($elementOrFieldset instanceof FieldsetInterface) {
18✔
123
                if ($fieldsetHelper instanceof FormIndentInterface) {
1✔
124
                    $fieldsetHelper->setIndent($indent . $this->getWhitespace(4));
1✔
125
                }
126

127
                if ($fieldsetHelper instanceof BaseFormCollection) {
1✔
128
                    $fieldsetHelper->setShouldWrap($this->shouldWrap());
1✔
129

130
                    $markup .= $fieldsetHelper->render($elementOrFieldset) . PHP_EOL;
1✔
131
                }
132
            } else {
133
                $elementOrFieldset->setOption('fieldset', $element);
18✔
134

135
                if ($elementHelper instanceof FormIndentInterface) {
18✔
136
                    $elementHelper->setIndent($indent . $this->getWhitespace(4));
18✔
137
                }
138

139
                if ($elementHelper instanceof FormRenderInterface) {
18✔
140
                    $markup .= $elementHelper->render($elementOrFieldset) . PHP_EOL;
18✔
141
                }
142
            }
143
        }
144

145
        if (!$this->shouldWrap) {
21✔
UNCOV
146
            return $markup . $templateMarkup;
×
147
        }
148

149
        // Every collection is wrapped by a fieldset if needed
150
        $attributes = $element->getAttributes();
21✔
151

152
        if (!$this->getDoctypeHelper()->isHtml5()) {
21✔
153
            unset(
21✔
154
                $attributes['name'],
21✔
155
                $attributes['disabled'],
21✔
156
                $attributes['form'],
21✔
157
            );
21✔
158
        }
159

160
        $label      = $element->getLabel() ?? '';
21✔
161
        $legend     = '';
21✔
162
        $htmlHelper = $this->getHtmlHelper();
21✔
163

164
        if ($label !== '') {
21✔
165
            $label = $this->translateLabel($label);
21✔
166
            $label = $this->escapeLabel($element, $label);
21✔
167

168
            assert(is_string($label));
21✔
169

170
            if (
171
                $label !== '' && !$element->hasAttribute('id')
21✔
172
                || ($element instanceof LabelAwareInterface && $element->getLabelOption('always_wrap'))
21✔
173
            ) {
174
                $label = '<span>' . $label . '</span>';
21✔
175
            }
176

177
            $labelClasses    = [];
21✔
178
            $labelAttributes = $element->getOption('label_attributes') ?? [];
21✔
179

180
            assert(is_array($labelAttributes));
21✔
181

182
            if (array_key_exists('class', $labelAttributes)) {
21✔
183
                $labelClasses = explode(' ', (string) $labelAttributes['class']);
21✔
184
            }
185

186
            $labelAttributes['class'] = trim(implode(' ', array_unique($labelClasses)));
21✔
187

188
            if ($asCard) {
21✔
189
                $labelAttributes = $this->mergeFormAttributes(
4✔
190
                    $element,
4✔
191
                    'col_attributes',
4✔
192
                    ['card-title'],
4✔
193
                    $labelAttributes,
4✔
194
                );
4✔
195
            }
196

197
            $legend = PHP_EOL . $indent . $this->getWhitespace(4) . $htmlHelper->render(
21✔
198
                'legend',
21✔
199
                $labelAttributes,
21✔
200
                $label,
21✔
201
            );
21✔
202
        }
203

204
        if ($asCard) {
21✔
205
            $classes = ['card-body'];
4✔
206

207
            if (array_key_exists('class', $attributes) && is_string($attributes['class'])) {
4✔
208
                $classes = array_merge(
4✔
209
                    $classes,
4✔
210
                    explode(' ', $attributes['class']),
4✔
211
                );
4✔
212
            }
213

214
            $attributes['class'] = trim(implode(' ', array_unique($classes)));
4✔
215
        }
216

217
        $markup = $baseIndent . $htmlHelper->render(
21✔
218
            'fieldset',
21✔
219
            $attributes,
21✔
220
            $legend . PHP_EOL . $markup . $templateMarkup . $indent,
21✔
221
        );
21✔
222

223
        if ($asCard) {
21✔
224
            $markup = PHP_EOL . $baseIndent . $this->getWhitespace(4) . $htmlHelper->render(
4✔
225
                'div',
4✔
226
                $this->mergeAttributes($element, 'card_attributes', ['card']),
4✔
227
                PHP_EOL . $baseIndent . $this->getWhitespace(
4✔
228
                    4,
4✔
229
                ) . $markup . PHP_EOL . $baseIndent . $this->getWhitespace(
4✔
230
                    4,
4✔
231
                ),
4✔
232
            );
4✔
233

234
            $markup = $baseIndent . $htmlHelper->render(
4✔
235
                'div',
4✔
236
                $this->mergeAttributes($element, 'col_attributes', []),
4✔
237
                $markup . PHP_EOL . $baseIndent,
4✔
238
            );
4✔
239
        }
240

241
        return $markup;
21✔
242
    }
243

244
    /**
245
     * Only render a template
246
     *
247
     * @throws DomainException
248
     * @throws RuntimeException
249
     */
NEW
250
    #[Override]
×
251
    public function renderTemplate(CollectionElement $collection, string $indent = ''): string
252
    {
UNCOV
253
        $elementOrFieldset = $collection->getTemplateElement();
×
254

255
        if (!$elementOrFieldset instanceof ElementInterface) {
×
UNCOV
256
            return '';
×
257
        }
258

UNCOV
259
        $templateMarkup = '';
×
260

261
        if ($elementOrFieldset instanceof FieldsetInterface) {
×
262
            $fieldsetHelper = $this->getFieldsetHelper();
×
UNCOV
263
            assert($fieldsetHelper instanceof HelperInterface);
×
264

265
            if ($fieldsetHelper instanceof FormIndentInterface) {
×
UNCOV
266
                $fieldsetHelper->setIndent($indent . $this->getWhitespace(4));
×
267
            }
268

269
            if ($fieldsetHelper instanceof BaseFormCollection) {
×
UNCOV
270
                $fieldsetHelper->setShouldWrap($this->shouldWrap());
×
271

UNCOV
272
                $templateMarkup = $fieldsetHelper->render($elementOrFieldset) . PHP_EOL;
×
273
            }
274
        } else {
275
            try {
276
                $elementHelper = $this->getElementHelper();
×
277
            } catch (\RuntimeException $e) {
×
UNCOV
278
                throw new RuntimeException($e->getMessage(), 0, $e);
×
279
            }
280

UNCOV
281
            assert($elementHelper instanceof HelperInterface);
×
282

283
            if ($elementHelper instanceof FormIndentInterface) {
×
UNCOV
284
                $elementHelper->setIndent($indent . $this->getWhitespace(4));
×
285
            }
286

287
            if ($elementHelper instanceof FormRenderInterface) {
×
UNCOV
288
                $templateMarkup = $elementHelper->render($elementOrFieldset) . PHP_EOL;
×
289
            }
290
        }
291

UNCOV
292
        $templateAttrbutes = $collection->getOption('template_attributes') ?? [];
×
293

UNCOV
294
        assert(is_array($templateAttrbutes));
×
295

UNCOV
296
        $htmlHelper = $this->getHtmlHelper();
×
297

298
        return $indent . $this->getWhitespace(4) . $htmlHelper->render(
×
299
            'template',
×
300
            $templateAttrbutes,
×
301
            $templateMarkup . $indent,
×
UNCOV
302
        ) . PHP_EOL;
×
303
    }
304

305
    /**
306
     * If set to true, collections are automatically wrapped around a fieldset
307
     *
308
     * @throws void
309
     */
310
    #[Override]
22✔
311
    public function setShouldWrap(bool $wrap): self
312
    {
313
        $this->shouldWrap = $wrap;
22✔
314

315
        return $this;
22✔
316
    }
317

318
    /**
319
     * Get wrapped
320
     *
321
     * @throws void
322
     */
323
    #[Override]
2✔
324
    public function shouldWrap(): bool
325
    {
326
        return $this->shouldWrap;
2✔
327
    }
328

329
    /**
330
     * @param array<int, string> $classes
331
     *
332
     * @return array<string, string>
333
     *
334
     * @throws void
335
     */
336
    private function mergeAttributes(ElementInterface $element, string $optionName, array $classes = []): array
4✔
337
    {
338
        $attributes = $element->getOption($optionName) ?? [];
4✔
339
        assert(is_array($attributes));
4✔
340

341
        if (array_key_exists('class', $attributes)) {
4✔
UNCOV
342
            $classes = array_merge($classes, explode(' ', (string) $attributes['class']));
×
343

UNCOV
344
            unset($attributes['class']);
×
345
        }
346

347
        if ($classes) {
4✔
348
            $attributes['class'] = implode(' ', array_unique($classes));
4✔
349
        }
350

351
        return $attributes;
4✔
352
    }
353

354
    /**
355
     * @param array<int, string>    $classes
356
     * @param array<string, string> $attributes
357
     *
358
     * @return array<string, string>
359
     *
360
     * @throws void
361
     */
362
    private function mergeFormAttributes(
4✔
363
        ElementInterface $element,
364
        string $optionName,
365
        array $classes = [],
366
        array $attributes = [],
367
    ): array {
368
        $form = $element->getOption('form');
4✔
369
        assert(
4✔
370
            $form instanceof FormInterface || $form === null,
4✔
371
            sprintf(
4✔
372
                '$form should be an Instance of %s or null, but was %s',
4✔
373
                FormInterface::class,
4✔
374
                get_debug_type($form),
4✔
375
            ),
4✔
376
        );
4✔
377

378
        if ($form !== null) {
4✔
379
            $formAttributes = $form->getOption($optionName) ?? [];
4✔
380

381
            assert(is_array($formAttributes));
4✔
382

383
            if (array_key_exists('class', $formAttributes)) {
4✔
384
                $classes = array_merge(explode(' ', (string) $formAttributes['class']), $classes);
4✔
385

386
                unset($formAttributes['class']);
4✔
387
            }
388

389
            $attributes = [...$formAttributes, ...$attributes];
4✔
390
        }
391

392
        if ($classes) {
4✔
393
            $attributes['class'] = implode(' ', array_unique($classes));
4✔
394
        }
395

396
        return $attributes;
4✔
397
    }
398
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc