From 25ae1dbc1b8675ef38798ff4518ac8fe96a30109 Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Tue, 1 Dec 2020 22:48:03 +0100 Subject: [PATCH 01/14] WIP --- README.md | 6 +- docs/api/components.md | 3 + docs/api/types.md | 14 +-- src/Components/ComponentAbstract.php | 41 ++++---- src/Components/Form/InputEmail.php | 2 +- src/Components/Form/InputPassword.php | 2 +- src/Components/Form/InputTel.php | 2 +- .../Buttons/Abstracts/ButtonTestAbstract.php | 8 +- .../Buttons/Abstracts/SubmitTestAbstract.php | 14 +-- .../Abstracts/InputCheckableTestAbstract.php | 49 +++++++--- .../Form/Abstracts/InputFileTestAbstract.php | 24 +++-- .../Form/Abstracts/InputRadioTestAbstract.php | 49 +++++++--- .../Unit/Form/Abstracts/InputTestAbstract.php | 93 ++++++++++++++----- .../Form/Abstracts/SelectTestAbstract.php | 23 ++++- .../Form/Abstracts/TemporalTestAbstract.php | 2 +- .../Form/Abstracts/TextareaTestAbstract.php | 2 +- .../Media/Abstracts/ImageTestAbstract.php | 8 +- .../Media/Abstracts/MediaTestAbstract.php | 10 +- .../Media/Abstracts/VideoTestAbstract.php | 2 +- 19 files changed, 244 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index 30da35df..d3975e78 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@

-Save time and take advantage of an extended set of ready-to-use and fully customizable bootstrap form components. +Save time and take advantage of a set of dynamical, ready-to-use and fully customizable bootstrap form components. Found this package helpful? Please consider supporting my work! @@ -82,10 +82,10 @@ And get this HTML generated for you: Call this component in your view: ```blade -{{-- helper style --}} +{{-- Helper style --}} {{ inputText()->name('title')->localized(['fr', 'en']) }} -{{-- facade style --}} +{{-- Facade style --}} {{ InputText::name('title')->localized(['fr', 'en']) }} ``` diff --git a/docs/api/components.md b/docs/api/components.md index 69cc56ae..50d556f2 100644 --- a/docs/api/components.md +++ b/docs/api/components.md @@ -61,6 +61,7 @@ * Prepend : `` * Label positioned above : `config('bootstrap-components.form.labelPositionedAbove')` +* Component HTML attributes: `autocomplete="on"` * Container classes : : `form-group` * Display success : `config('bootstrap-components.form.formValidation.displaySuccess')` * Display failure : `config('bootstrap-components.form.formValidation.displayFailure')` @@ -77,6 +78,7 @@ * Prepend : `` * Label positioned above : `config('bootstrap-components.form.labelPositionedAbove')` +* Component HTML attributes: `autocomplete="on"` * Container classes : : `form-group` * Display success : `config('bootstrap-components.form.formValidation.displaySuccess')` * Display failure : `config('bootstrap-components.form.formValidation.displayFailure')` @@ -109,6 +111,7 @@ * Prepend : `` * Label positioned above : `config('bootstrap-components.form.labelPositionedAbove')` +* Component HTML attributes: `autocomplete="on"` * Container classes : : `form-group` * Display success : `config('bootstrap-components.form.formValidation.displaySuccess')` * Display failure : `config('bootstrap-components.form.formValidation.displayFailure')` diff --git a/docs/api/types.md b/docs/api/types.md index f9bb15b9..548a51a5 100644 --- a/docs/api/types.md +++ b/docs/api/types.md @@ -21,21 +21,21 @@ |---|---|---| | containerId(string $containerId): self | No | Set the component container id. | | componentId(string $componentId): self | No | Set the component id. | -| containerClasses(array $containerClasses): self | No | Set the component container classes. | -| componentClasses(array $componentClasses): self | No | Set the component classes. | -| containerHtmlAttributes(array $containerHtmlAttributes): self | No | Set the component container HTML attributes. | -| componentHtmlAttributes(array $componentHtmlAttributes): self | No | Set the component HTML attributes. | +| componentClasses(array $componentClasses): self | No | Set the component classes. The given classes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | +| containerClasses(array $containerClasses): self | No | Set the component container classes. The given classes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | +| componentHtmlAttributes(array $componentHtmlAttributes): self | No | Set the component HTML attributes. The given HTML attributes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | +| containerHtmlAttributes(array $containerHtmlAttributes): self | No | Set the component container HTML attributes. The given HTML attributes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | **Usage** ```php - ->containerId('container-id') ->componentId('component-id') - ->containerClasses(['container', 'classes']) + ->containerId('container-id') ->componentClasses(['component', 'classes']) - ->containerHtmlAttributes(['container', 'html', 'attributes']) + ->containerClasses(['container', 'classes']) ->componentHtmlAttributes(['component', 'html', 'attributes']); + ->containerHtmlAttributes(['container', 'html', 'attributes']) ``` ## FormAbstract diff --git a/src/Components/ComponentAbstract.php b/src/Components/ComponentAbstract.php index 4cadf70b..b82c2995 100644 --- a/src/Components/ComponentAbstract.php +++ b/src/Components/ComponentAbstract.php @@ -27,56 +27,57 @@ public function __construct() $this->type = $this->setType(); $this->view = $this->setView(); $this->componentClasses = $this->setComponentClasses(); - $this->componentHtmlAttributes = $this->setComponentHtmlAttributes(); $this->containerClasses = $this->setContainerClasses(); + $this->componentHtmlAttributes = $this->setComponentHtmlAttributes(); $this->containerHtmlAttributes = $this->setContainerHtmlAttributes(); } - public function componentId(string $componentId): self + public function containerId(string $containerId): self { - $this->componentId = $componentId; + $this->containerId = $containerId; return $this; } - public function componentClasses(array $componentClasses): self + public function componentId(string $componentId): self { - $this->componentClasses = $componentClasses; + $this->componentId = $componentId; return $this; } - public function containerId(string $containerId): self + public function componentClasses(array $componentClasses, bool $replace = false): self { - $this->containerId = $containerId; + $this->componentClasses = $replace + ? $componentClasses + : array_merge($this->componentClasses, $componentClasses); return $this; } - /** - * Set the component container classes. - * - * @param array $containerClasses - * - * @return $this - */ - public function containerClasses(array $containerClasses): self + public function containerClasses(array $containerClasses, bool $replace = false): self { - $this->containerClasses = $containerClasses; + $this->containerClasses = $replace + ? $containerClasses + : array_merge($this->containerClasses, $containerClasses); return $this; } - public function componentHtmlAttributes(array $componentHtmlAttributes): self + public function componentHtmlAttributes(array $componentHtmlAttributes, bool $replace = false): self { - $this->componentHtmlAttributes = $componentHtmlAttributes; + $this->componentHtmlAttributes = $replace + ? $componentHtmlAttributes + : array_merge($this->componentHtmlAttributes, $componentHtmlAttributes); return $this; } - public function containerHtmlAttributes(array $containerHtmlAttributes): self + public function containerHtmlAttributes(array $containerHtmlAttributes, bool $replace = false): self { - $this->containerHtmlAttributes = $containerHtmlAttributes; + $this->containerHtmlAttributes = $replace + ? $containerHtmlAttributes + : array_merge($this->containerHtmlAttributes, $containerHtmlAttributes); return $this; } diff --git a/src/Components/Form/InputEmail.php b/src/Components/Form/InputEmail.php index f22bfd33..4a45dad4 100644 --- a/src/Components/Form/InputEmail.php +++ b/src/Components/Form/InputEmail.php @@ -48,7 +48,7 @@ protected function setContainerClasses(): array protected function setComponentHtmlAttributes(): array { - return []; + return ['autocomplete' => 'on']; } protected function setContainerHtmlAttributes(): array diff --git a/src/Components/Form/InputPassword.php b/src/Components/Form/InputPassword.php index 8f4ccc35..8645b3e3 100644 --- a/src/Components/Form/InputPassword.php +++ b/src/Components/Form/InputPassword.php @@ -53,7 +53,7 @@ protected function setComponentHtmlAttributes(): array protected function setContainerHtmlAttributes(): array { - return []; + return ['autocomplete' => 'on']; } protected function setDisplaySuccess(): bool diff --git a/src/Components/Form/InputTel.php b/src/Components/Form/InputTel.php index 996876d0..ffa20318 100644 --- a/src/Components/Form/InputTel.php +++ b/src/Components/Form/InputTel.php @@ -48,7 +48,7 @@ protected function setContainerClasses(): array protected function setComponentHtmlAttributes(): array { - return []; + return ['autocomplete' => 'on']; } protected function setContainerHtmlAttributes(): array diff --git a/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php b/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php index 8b6e80f6..e2c63f9c 100644 --- a/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php +++ b/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php @@ -24,7 +24,7 @@ public function setCustomUrl() self::assertStringContainsString('href="default-url"', $html); } - public function testSetUrlOverridesDefault() + public function testSetUrlReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -55,7 +55,7 @@ public function testSetCustomLabel() self::assertStringContainsString('default-label', $html); } - public function testSetLabelOverridesDefault() + public function testSetLabelReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -110,7 +110,7 @@ public function testSetCustomContainerClasses() self::assertStringContainsString('class="component-container default container classes"', $html); } - public function testSetContainerClassesOverridesDefault() + public function testSetContainerClassesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -131,7 +131,7 @@ public function testSetCustomComponentClasses() self::assertStringContainsString('class="component btn default component classes"', $html); } - public function testSetComponentClassesOverridesDefault() + public function testSetComponentClassesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), diff --git a/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php b/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php index 349f7ca5..f8cc5655 100644 --- a/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php +++ b/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php @@ -54,7 +54,7 @@ protected function getComponentKey(): string return $this->getComponentType(); } - public function testSetPrependOverridesDefault() + public function testSetPrependReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -81,7 +81,7 @@ public function testSetCustomAppend() self::assertStringContainsString('default-append', $html); } - public function testSetAppendOverridesDefault() + public function testSetAppendReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -115,7 +115,7 @@ public function testSetCustomLabel() self::assertStringContainsString('default-label', $html); } - public function testSetLabelOverridesDefault() + public function testSetLabelReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -179,7 +179,7 @@ public function testSetCustomContainerClasses() self::assertStringContainsString('class="component-container default container classes"', $html); } - public function testSetContainerClassesOverridesDefault() + public function testSetContainerClassesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -200,7 +200,7 @@ public function testSetCustomComponentClasses() self::assertStringContainsString('class="component btn default component classes"', $html); } - public function testSetComponentClassesOverridesDefault() + public function testSetComponentClassesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -224,7 +224,7 @@ public function testSetCustomContainerHtmlAttributes() ); } - public function testSetContainerHtmlAttributesOverridesDefault() + public function testSetContainerHtmlAttributesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -247,7 +247,7 @@ public function testSetCustomComponentHtmlAttributes() self::assertStringContainsString('default="component" html="attributes">', $html); } - public function testSetComponentHtmlAttributesOverridesDefault() + public function testSetComponentHtmlAttributesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), diff --git a/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php b/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php index 03c24a12..b452537f 100644 --- a/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php @@ -34,7 +34,7 @@ public function testSetCustomPrepend(): void self::assertStringContainsString('default-prepend', $html); } - public function testSetPrependOverridesDefault(): void + public function testSetPrependReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -69,7 +69,7 @@ public function testSetCustomAppend(): void self::assertStringContainsString('default-append', $html); } - public function testSetAppendOverridesDefault(): void + public function testSetAppendReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -239,7 +239,7 @@ public function testSetCustomLabelPositionedAbove(): void self::markTestSkipped(); } - public function testSetLabelPositionedAboveOverridesDefault(): void + public function testSetLabelPositionedAboveReplacesDefault(): void { self::markTestSkipped(); } @@ -298,21 +298,33 @@ public function testSetCustomContainerClasses(): void ); } - public function testSetContainerClassesOverridesDefault(): void + public function testSetContainerClassesMergedToDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->containerClasses(['custom', 'container', 'classes'])->toHtml(); + $html = $this->getComponent()->name('name')->containerClasses(['with', 'merged'])->toHtml(); self::assertStringContainsString( 'class="component-container custom-control custom-' . $this->getComponentType() - . ' custom container classes"', + . ' default container classes with merged"', $html ); - self::assertStringNotContainsString( + } + + public function testSetContainerClassesReplacesDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent() + ->name('name') + ->containerClasses(['custom', 'container', 'classes'], true) + ->toHtml(); + self::assertStringContainsString( 'class="component-container custom-control custom-' . $this->getComponentType() - . ' default container classes"', + . ' custom container classes"', $html ); } @@ -327,14 +339,29 @@ public function testSetCustomComponentClasses(): void self::assertStringContainsString('class="component custom-control-input default component classes"', $html); } - public function testSetComponentClassesOverridesDefault(): void + public function testSetComponentClassesMergedToDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); + self::assertStringContainsString( + 'class="component custom-control-input default component classes with merged"', + $html + ); + } + + public function testSetComponentClassesReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['custom', 'component', 'classes'])->toHtml(); + $html = $this->getComponent() + ->name('name') + ->componentClasses(['custom', 'component', 'classes'], true) + ->toHtml(); self::assertStringContainsString('class="component custom-control-input custom component classes"', $html); - self::assertStringNotContainsString('class="component custom-control-input default component classes"', $html); } } diff --git a/tests/Unit/Form/Abstracts/InputFileTestAbstract.php b/tests/Unit/Form/Abstracts/InputFileTestAbstract.php index 0aa074cc..b80262eb 100644 --- a/tests/Unit/Form/Abstracts/InputFileTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputFileTestAbstract.php @@ -181,19 +181,31 @@ public function testSetCustomComponentClasses(): void ); } - public function testSetComponentClassesOverridesDefault(): void + public function testSetComponentClassesMergedToDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['custom', 'component', 'classes'])->toHtml(); + $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); self::assertStringContainsString( - 'class="component form-control custom-file-input custom component classes"', + 'class="component form-control custom-file-input default component classes with merged"', $html ); - self::assertStringNotContainsString( - 'class="component form-control custom-file-input default component classes"', + } + + public function testSetComponentClassesReplacesDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent() + ->name('name') + ->componentClasses(['custom', 'component', 'classes'], true) + ->toHtml(); + self::assertStringContainsString( + 'class="component form-control custom-file-input custom component classes"', $html ); } @@ -228,7 +240,7 @@ public function testCustomShowRemoveCheckbox(): void self::assertStringContainsString(' name="remove_name"', $html); } - public function testSetShowRemoveCheckboxOverridesDefault(): void + public function testSetShowRemoveCheckboxReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), diff --git a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php index 941bad85..3d127526 100644 --- a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php @@ -36,7 +36,7 @@ public function testSetCustomPrepend(): void self::assertStringContainsString('default-prepend', $html); } - public function testSetPrependOverridesDefault(): void + public function testSetPrependReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -71,7 +71,7 @@ public function testSetCustomAppend(): void self::assertStringContainsString('default-append', $html); } - public function testSetAppendOverridesDefault(): void + public function testSetAppendReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -214,7 +214,7 @@ public function testSetCustomLabelPositionedAbove(): void self::markTestSkipped(); } - public function testSetLabelPositionedAboveOverridesDefault(): void + public function testSetLabelPositionedAboveReplacesDefault(): void { self::markTestSkipped(); } @@ -296,19 +296,31 @@ public function testSetCustomContainerClasses(): void ); } - public function testSetContainerClassesOverridesDefault(): void + public function testSetContainerClassesMergedToDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->containerClasses(['custom', 'container', 'classes'])->toHtml(); + $html = $this->getComponent()->name('name')->containerClasses(['with', 'merged'])->toHtml(); self::assertStringContainsString( - 'class="component-container custom-control custom-checkbox custom container classes"', + 'class="component-container custom-control custom-checkbox default container classes with merged"', $html ); - self::assertStringNotContainsString( - 'class="component-container form-group custom-control custom-checkbox default container classes"', + } + + public function testSetContainerClassesReplacesDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent() + ->name('name') + ->containerClasses(['custom', 'container', 'classes'], true) + ->toHtml(); + self::assertStringContainsString( + 'class="component-container custom-control custom-checkbox custom container classes"', $html ); } @@ -323,14 +335,29 @@ public function testSetCustomComponentClasses(): void self::assertStringContainsString('class="component custom-control-input default component classes"', $html); } - public function testSetComponentClassesOverridesDefault(): void + public function testSetComponentClassesMergedToDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); + self::assertStringContainsString( + 'class="component custom-control-input default component classes with merged"', + $html + ); + } + + public function testSetComponentClassesReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['custom', 'component', 'classes'])->toHtml(); + $html = $this->getComponent() + ->name('name') + ->componentClasses(['custom', 'component', 'classes'], true) + ->toHtml(); self::assertStringContainsString('class="component custom-control-input custom component classes"', $html); - self::assertStringNotContainsString('class="component custom-control-input default component classes"', $html); } } diff --git a/tests/Unit/Form/Abstracts/InputTestAbstract.php b/tests/Unit/Form/Abstracts/InputTestAbstract.php index 3e96692c..e754afac 100644 --- a/tests/Unit/Form/Abstracts/InputTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputTestAbstract.php @@ -2,12 +2,12 @@ namespace Okipa\LaravelBootstrapComponents\Tests\Unit\Form\Abstracts; -use RuntimeException; use Illuminate\Support\MessageBag; use Okipa\LaravelBootstrapComponents\Components\ComponentAbstract; use Okipa\LaravelBootstrapComponents\Components\Form\Abstracts\FormAbstract; use Okipa\LaravelBootstrapComponents\Tests\BootstrapComponentsTestCase; use Okipa\LaravelBootstrapComponents\Tests\Fakers\UsersFaker; +use RuntimeException; abstract class InputTestAbstract extends BootstrapComponentsTestCase { @@ -84,7 +84,7 @@ protected function getComponentKey(): string abstract protected function getCustomComponent(): ComponentAbstract; - public function testSetPrependOverridesDefault(): void + public function testSetPrependReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -125,7 +125,7 @@ public function testSetCustomAppend(): void self::assertStringContainsString('default-append', $html); } - public function testSetAppendOverridesDefault(): void + public function testSetAppendReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -172,7 +172,7 @@ public function testSetCustomCaption(): void self::assertStringContainsString('class="caption form-text text-muted">default-caption', $html); } - public function testSetCaptionOverridesDefault(): void + public function testSetCaptionReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -302,7 +302,7 @@ public function testSetCustomLabelPositionedAbove(): void self::assertLessThan($labelPosition, $inputPosition); } - public function testSetLabelPositionedAboveOverridesDefault(): void + public function testSetLabelPositionedAboveReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -376,7 +376,7 @@ public function testSetCustomDisplaySuccess(): void self::assertStringContainsString(__('Field correctly filled.'), $html); } - public function testSetDisplaySuccessOverridesDefault(): void + public function testSetDisplaySuccessReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -404,7 +404,7 @@ public function testSetCustomDisplayFailure(): void self::assertStringContainsString($errors->first('name'), $html); } - public function testSetDisplayFailureOverridesDefault(): void + public function testSetDisplayFailureReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -480,15 +480,31 @@ public function testSetCustomContainerClasses(): void self::assertStringContainsString('class="component-container default container classes"', $html); } - public function testSetContainerClassesOverridesDefault(): void + public function testSetContainerClassesMergedToDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent()->name('name')->containerClasses(['with', 'merged'])->toHtml(); + self::assertStringContainsString( + 'class="component-container default container classes with merged"', + $html + ); + self::assertStringNotContainsString('class="component-container default container classes"', $html); + } + + public function testSetContainerClassesReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->containerClasses(['custom', 'container', 'classes'])->toHtml(); + $html = $this->getComponent() + ->name('name') + ->containerClasses(['custom', 'container', 'classes'], true) + ->toHtml(); self::assertStringContainsString('class="component-container custom container classes"', $html); - self::assertStringNotContainsString('class="component-container form-group default container classes"', $html); } public function testSetCustomComponentClasses(): void @@ -501,15 +517,27 @@ public function testSetCustomComponentClasses(): void self::assertStringContainsString('class="component form-control default component classes"', $html); } - public function testSetComponentClassesOverridesDefault(): void + public function testSetComponentClassesMergedToDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['custom', 'component', 'classes'])->toHtml(); + $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); + self::assertStringContainsString('class="component form-control default component classes with merged"', $html); + } + + public function testSetComponentClassesReplacesDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent() + ->name('name') + ->componentClasses(['custom', 'component', 'classes'], true) + ->toHtml(); self::assertStringContainsString('class="component form-control custom component classes"', $html); - self::assertStringNotContainsString('class="component form-control default component classes"', $html); } public function testSetCustomContainerHtmlAttributes(): void @@ -519,13 +547,23 @@ public function testSetCustomContainerHtmlAttributes(): void get_class($this->getCustomComponent()) ); $html = $this->getComponent()->name('name')->toHtml(); - self::assertStringContainsString( - 'default="container" html="attributes">', - $html + self::assertStringContainsString('default="container" html="attributes">', $html); + } + + public function testSetContainerHtmlAttributesMergedToDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) ); + $html = $this->getComponent() + ->name('name') + ->containerHtmlAttributes(['with' => 'merged']) + ->toHtml(); + self::assertStringContainsString('default="container" html="attributes" with="merged">', $html); } - public function testSetContainerHtmlAttributesOverridesDefault(): void + public function testSetContainerHtmlAttributesReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -533,10 +571,9 @@ public function testSetContainerHtmlAttributesOverridesDefault(): void ); $html = $this->getComponent() ->name('name') - ->containerHtmlAttributes(['custom' => 'container', 'html' => 'attributes']) + ->containerHtmlAttributes(['custom' => 'container', 'html' => 'attributes'], true) ->toHtml(); self::assertStringContainsString('custom="container" html="attributes">', $html); - self::assertStringNotContainsString('default="container" html="attributes">', $html); } public function testSetCustomComponentHtmlAttributes(): void @@ -549,7 +586,20 @@ public function testSetCustomComponentHtmlAttributes(): void self::assertStringContainsString('default="component" html="attributes">', $html); } - public function testSetComponentHtmlAttributesOverridesDefault(): void + public function testSetComponentHtmlAttributesMergedToDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent()->name('name') + ->value(null) + ->componentHtmlAttributes(['with' => 'merged']) + ->toHtml(); + self::assertStringContainsString('default="component" html="attributes" with="merged">', $html); + } + + public function testSetComponentHtmlAttributesReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -557,9 +607,8 @@ public function testSetComponentHtmlAttributesOverridesDefault(): void ); $html = $this->getComponent()->name('name') ->value(null) - ->componentHtmlAttributes(['custom' => 'component', 'html' => 'attributes']) + ->componentHtmlAttributes(['custom' => 'component', 'html' => 'attributes'], true) ->toHtml(); self::assertStringContainsString('custom="component" html="attributes">', $html); - self::assertStringNotContainsString('default="component" html="attributes">', $html); } } diff --git a/tests/Unit/Form/Abstracts/SelectTestAbstract.php b/tests/Unit/Form/Abstracts/SelectTestAbstract.php index 8b031212..1cbe2070 100644 --- a/tests/Unit/Form/Abstracts/SelectTestAbstract.php +++ b/tests/Unit/Form/Abstracts/SelectTestAbstract.php @@ -578,7 +578,7 @@ public function testSetCustomLabelPositionedAbove(): void self::assertLessThan($labelPosition, $inputPosition); } - public function testSetLabelPositionedAboveOverridesDefault(): void + public function testSetLabelPositionedAboveReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -700,14 +700,29 @@ public function testSetCustomComponentClasses(): void self::assertStringContainsString('class="component custom-select default component classes"', $html); } - public function testSetComponentClassesOverridesDefault(): void + public function testSetComponentClassesMergedToDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['custom', 'component', 'classes'])->toHtml(); + $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); + self::assertStringContainsString( + 'class="component custom-select default component classes with merged"', + $html + ); + } + + public function testSetComponentClassesReplacesDefault(): void + { + config()->set( + 'bootstrap-components.components.' . $this->getComponentKey(), + get_class($this->getCustomComponent()) + ); + $html = $this->getComponent() + ->name('name') + ->componentClasses(['custom', 'component', 'classes'], true) + ->toHtml(); self::assertStringContainsString('class="component custom-select custom component classes"', $html); - self::assertStringNotContainsString('class="component custom-select default component classes"', $html); } } diff --git a/tests/Unit/Form/Abstracts/TemporalTestAbstract.php b/tests/Unit/Form/Abstracts/TemporalTestAbstract.php index db3c1e91..d0378bd3 100644 --- a/tests/Unit/Form/Abstracts/TemporalTestAbstract.php +++ b/tests/Unit/Form/Abstracts/TemporalTestAbstract.php @@ -51,7 +51,7 @@ public function testSetCustomFormat(): void self::assertStringContainsString($user->published_at->format('d/m/Y H-i-s'), $html); } - public function testSetFormatOverridesDefault(): void + public function testSetFormatReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), diff --git a/tests/Unit/Form/Abstracts/TextareaTestAbstract.php b/tests/Unit/Form/Abstracts/TextareaTestAbstract.php index e8b5a7dd..0c46695c 100644 --- a/tests/Unit/Form/Abstracts/TextareaTestAbstract.php +++ b/tests/Unit/Form/Abstracts/TextareaTestAbstract.php @@ -96,7 +96,7 @@ public function testSetCustomLabelPositionedAbove(): void self::assertLessThan($labelPosition, $inputPosition); } - public function testSetLabelPositionedAboveOverridesDefault(): void + public function testSetLabelPositionedAboveReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), diff --git a/tests/Unit/Media/Abstracts/ImageTestAbstract.php b/tests/Unit/Media/Abstracts/ImageTestAbstract.php index 5b031e6c..ec0c49db 100644 --- a/tests/Unit/Media/Abstracts/ImageTestAbstract.php +++ b/tests/Unit/Media/Abstracts/ImageTestAbstract.php @@ -40,7 +40,7 @@ public function testSetNoLinkTitleWithLabelAndAlt() self::assertStringContainsString('title="custom-label"', $html); } - public function testSetLinkTitleOverridesDefault() + public function testSetLinkTitleReplacesDefault() { $html = image()->label('custom-label') ->linkTitle('custom-title') @@ -73,7 +73,7 @@ public function testNoAltWithLabelAndLinkTitle() self::assertStringContainsString('alt="custom-label"', $html); } - public function testSetAltOverridesDefault() + public function testSetAltReplacesDefault() { $html = image()->label('custom-label')->linkTitle('custom-title')->alt('custom-alt')->toHtml(); self::assertStringContainsString('alt="custom-alt"', $html); @@ -126,7 +126,7 @@ public function testSetCustomLinkClasses() self::assertStringContainsString('class="component-link default link classes"', $html); } - public function testSetLinkClassesOverridesDefault() + public function testSetLinkClassesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -147,7 +147,7 @@ public function testSetCustomLinkHtmlAttributes() self::assertStringContainsString('default="link" html="attributes">', $html); } - public function testSetLinkHtmlAttributesOverridesDefault() + public function testSetLinkHtmlAttributesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), diff --git a/tests/Unit/Media/Abstracts/MediaTestAbstract.php b/tests/Unit/Media/Abstracts/MediaTestAbstract.php index 0db3fff7..ce8af199 100644 --- a/tests/Unit/Media/Abstracts/MediaTestAbstract.php +++ b/tests/Unit/Media/Abstracts/MediaTestAbstract.php @@ -63,7 +63,7 @@ protected function getComponentKey(): string return $this->getComponentType(); } - public function testSetCaptionOverridesDefault() + public function testSetCaptionReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -135,7 +135,7 @@ public function testSetCustomContainerClasses() self::assertStringContainsString('class="component-container default container classes"', $html); } - public function testSetContainerClassesOverridesDefault() + public function testSetContainerClassesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -156,7 +156,7 @@ public function testSetCustomComponentClasses() self::assertStringContainsString('class="component default component classes"', $html); } - public function testSetComponentClassesOverridesDefault() + public function testSetComponentClassesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -180,7 +180,7 @@ public function testSetCustomContainerHtmlAttributes() ); } - public function testSetContainerHtmlAttributesOverridesDefault() + public function testSetContainerHtmlAttributesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -203,7 +203,7 @@ public function testSetCustomComponentHtmlAttributes() self::assertStringContainsString('default="component" html="attributes">', $html); } - public function testSetComponentHtmlAttributesOverridesDefault() + public function testSetComponentHtmlAttributesReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), diff --git a/tests/Unit/Media/Abstracts/VideoTestAbstract.php b/tests/Unit/Media/Abstracts/VideoTestAbstract.php index 660ea818..e03b282c 100644 --- a/tests/Unit/Media/Abstracts/VideoTestAbstract.php +++ b/tests/Unit/Media/Abstracts/VideoTestAbstract.php @@ -14,7 +14,7 @@ public function testSetCustomPoster() self::assertStringContainsString('poster="default-poster"', $html); } - public function testSetPosterOverridesDefault() + public function testSetPosterReplacesDefault() { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), From 1910670a5ffe6caaa4f6fb390ab421fc45535eca Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Thu, 3 Dec 2020 21:24:23 +0100 Subject: [PATCH 02/14] WIP --- CHANGELOG.md | 10 ++++ README.md | 2 + docs/api/types.md | 8 +-- docs/upgrade-guides/from-v2-to-v3.md | 19 +++++++ docs/upgrade-guides/from-v4-to-v5.md | 22 ++++++++ src/Components/ComponentAbstract.php | 32 ++++++------ .../Abstracts/InputCheckableTestAbstract.php | 23 +++------ .../Form/Abstracts/InputFileTestAbstract.php | 14 ++---- .../Form/Abstracts/InputRadioTestAbstract.php | 30 ++++------- .../Unit/Form/Abstracts/InputTestAbstract.php | 50 +++++++------------ .../Form/Abstracts/SelectTestAbstract.php | 14 ++---- 11 files changed, 116 insertions(+), 108 deletions(-) create mode 100644 docs/upgrade-guides/from-v2-to-v3.md create mode 100644 docs/upgrade-guides/from-v4-to-v5.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 60dab789..3b3c6f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [5.0.0](https://github.com/Okipa/laravel-bootstrap-components/compare/4.0.0...5.0.0) + +2020-12-02 + +* Method signature changes + +:point_right: [See the upgrade guide](/docs/upgrade-guides/from-v4-to-v5.md) + ## [4.0.0](https://github.com/Okipa/laravel-bootstrap-components/compare/3.0.3...4.0.0) 2020-11-14 @@ -40,6 +48,8 @@ * Dropped Laravel 5.8 and 6.0 support * Dropped PHP 7.2 and 7.3 support +:point_right: [See the upgrade guide](/docs/upgrade-guides/from-v2-to-v3.md) + ## [2.2.3](https://github.com/Okipa/laravel-bootstrap-components/compare/2.2.2...2.2.3) 2020-07-16 diff --git a/README.md b/README.md index d3975e78..bb8488ac 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,9 @@ Found this package helpful? Please consider supporting my work! ## Upgrade guide +* [From V4 to V5](/docs/upgrade-guides/from-v4-to-v5.md) * [From V3 to V4](/docs/upgrade-guides/from-v3-to-v4.md) +* [From V2 to V3](/docs/upgrade-guides/from-v2-to-v3.md) * [From V1 to V2](/docs/upgrade-guides/from-v1-to-v2.md) ## Usage diff --git a/docs/api/types.md b/docs/api/types.md index 548a51a5..16f6c449 100644 --- a/docs/api/types.md +++ b/docs/api/types.md @@ -21,10 +21,10 @@ |---|---|---| | containerId(string $containerId): self | No | Set the component container id. | | componentId(string $componentId): self | No | Set the component id. | -| componentClasses(array $componentClasses): self | No | Set the component classes. The given classes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | -| containerClasses(array $containerClasses): self | No | Set the component container classes. The given classes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | -| componentHtmlAttributes(array $componentHtmlAttributes): self | No | Set the component HTML attributes. The given HTML attributes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | -| containerHtmlAttributes(array $containerHtmlAttributes): self | No | Set the component container HTML attributes. The given HTML attributes will be merged to component default ones. You can activate the replacing mode by setting the second argument to `true`. | +| componentClasses(array $componentClasses): self | No | The given HTML classes will replace the component default ones. You can activate the merge mode in order to add the given classes to the default ones by setting the second argument to `true`. | +| containerClasses(array $containerClasses): self | No | The given HTML classes will replace the component default ones. You can activate the merge mode in order to add the given classes to the default ones by setting the second argument to `true`. | +| componentHtmlAttributes(array $componentHtmlAttributes): self | No | The given HTML attributes will replace the component default ones. You can activate the merge mode in order to add the given attributes to the default ones by setting the second argument to `true`. | +| containerHtmlAttributes(array $containerHtmlAttributes): self | No | The given HTML attributes will replace the component default ones. You can activate the merge mode in order to add the given attributes to the default ones by setting the second argument to `true`. | **Usage** diff --git a/docs/upgrade-guides/from-v2-to-v3.md b/docs/upgrade-guides/from-v2-to-v3.md new file mode 100644 index 00000000..e0b720f5 --- /dev/null +++ b/docs/upgrade-guides/from-v2-to-v3.md @@ -0,0 +1,19 @@ +# Upgrade from v2 to v3 + +Follow the steps below to upgrade the package. + +## Laravel and PHP old version support drop + +Whereas Laravel 8 is now supported by this package, support for any version before Laravel 7 has been dropped. + +Support for any version before PHP 7.4 has also been dropped. + +As so, you should upgrade your Laravel and PHP versions in order upgrade to V2. + +## See all changes + +See all change with the [comparison tool](https://github.com/Okipa/laravel-bootstrap-components/compare/2.2.3...3.0.0). + +## Undocumented changes + +If you see any forgotten and undocumented change, please submit a PR to add them to this upgrade guide. diff --git a/docs/upgrade-guides/from-v4-to-v5.md b/docs/upgrade-guides/from-v4-to-v5.md new file mode 100644 index 00000000..33593309 --- /dev/null +++ b/docs/upgrade-guides/from-v4-to-v5.md @@ -0,0 +1,22 @@ +# Upgrade from v4 to v5 + +Follow the steps below to upgrade the package. + +## Method signature changes + +The behaviour of the following methods have gained the ability to merge given HTML classes or HTML attributes to the component default ones instead of replacing them. + +To trigger this new behaviour, you'll just have to set the second boolean `$mergeMode` attribute to `false`. + +* `componentClasses` +* `containerClasses` +* `componentHtmlAttributes` +* `containerHtmlAttributes` + +## See all changes + +See all change with the [comparison tool](https://github.com/Okipa/laravel-bootstrap-components/compare/4.0.0...5.0.0). + +## Undocumented changes + +If you see any forgotten and undocumented change, please submit a PR to add them to this upgrade guide. diff --git a/src/Components/ComponentAbstract.php b/src/Components/ComponentAbstract.php index b82c2995..84a6e10e 100644 --- a/src/Components/ComponentAbstract.php +++ b/src/Components/ComponentAbstract.php @@ -46,38 +46,38 @@ public function componentId(string $componentId): self return $this; } - public function componentClasses(array $componentClasses, bool $replace = false): self + public function componentClasses(array $componentClasses, bool $mergeMode = false): self { - $this->componentClasses = $replace - ? $componentClasses - : array_merge($this->componentClasses, $componentClasses); + $this->componentClasses = $mergeMode + ? array_merge($this->componentClasses, $componentClasses) + : $componentClasses; return $this; } - public function containerClasses(array $containerClasses, bool $replace = false): self + public function containerClasses(array $containerClasses, bool $mergeMode = false): self { - $this->containerClasses = $replace - ? $containerClasses - : array_merge($this->containerClasses, $containerClasses); + $this->containerClasses = $mergeMode + ? array_merge($this->containerClasses, $containerClasses) + : $containerClasses; return $this; } - public function componentHtmlAttributes(array $componentHtmlAttributes, bool $replace = false): self + public function componentHtmlAttributes(array $componentHtmlAttributes, bool $mergeMode = false): self { - $this->componentHtmlAttributes = $replace - ? $componentHtmlAttributes - : array_merge($this->componentHtmlAttributes, $componentHtmlAttributes); + $this->componentHtmlAttributes = $mergeMode + ? array_merge($this->componentHtmlAttributes, $componentHtmlAttributes) + : $componentHtmlAttributes; return $this; } - public function containerHtmlAttributes(array $containerHtmlAttributes, bool $replace = false): self + public function containerHtmlAttributes(array $containerHtmlAttributes, bool $mergeMode = false): self { - $this->containerHtmlAttributes = $replace - ? $containerHtmlAttributes - : array_merge($this->containerHtmlAttributes, $containerHtmlAttributes); + $this->containerHtmlAttributes = $mergeMode + ? array_merge($this->containerHtmlAttributes, $containerHtmlAttributes) + : $containerHtmlAttributes; return $this; } diff --git a/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php b/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php index b452537f..85b267c7 100644 --- a/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php @@ -304,10 +304,10 @@ public function testSetContainerClassesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->containerClasses(['with', 'merged'])->toHtml(); + $html = $this->getComponent()->name('name')->containerClasses(['merged'], true)->toHtml(); self::assertStringContainsString( 'class="component-container custom-control custom-' . $this->getComponentType() - . ' default container classes with merged"', + . ' default container classes merged"', $html ); } @@ -318,13 +318,9 @@ public function testSetContainerClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->containerClasses(['custom', 'container', 'classes'], true) - ->toHtml(); + $html = $this->getComponent()->name('name')->containerClasses(['replaced'])->toHtml(); self::assertStringContainsString( - 'class="component-container custom-control custom-' . $this->getComponentType() - . ' custom container classes"', + 'class="component-container custom-control custom-' . $this->getComponentType() . ' replaced"', $html ); } @@ -345,9 +341,9 @@ public function testSetComponentClassesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); + $html = $this->getComponent()->name('name')->componentClasses(['merged'], true)->toHtml(); self::assertStringContainsString( - 'class="component custom-control-input default component classes with merged"', + 'class="component custom-control-input default component classes merged"', $html ); } @@ -358,10 +354,7 @@ public function testSetComponentClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->componentClasses(['custom', 'component', 'classes'], true) - ->toHtml(); - self::assertStringContainsString('class="component custom-control-input custom component classes"', $html); + $html = $this->getComponent()->name('name')->componentClasses(['replaced'])->toHtml(); + self::assertStringContainsString('class="component custom-control-input replaced"', $html); } } diff --git a/tests/Unit/Form/Abstracts/InputFileTestAbstract.php b/tests/Unit/Form/Abstracts/InputFileTestAbstract.php index b80262eb..923688b1 100644 --- a/tests/Unit/Form/Abstracts/InputFileTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputFileTestAbstract.php @@ -187,9 +187,9 @@ public function testSetComponentClassesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); + $html = $this->getComponent()->name('name')->componentClasses(['merged'], true)->toHtml(); self::assertStringContainsString( - 'class="component form-control custom-file-input default component classes with merged"', + 'class="component form-control custom-file-input default component classes merged"', $html ); } @@ -200,14 +200,8 @@ public function testSetComponentClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->componentClasses(['custom', 'component', 'classes'], true) - ->toHtml(); - self::assertStringContainsString( - 'class="component form-control custom-file-input custom component classes"', - $html - ); + $html = $this->getComponent()->name('name')->componentClasses(['replaced'])->toHtml(); + self::assertStringContainsString('class="component form-control custom-file-input replaced"', $html); } public function testSetUploadedFile(): void diff --git a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php index 3d127526..76ae32bd 100644 --- a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php @@ -277,10 +277,7 @@ public function testDefaultComponentIdFormatting(): void { $html = $this->getComponent()->name('camelCaseName')->toHtml(); self::assertStringContainsString(' for="' . $this->getComponentType() . '-camel-case-name-value"', $html); - self::assertStringContainsString( - 'getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->containerClasses(['with', 'merged'])->toHtml(); + $html = $this->getComponent()->name('name')->containerClasses(['merged'], true)->toHtml(); self::assertStringContainsString( - 'class="component-container custom-control custom-checkbox default container classes with merged"', + 'class="component-container custom-control custom-checkbox default container classes merged"', $html ); } @@ -315,14 +312,8 @@ public function testSetContainerClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->containerClasses(['custom', 'container', 'classes'], true) - ->toHtml(); - self::assertStringContainsString( - 'class="component-container custom-control custom-checkbox custom container classes"', - $html - ); + $html = $this->getComponent()->name('name')->containerClasses(['replaced'])->toHtml(); + self::assertStringContainsString('class="component-container custom-control custom-checkbox replaced"', $html); } public function testSetCustomComponentClasses(): void @@ -341,9 +332,9 @@ public function testSetComponentClassesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); + $html = $this->getComponent()->name('name')->componentClasses(['merged'], true)->toHtml(); self::assertStringContainsString( - 'class="component custom-control-input default component classes with merged"', + 'class="component custom-control-input default component classes merged"', $html ); } @@ -354,10 +345,7 @@ public function testSetComponentClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->componentClasses(['custom', 'component', 'classes'], true) - ->toHtml(); - self::assertStringContainsString('class="component custom-control-input custom component classes"', $html); + $html = $this->getComponent()->name('name')->componentClasses(['replaced'])->toHtml(); + self::assertStringContainsString('class="component custom-control-input replaced"', $html); } } diff --git a/tests/Unit/Form/Abstracts/InputTestAbstract.php b/tests/Unit/Form/Abstracts/InputTestAbstract.php index e754afac..e2ac2591 100644 --- a/tests/Unit/Form/Abstracts/InputTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputTestAbstract.php @@ -486,12 +486,8 @@ public function testSetContainerClassesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->containerClasses(['with', 'merged'])->toHtml(); - self::assertStringContainsString( - 'class="component-container default container classes with merged"', - $html - ); - self::assertStringNotContainsString('class="component-container default container classes"', $html); + $html = $this->getComponent()->name('name')->containerClasses(['merged'], true)->toHtml(); + self::assertStringContainsString('class="component-container default container classes merged"', $html); } public function testSetContainerClassesReplacesDefault(): void @@ -500,11 +496,8 @@ public function testSetContainerClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->containerClasses(['custom', 'container', 'classes'], true) - ->toHtml(); - self::assertStringContainsString('class="component-container custom container classes"', $html); + $html = $this->getComponent()->name('name')->containerClasses(['replaced'])->toHtml(); + self::assertStringContainsString('class="component-container replaced"', $html); } public function testSetCustomComponentClasses(): void @@ -523,8 +516,8 @@ public function testSetComponentClassesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); - self::assertStringContainsString('class="component form-control default component classes with merged"', $html); + $html = $this->getComponent()->name('name')->componentClasses(['merged'], true)->toHtml(); + self::assertStringContainsString('class="component form-control default component classes merged"', $html); } public function testSetComponentClassesReplacesDefault(): void @@ -533,11 +526,8 @@ public function testSetComponentClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->componentClasses(['custom', 'component', 'classes'], true) - ->toHtml(); - self::assertStringContainsString('class="component form-control custom component classes"', $html); + $html = $this->getComponent()->name('name')->componentClasses(['replaced'])->toHtml(); + self::assertStringContainsString('class="component form-control replaced"', $html); } public function testSetCustomContainerHtmlAttributes(): void @@ -556,10 +546,7 @@ public function testSetContainerHtmlAttributesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->containerHtmlAttributes(['with' => 'merged']) - ->toHtml(); + $html = $this->getComponent()->name('name')->containerHtmlAttributes(['with' => 'merged'], true)->toHtml(); self::assertStringContainsString('default="container" html="attributes" with="merged">', $html); } @@ -569,11 +556,8 @@ public function testSetContainerHtmlAttributesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->containerHtmlAttributes(['custom' => 'container', 'html' => 'attributes'], true) - ->toHtml(); - self::assertStringContainsString('custom="container" html="attributes">', $html); + $html = $this->getComponent()->name('name')->containerHtmlAttributes(['replaces' => 'default'])->toHtml(); + self::assertStringContainsString('replaces="default">', $html); } public function testSetCustomComponentHtmlAttributes(): void @@ -592,9 +576,10 @@ public function testSetComponentHtmlAttributesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name') + $html = $this->getComponent() + ->name('name') ->value(null) - ->componentHtmlAttributes(['with' => 'merged']) + ->componentHtmlAttributes(['with' => 'merged'], true) ->toHtml(); self::assertStringContainsString('default="component" html="attributes" with="merged">', $html); } @@ -605,10 +590,11 @@ public function testSetComponentHtmlAttributesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name') + $html = $this->getComponent() + ->name('name') ->value(null) - ->componentHtmlAttributes(['custom' => 'component', 'html' => 'attributes'], true) + ->componentHtmlAttributes(['replaces' => 'default']) ->toHtml(); - self::assertStringContainsString('custom="component" html="attributes">', $html); + self::assertStringContainsString('replaces="default">', $html); } } diff --git a/tests/Unit/Form/Abstracts/SelectTestAbstract.php b/tests/Unit/Form/Abstracts/SelectTestAbstract.php index 1cbe2070..20cad51f 100644 --- a/tests/Unit/Form/Abstracts/SelectTestAbstract.php +++ b/tests/Unit/Form/Abstracts/SelectTestAbstract.php @@ -706,11 +706,8 @@ public function testSetComponentClassesMergedToDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent()->name('name')->componentClasses(['with', 'merged'])->toHtml(); - self::assertStringContainsString( - 'class="component custom-select default component classes with merged"', - $html - ); + $html = $this->getComponent()->name('name')->componentClasses(['merged'], true)->toHtml(); + self::assertStringContainsString('class="component custom-select default component classes merged"', $html); } public function testSetComponentClassesReplacesDefault(): void @@ -719,10 +716,7 @@ public function testSetComponentClassesReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $html = $this->getComponent() - ->name('name') - ->componentClasses(['custom', 'component', 'classes'], true) - ->toHtml(); - self::assertStringContainsString('class="component custom-select custom component classes"', $html); + $html = $this->getComponent()->name('name')->componentClasses(['replaced'])->toHtml(); + self::assertStringContainsString('class="component custom-select replaced"', $html); } } From dd1fceaca82be796b800b587ea3c4b27406547dc Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Sun, 6 Dec 2020 21:48:36 +0100 Subject: [PATCH 03/14] WIP --- docs/api/types.md | 20 +- .../form/checkbox.blade.php | 2 +- .../bootstrap-components/form/file.blade.php | 4 +- .../bootstrap-components/form/input.blade.php | 28 +-- .../bootstrap-components/form/radio.blade.php | 2 +- .../form/select.blade.php | 2 +- .../form/textarea.blade.php | 2 +- .../partials/validation-feedback.blade.php | 20 +- .../Buttons/Abstracts/ButtonAbstract.php | 6 +- .../Buttons/Abstracts/SubmitAbstract.php | 21 +- src/Components/ComponentAbstract.php | 141 ++++++------ .../Form/Abstracts/CheckableAbstract.php | 20 +- .../Form/Abstracts/FormAbstract.php | 216 ++++++++++-------- .../Form/Abstracts/MultilingualAbstract.php | 148 ++++++------ .../Form/Abstracts/RadioAbstract.php | 12 +- .../Form/Abstracts/SelectableAbstract.php | 17 +- .../Form/Abstracts/TemporalAbstract.php | 2 +- .../Form/Abstracts/UploadableAbstract.php | 6 +- src/Components/Form/Multilingual/Resolver.php | 9 +- .../Traits/MultilingualValidityChecks.php | 17 -- .../Form/Traits/RadioValidityChecks.php | 3 +- .../Form/Traits/SelectValidityChecks.php | 8 +- .../Form/Traits/TemporalValidityChecks.php | 6 +- .../Media/Abstracts/ImageAbstract.php | 45 ++-- .../Media/Abstracts/MediaAbstract.php | 12 +- .../Media/Abstracts/VideoAbstract.php | 6 +- .../Abstracts/InputCheckableTestAbstract.php | 33 +-- .../Form/Abstracts/InputFileTestAbstract.php | 27 +-- .../InputMultilingualTestAbstract.php | 52 ++--- .../Form/Abstracts/InputRadioTestAbstract.php | 33 +-- .../Unit/Form/Abstracts/InputTestAbstract.php | 47 ++-- .../Form/Abstracts/SelectTestAbstract.php | 20 +- .../Form/Abstracts/TemporalTestAbstract.php | 12 +- .../Form/Abstracts/TextareaTestAbstract.php | 48 ++-- 34 files changed, 483 insertions(+), 564 deletions(-) delete mode 100644 src/Components/Form/Traits/MultilingualValidityChecks.php diff --git a/docs/api/types.md b/docs/api/types.md index 16f6c449..6bf1c5be 100644 --- a/docs/api/types.md +++ b/docs/api/types.md @@ -120,15 +120,9 @@ // inherits FormAbstract methods ->locales(['fr', 'en']) - ->value(function(string $locale){ - return $name[$locale]; - }); - ->prepend(function(string $locale){ - return 'prepend-' . $locale; - }) - ->append(function(string $locale){ - return 'append-' . $locale; - }) + ->value(fn(string $locale) => $name[$locale]); + ->prepend(fn(string $locale) => 'prepend-' . $locale) + ->append(fn(string $locale) => 'append-' . $locale) ``` **Components** @@ -176,9 +170,7 @@ ```php // inherits FormAbstract methods - ->uploadedFile(function(){ - return '
Some HTML
'; - }) + ->uploadedFile(fn() => '
Some HTML
') ->showRemoveCheckbox(true, 'Remove this file'); ``` @@ -242,9 +234,7 @@ ]), 'id', 'title') ->selected('id', 1) // or ->selected('id', [1]) in multiple mode - ->disabled(function(array $option){ - return ! $option['active']; - }) + ->disabled(fn(array $option) => ! $option['active']) ->multiple(); ``` diff --git a/resources/views/bootstrap-components/form/checkbox.blade.php b/resources/views/bootstrap-components/form/checkbox.blade.php index 264034c7..ca08dc3f 100644 --- a/resources/views/bootstrap-components/form/checkbox.blade.php +++ b/resources/views/bootstrap-components/form/checkbox.blade.php @@ -1,5 +1,5 @@ $containerId] : null) }}{{ html_classes('component-container', 'custom-control', 'custom-' . $type, $containerClasses) }}{{ html_attributes($containerHtmlAttributes) }}> - + @include('bootstrap-components::bootstrap-components.partials.validation-feedback') @include('bootstrap-components::bootstrap-components.partials.caption') diff --git a/resources/views/bootstrap-components/form/file.blade.php b/resources/views/bootstrap-components/form/file.blade.php index fa45ef09..9e085351 100644 --- a/resources/views/bootstrap-components/form/file.blade.php +++ b/resources/views/bootstrap-components/form/file.blade.php @@ -13,8 +13,8 @@ @endif @include('bootstrap-components::bootstrap-components.partials.prepend')
- - @if(($value = old($name, $value)) || $placeholder) + + @if($placeholder || ($value = old($name, $value))) @endif
diff --git a/resources/views/bootstrap-components/form/input.blade.php b/resources/views/bootstrap-components/form/input.blade.php index 800f0ba7..d158f4de 100644 --- a/resources/views/bootstrap-components/form/input.blade.php +++ b/resources/views/bootstrap-components/form/input.blade.php @@ -1,19 +1,19 @@ $containerId] : null) }}{{ html_classes('component-container', $containerClasses) }}{{ html_attributes($containerHtmlAttributes) }}> -@if($labelPositionedAbove) - @include('bootstrap-components::bootstrap-components.partials.label') -@endif -@if(! empty($prepend) || ! empty($append)) -
-@endif + @if($labelPositionedAbove) + @include('bootstrap-components::bootstrap-components.partials.label') + @endif + @if(! empty($prepend) || ! empty($append)) +
+ @endif @include('bootstrap-components::bootstrap-components.partials.prepend') - $placeholder] : null, $componentHtmlAttributes) }}> + $placeholder] : null, $componentHtmlAttributes) }}> @include('bootstrap-components::bootstrap-components.partials.append') @include('bootstrap-components::bootstrap-components.partials.validation-feedback') -@if(! empty($prepend) || ! empty($append)) -
-@endif -@unless($labelPositionedAbove) - @include('bootstrap-components::bootstrap-components.partials.label') -@endunless -@include('bootstrap-components::bootstrap-components.partials.caption') + @if(! empty($prepend) || ! empty($append)) +
+ @endif + @unless($labelPositionedAbove) + @include('bootstrap-components::bootstrap-components.partials.label') + @endunless + @include('bootstrap-components::bootstrap-components.partials.caption') diff --git a/resources/views/bootstrap-components/form/radio.blade.php b/resources/views/bootstrap-components/form/radio.blade.php index 7ad16059..687662f4 100644 --- a/resources/views/bootstrap-components/form/radio.blade.php +++ b/resources/views/bootstrap-components/form/radio.blade.php @@ -1,5 +1,5 @@ $containerId] : null) }}{{ html_classes('component-container', 'custom-control', 'custom-radio', $containerClasses) }}{{ html_attributes($containerHtmlAttributes) }}> - + @include('bootstrap-components::bootstrap-components.partials.validation-feedback') @include('bootstrap-components::bootstrap-components.partials.caption') diff --git a/resources/views/bootstrap-components/form/select.blade.php b/resources/views/bootstrap-components/form/select.blade.php index b17de6e1..97cbb127 100644 --- a/resources/views/bootstrap-components/form/select.blade.php +++ b/resources/views/bootstrap-components/form/select.blade.php @@ -6,7 +6,7 @@
@endif @include('bootstrap-components::bootstrap-components.partials.prepend') - @if($placeholder) @endif diff --git a/resources/views/bootstrap-components/form/textarea.blade.php b/resources/views/bootstrap-components/form/textarea.blade.php index fe63760b..b3da217c 100644 --- a/resources/views/bootstrap-components/form/textarea.blade.php +++ b/resources/views/bootstrap-components/form/textarea.blade.php @@ -6,7 +6,7 @@
@endif @include('bootstrap-components::bootstrap-components.partials.prepend') - + @include('bootstrap-components::bootstrap-components.partials.append') @include('bootstrap-components::bootstrap-components.partials.validation-feedback') @if(! empty($prepend) || ! empty($append)) diff --git a/resources/views/bootstrap-components/partials/validation-feedback.blade.php b/resources/views/bootstrap-components/partials/validation-feedback.blade.php index 5c005353..75873b32 100644 --- a/resources/views/bootstrap-components/partials/validation-feedback.blade.php +++ b/resources/views/bootstrap-components/partials/validation-feedback.blade.php @@ -1,11 +1,9 @@ -@isset($errors) - @if($errorMessage && $displayFailure) -
- {!! $errorMessage !!} -
- @elseif($displaySuccess) -
- @lang('Field correctly filled.') -
- @endif -@endisset +@if($errorMessage = $errorMessage($errors ?? null, $locale ?? null)) +
+ {!! $errorMessage !!} +
+@elseif($successMessage = $successMessage()) +
+ {!! $successMessage !!} +
+@endif diff --git a/src/Components/Buttons/Abstracts/ButtonAbstract.php b/src/Components/Buttons/Abstracts/ButtonAbstract.php index ef476d0c..5170342f 100644 --- a/src/Components/Buttons/Abstracts/ButtonAbstract.php +++ b/src/Components/Buttons/Abstracts/ButtonAbstract.php @@ -26,11 +26,9 @@ public function route(string $route, array $params = []): self return $this; } - protected function getParameters(): array + protected function getViewParams(): array { - $url = $this->getUrl(); - - return array_merge(parent::getParameters(), compact('url')); + return array_merge(parent::getViewParams(), ['url' => $this->getUrl()]); } protected function getUrl(): ?string diff --git a/src/Components/Buttons/Abstracts/SubmitAbstract.php b/src/Components/Buttons/Abstracts/SubmitAbstract.php index 32b49540..883d99c8 100644 --- a/src/Components/Buttons/Abstracts/SubmitAbstract.php +++ b/src/Components/Buttons/Abstracts/SubmitAbstract.php @@ -41,20 +41,15 @@ public function label(?string $label): self return $this; } - protected function getValues(): array + protected function getViewParams(): array { - return array_merge(parent::getValues(), $this->getParameters()); - } - - protected function getParameters(): array - { - $type = $this->getType(); - $url = null; - $prepend = $this->getPrepend(); - $append = $this->getAppend(); - $label = $this->getLabel(); - - return compact('type', 'url', 'prepend', 'append', 'label'); + return array_merge(parent::getViewParams(), [ + 'type' => $this->getType(), + 'url' => $this->getType(), + 'prepend' => $this->getPrepend(), + 'append' => $this->getAppend(), + 'label' => $this->getLabel(), + ]); } protected function getPrepend(): ?string diff --git a/src/Components/ComponentAbstract.php b/src/Components/ComponentAbstract.php index 84a6e10e..aef4cdc0 100644 --- a/src/Components/ComponentAbstract.php +++ b/src/Components/ComponentAbstract.php @@ -32,56 +32,6 @@ public function __construct() $this->containerHtmlAttributes = $this->setContainerHtmlAttributes(); } - public function containerId(string $containerId): self - { - $this->containerId = $containerId; - - return $this; - } - - public function componentId(string $componentId): self - { - $this->componentId = $componentId; - - return $this; - } - - public function componentClasses(array $componentClasses, bool $mergeMode = false): self - { - $this->componentClasses = $mergeMode - ? array_merge($this->componentClasses, $componentClasses) - : $componentClasses; - - return $this; - } - - public function containerClasses(array $containerClasses, bool $mergeMode = false): self - { - $this->containerClasses = $mergeMode - ? array_merge($this->containerClasses, $containerClasses) - : $containerClasses; - - return $this; - } - - public function componentHtmlAttributes(array $componentHtmlAttributes, bool $mergeMode = false): self - { - $this->componentHtmlAttributes = $mergeMode - ? array_merge($this->componentHtmlAttributes, $componentHtmlAttributes) - : $componentHtmlAttributes; - - return $this; - } - - public function containerHtmlAttributes(array $containerHtmlAttributes, bool $mergeMode = false): self - { - $this->containerHtmlAttributes = $mergeMode - ? array_merge($this->containerHtmlAttributes, $containerHtmlAttributes) - : $containerHtmlAttributes; - - return $this; - } - /** * @return string * @throws \Throwable @@ -102,7 +52,7 @@ public function render(array $extraData = []): string $this->checkValuesValidity(); $view = $this->getView(); $html = $view - ? (string) view('bootstrap-components::' . $view, array_merge($this->getValues(), $extraData))->render() + ? (string) view('bootstrap-components::' . $view, array_merge($this->getViewParams(), $extraData))->render() : ''; return trim($html); @@ -117,23 +67,21 @@ protected function getView(): string abstract protected function setView(): string; - protected function getValues(): array + protected function getViewParams(): array { - $componentId = $this->getComponentId(); - $containerId = $this->getContainerId(); - $componentClasses = $this->getComponentClasses(); - $containerClasses = $this->getContainerClasses(); - $componentHtmlAttributes = $this->getComponentHtmlAttributes(); - $containerHtmlAttributes = $this->getContainerHtmlAttributes(); + return [ + 'containerId' => $this->getContainerId(), + 'containerClasses' => $this->getContainerClasses(), + 'containerHtmlAttributes' => $this->getContainerHtmlAttributes(), + 'componentId' => $this->getComponentId(), + 'componentClasses' => $this->getComponentClasses(), + 'componentHtmlAttributes' => $this->getComponentHtmlAttributes(), + ]; + } - return compact( - 'componentId', - 'containerId', - 'componentClasses', - 'containerClasses', - 'componentHtmlAttributes', - 'containerHtmlAttributes' - ); + protected function getContainerId(): ?string + { + return $this->containerId; } protected function getComponentId(): ?string @@ -141,11 +89,13 @@ protected function getComponentId(): ?string return $this->componentId; } - protected function getContainerId(): ?string + protected function getContainerClasses(): array { - return $this->containerId; + return $this->containerClasses; } + abstract protected function setContainerClasses(): array; + protected function getComponentClasses(): array { return $this->componentClasses; @@ -153,12 +103,12 @@ protected function getComponentClasses(): array abstract protected function setComponentClasses(): array; - protected function getContainerClasses(): array + protected function getContainerHtmlAttributes(): array { - return $this->containerClasses; + return $this->containerHtmlAttributes; } - abstract protected function setContainerClasses(): array; + abstract protected function setContainerHtmlAttributes(): array; protected function getComponentHtmlAttributes(): array { @@ -167,12 +117,55 @@ protected function getComponentHtmlAttributes(): array abstract protected function setComponentHtmlAttributes(): array; - protected function getContainerHtmlAttributes(): array + public function containerId(string $containerId): self { - return $this->containerHtmlAttributes; + $this->containerId = $containerId; + + return $this; } - abstract protected function setContainerHtmlAttributes(): array; + public function componentId(string $componentId): self + { + $this->componentId = $componentId; + + return $this; + } + + public function componentClasses(array $componentClasses, bool $mergeMode = false): self + { + $this->componentClasses = $mergeMode + ? array_merge($this->componentClasses, $componentClasses) + : $componentClasses; + + return $this; + } + + public function containerClasses(array $containerClasses, bool $mergeMode = false): self + { + $this->containerClasses = $mergeMode + ? array_merge($this->containerClasses, $containerClasses) + : $containerClasses; + + return $this; + } + + public function componentHtmlAttributes(array $componentHtmlAttributes, bool $mergeMode = false): self + { + $this->componentHtmlAttributes = $mergeMode + ? array_merge($this->componentHtmlAttributes, $componentHtmlAttributes) + : $componentHtmlAttributes; + + return $this; + } + + public function containerHtmlAttributes(array $containerHtmlAttributes, bool $mergeMode = false): self + { + $this->containerHtmlAttributes = $mergeMode + ? array_merge($this->containerHtmlAttributes, $containerHtmlAttributes) + : $containerHtmlAttributes; + + return $this; + } protected function getType(): string { diff --git a/src/Components/Form/Abstracts/CheckableAbstract.php b/src/Components/Form/Abstracts/CheckableAbstract.php index b921d57a..30d7b782 100644 --- a/src/Components/Form/Abstracts/CheckableAbstract.php +++ b/src/Components/Form/Abstracts/CheckableAbstract.php @@ -15,18 +15,28 @@ public function checked(bool $checked = true): self protected function setLabelPositionedAbove(): bool { - return true; // Unused for checkable components. + // Setting `true` but this property will not be used for checkable components. + return true; } protected function getComponentHtmlAttributes(): array { - return array_merge(parent::getComponentHtmlAttributes(), $this->getChecked() ? ['checked' => 'checked'] : []); + return array_merge($this->componentHtmlAttributes, $this->getChecked() ? ['checked' => 'checked'] : []); } protected function getChecked(): bool { - $old = old($this->convertArrayNameInNotation()); - - return $old ?? $this->checked ?? (bool) (optional($this->model)->{$this->getName()} ?: $this->value); + $oldChecked = old($this->convertArrayNameInNotation()); + if (isset($oldChecked)) { + return $oldChecked; + } + if (isset($this->checked)) { + return $this->checked; + } + if (isset($this->value)) { + return (bool) $this->value; + } + + return (bool) optional($this->model)->{$this->getName()}; } } diff --git a/src/Components/Form/Abstracts/FormAbstract.php b/src/Components/Form/Abstracts/FormAbstract.php index 7afcd78a..86965d2e 100644 --- a/src/Components/Form/Abstracts/FormAbstract.php +++ b/src/Components/Form/Abstracts/FormAbstract.php @@ -5,6 +5,7 @@ use Closure; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; +use Illuminate\Support\ViewErrorBag; use Okipa\LaravelBootstrapComponents\Components\ComponentAbstract; use Okipa\LaravelBootstrapComponents\Components\Form\Traits\FormValidityChecks; @@ -12,6 +13,9 @@ abstract class FormAbstract extends ComponentAbstract { use FormValidityChecks; + /** @property mixed $value */ + protected $value; + protected ?Model $model = null; protected string $name; @@ -30,10 +34,7 @@ abstract class FormAbstract extends ComponentAbstract protected bool $labelPositionedAbove; - /** @property mixed $value */ - protected $value; - - protected ?string $placeholder; + protected ?string $placeholder = null; protected bool $displaySuccess; @@ -46,6 +47,7 @@ public function __construct() $this->append = $this->setAppend(); $this->labelPositionedAbove = $this->setLabelPositionedAbove(); $this->caption = $this->setCaption(); + $this->errors = new ViewErrorBag(); $this->displaySuccess = $this->setDisplaySuccess(); $this->displayFailure = $this->setDisplayFailure(); } @@ -102,6 +104,11 @@ public function placeholder(?string $placeholder): self return $this; } + /** + * @param mixed $value + * + * @return $this + */ public function value($value): self { $this->value = $value; @@ -138,49 +145,25 @@ public function displayFailure(bool $displayFailure = true): self return $this; } - protected function getValues(): array + protected function getValidationClass(?ViewErrorBag $errors): ?string { - return array_merge(parent::getValues(), $this->getParameters()); - } + if (! $errors) { + return null; + } + if ($errors->isEmpty()) { + return null; + } + if ($errors->has($this->convertArrayNameInNotation())) { + return $this->getDisplayFailure() ? 'is-invalid' : null; + } - protected function getParameters(): array - { - $model = $this->getModel(); - $type = $this->getType(); - $name = $this->getName(); - $prepend = $this->getPrepend(); - $append = $this->getAppend(); - $caption = $this->getCaption(); - $label = $this->getLabel(); - $labelPositionedAbove = $this->getLabelPositionedAbove(); - $value = $this->getValue(); - $placeholder = $this->getPlaceholder(); - $displaySuccess = $this->getDisplaySuccess(); - $displayFailure = $this->getDisplayFailure(); - $validationClass = $this->getValidationClass(); - $errorMessage = $this->getErrorMessage(); - - return compact( - 'model', - 'type', - 'name', - 'prepend', - 'append', - 'caption', - 'label', - 'labelPositionedAbove', - 'value', - 'placeholder', - 'displaySuccess', - 'displayFailure', - 'validationClass', - 'errorMessage' - ); + // Only highlight valid fields if there are invalid fields. + return $this->getDisplaySuccess() ? 'is-valid' : null; } - protected function getModel(): ?Model + protected function convertArrayNameInNotation(string $notation = '.'): string { - return $this->model; + return str_replace(['[', ']'], [$notation, ''], $this->getName()); } protected function getName(): string @@ -188,43 +171,66 @@ protected function getName(): string return $this->name ?? ''; } - protected function getPrepend(): ?string + protected function getDisplayFailure(): bool { - $prepend = $this->prepend; - - // Fallback for usage of closure with multilingual disabled. - return $prepend instanceof Closure ? $prepend(app()->getLocale()) : $prepend; + return $this->displayFailure; } - abstract protected function setPrepend(): ?string; + abstract protected function setDisplayFailure(): bool; - protected function getAppend(): ?string + protected function getDisplaySuccess(): bool { - $append = $this->append; - - // Fallback for usage of closure with multilingual disabled. - return $append instanceof Closure ? $append(app()->getLocale()) : $append; + return $this->displaySuccess; } - abstract protected function setAppend(): ?string; + abstract protected function setDisplaySuccess(): bool; - protected function getCaption(): ?string + protected function getErrorMessage(?ViewErrorBag $errors): ?string { - return $this->caption; - } + if (! $errors) { + return null; + } + if (! $this->getDisplayFailure()) { + return null; + } - abstract protected function setCaption(): ?string; + return $errors->first($this->convertArrayNameInNotation()); + } - protected function getLabel(): ?string + protected function getSuccessMessage(): ?string { - $label = $this->label ?: (string) __('validation.attributes.' . $this->removeArrayCharactersFromName()); + if ($this->getDisplaySuccess()) { + return (string) __('Field correctly filled.'); + } - return $this->hideLabel ? null : $label; + return null; } - protected function removeArrayCharactersFromName(): string + protected function getViewParams(): array { - return strstr($this->getName(), '[', true) ?: $this->getName(); + return array_merge(parent::getViewParams(), [ + 'validationClass' => fn(?ViewErrorBag $errors) => $this->getValidationClass($errors), + 'errorMessage' => fn(?ViewErrorBag $errors) => $this->getErrorMessage($errors), + 'successMessage' => fn() => $this->getSuccessMessage(), + 'labelPositionedAbove' => $this->getLabelPositionedAbove(), + 'label' => $this->getLabel(), + 'type' => $this->getType(), + 'name' => $this->getName(), + 'value' => $this->getValue(), + 'placeholder' => $this->getPlaceholder(), + 'prepend' => $this->getPrepend(), + 'append' => $this->getAppend(), + 'caption' => $this->getCaption(), + ]); + } + + protected function getComponentId(): string + { + if ($this->componentId) { + return $this->componentId; + } + + return $this->getType() . '-' . Str::slug(Str::snake($this->convertArrayNameInNotation('-'), '-')); } protected function getLabelPositionedAbove(): bool @@ -234,59 +240,87 @@ protected function getLabelPositionedAbove(): bool abstract protected function setLabelPositionedAbove(): bool; - protected function getValue() + protected function getLabel(): ?string { - $value = old($this->convertArrayNameInNotation()) ?: $this->value; - // Fallback for usage of closure with multilingual disabled. - $value = $value instanceof Closure ? $value(app()->getLocale()) : $value; + if ($this->hideLabel) { + return null; + } + if ($this->label) { + return $this->label; + } - return $value ?? optional($this->getModel())->{$this->convertArrayNameInNotation()}; + return (string) __('validation.attributes.' . $this->removeArrayCharactersFromName()); } - protected function convertArrayNameInNotation(string $notation = '.'): string + protected function removeArrayCharactersFromName(): string { - return str_replace(['[', ']'], [$notation, ''], $this->getName()); + return strstr($this->getName(), '[', true) ?: $this->getName(); } - protected function getPlaceholder(): ?string + /** @return mixed */ + protected function getValue() { - return $this->placeholder - ?? ($this->getLabel() ?: (string) __('validation.attributes.' . $this->removeArrayCharactersFromName())); + $oldValue = old($this->convertArrayNameInNotation()); + if ($oldValue) { + return $oldValue; + } + // Fallback for usage of closure with multilingual disabled. + if ($this->value instanceof Closure) { + return ($this->value)(app()->getLocale()); + } + if (isset($this->value)) { + return $this->value; + } + + return optional($this->model)->{$this->convertArrayNameInNotation()}; } - protected function getDisplaySuccess(): bool + protected function getPlaceholder(): ?string { - return $this->displaySuccess; - } + if (isset($this->placeholder)) { + return $this->placeholder; + } + $label = $this->getLabel(); + if ($label) { + return $label; + } - abstract protected function setDisplaySuccess(): bool; + return (string) __('validation.attributes.' . $this->removeArrayCharactersFromName()); + } - protected function getDisplayFailure(): bool + protected function getPrepend(): ?string { - return $this->displayFailure; + // Fallback for usage of closure with multilingual disabled. + if ($this->prepend instanceof Closure) { + return ($this->prepend)(app()->getLocale()); + } + + return $this->prepend; } - abstract protected function setDisplayFailure(): bool; + abstract protected function setPrepend(): ?string; - protected function getValidationClass(): ?string + protected function getAppend(): ?string { - if (session()->has('errors')) { - return session()->get('errors')->has($this->convertArrayNameInNotation()) - ? ($this->getDisplayFailure() ? 'is-invalid' : null) - : ($this->getDisplaySuccess() ? 'is-valid' : null); + // Fallback for usage of closure with multilingual disabled. + if ($this->append instanceof Closure) { + return ($this->append)(app()->getLocale()); } - return null; + return $this->append; } - protected function getErrorMessage(): ?string + abstract protected function setAppend(): ?string; + + protected function getCaption(): ?string { - return optional(session()->get('errors'))->first($this->convertArrayNameInNotation()); + return $this->caption; } - protected function getComponentId(): string + abstract protected function setCaption(): ?string; + + protected function getModel(): ?Model { - return parent::getComponentId() - ?? $this->getType() . '-' . Str::slug(Str::snake($this->convertArrayNameInNotation('-'), '-')); + return $this->model; } } diff --git a/src/Components/Form/Abstracts/MultilingualAbstract.php b/src/Components/Form/Abstracts/MultilingualAbstract.php index 3b02cea6..6cbd9e05 100644 --- a/src/Components/Form/Abstracts/MultilingualAbstract.php +++ b/src/Components/Form/Abstracts/MultilingualAbstract.php @@ -3,13 +3,11 @@ namespace Okipa\LaravelBootstrapComponents\Components\Form\Abstracts; use Closure; +use Illuminate\Support\ViewErrorBag; use Okipa\LaravelBootstrapComponents\Components\Form\Multilingual\Resolver; -use Okipa\LaravelBootstrapComponents\Components\Form\Traits\MultilingualValidityChecks; abstract class MultilingualAbstract extends FormAbstract { - use MultilingualValidityChecks; - protected Resolver $multilingualResolver; protected array $locales; @@ -59,7 +57,7 @@ protected function multilingualRender(array $extraData = []): string $componentHtml = $view ? (string) view( 'bootstrap-components::' . $view, - array_merge($this->getLocalizedValues($locale), $extraData) + array_merge($this->getLocalizedViewParams($locale), $extraData) )->render() : ''; $html .= trim($componentHtml); @@ -68,39 +66,41 @@ protected function multilingualRender(array $extraData = []): string return $html; } - protected function getLocalizedValues(string $locale): array - { - return array_merge($this->getValues(), $this->getLocalizedParameters($locale)); + protected function getLocalizedViewParams(string $locale): array + { + return [ + 'component' => $this, + 'locale' => $locale, + 'containerId' => $this->getLocalizedContainerId($locale), + 'containerClasses' => $this->getContainerClasses(), + 'containerHtmlAttributes' => $this->getContainerHtmlAttributes(), + 'componentId' => $this->getLocalizedComponentId($locale), + 'componentClasses' => $this->getComponentClasses(), + 'componentHtmlAttributes' => $this->getLocalizedComponentHtmlAttributes($locale), + 'validationClass' => fn( + ?ViewErrorBag $errors, + ?string $locale + ) => $this->getLocalizedValidationClass($errors, $locale), + 'errorMessage' => fn( + ?ViewErrorBag $errors, + ?string $locale + ) => $this->getLocalizedErrorMessage($errors, $locale), + 'successMessage' => fn() => $this->getSuccessMessage(), + 'labelPositionedAbove' => $this->getLabelPositionedAbove(), + 'label' => $this->getLocalizedLabel($locale), + 'type' => $this->getType(), + 'name' => $this->getLocalizedName($locale), + 'value' => $this->getLocalizedValue($locale), + 'placeholder' => $this->getLocalizedPlaceholder($locale), + 'prepend' => $this->getLocalizedPrepend($locale), + 'append' => $this->getLocalizedAppend($locale), + 'caption' => $this->getCaption(), + ]; } - protected function getLocalizedParameters(string $locale): array + protected function getLocalizedContainerId(string $locale): ?string { - $parentParams = $this->getParameters(); - $componentId = $this->getLocalizedComponentId($locale); - $containerId = $this->getLocalizedContainerId($locale); - $componentHtmlAttributes = $this->getLocalizedComponentHtmlAttributes($locale); - $name = $this->getLocalizedName($locale); - $prepend = $this->getLocalizedPrepend($locale); - $append = $this->getLocalizedAppend($locale); - $label = $this->getLocalizedLabel($locale); - $value = $this->getLocalizedValue($locale); - $placeholder = $this->getLocalizedPlaceholder($locale); - $validationClass = $this->getLocalizedValidationClass($locale); - $errorMessage = $this->getLocalizedErrorMessage($locale); - - return array_merge($parentParams, compact( - 'componentId', - 'containerId', - 'componentHtmlAttributes', - 'name', - 'prepend', - 'append', - 'label', - 'value', - 'placeholder', - 'validationClass', - 'errorMessage' - )); + return $this->getContainerId() ? $this->getContainerId() . '-' . $locale : null; } protected function getLocalizedComponentId(string $locale): string @@ -108,35 +108,37 @@ protected function getLocalizedComponentId(string $locale): string return $this->getComponentId() . '-' . $locale; } - protected function getLocalizedContainerId(string $locale): ?string - { - return $this->getContainerId() ? $this->getContainerId() . '-' . $locale : null; - } - protected function getLocalizedComponentHtmlAttributes(string $locale): array { return array_merge(['data-locale' => $locale], $this->getComponentHtmlAttributes()); } - protected function getLocalizedName(string $locale): string + protected function getLocalizedValidationClass(?ViewErrorBag $errors, string $locale): ?string { - return $this->multilingualResolver->resolveLocalizedName($this->getName(), $locale); - } - - protected function getLocalizedPrepend(string $locale): ?string - { - $prepend = $this->prepend; + if (! $errors) { + return null; + } + if ($errors->isEmpty()) { + return null; + } + if ($errors->has($this->multilingualResolver->resolveErrorMessageBagKey($this->getName(), $locale))) { + return $this->getDisplayFailure() ? 'is-invalid' : null; + } - // fallback for usage of closure with multilingual disabled - return $prepend instanceof Closure ? $prepend($locale) : $prepend; + // Only highlight valid fields if there are invalid fields. + return $this->getDisplaySuccess() ? 'is-valid' : null; } - protected function getLocalizedAppend(string $locale): ?string + protected function getLocalizedErrorMessage(?ViewErrorBag $errors, string $locale): ?string { - $append = $this->append; + if (! $errors) { + return null; + } + if (! $this->getDisplayFailure()) { + return null; + } - // fallback for usage of closure with multilingual disabled - return $append instanceof Closure ? $append($locale) : $append; + return $this->multilingualResolver->resolveErrorMessage($this->getName(), $errors, $locale); } protected function getLocalizedLabel(string $locale): ?string @@ -146,18 +148,30 @@ protected function getLocalizedLabel(string $locale): ?string return $label ? $label . ' (' . mb_strtoupper($locale) . ')' : null; } + protected function getLocalizedName(string $locale): string + { + return $this->multilingualResolver->resolveLocalizedName($this->getName(), $locale); + } + protected function getLocalizedValue(string $locale) { - $oldValue = $this->multilingualResolver->resolveLocalizedOldValue($this->getName(), $locale); - /** @var Closure|null $valueClosure */ - $valueClosure = $this->multilingualMode() ? $this->value : null; - $modelValue = $this->multilingualResolver->resolveLocalizedModelValue( + $oldLocalizedValue = $this->multilingualResolver->resolveLocalizedOldValue($this->getName(), $locale); + if ($oldLocalizedValue) { + return $oldLocalizedValue; + } + if ($this->value instanceof Closure) { + return ($this->value)($locale); + } + $localizedValue = $this->multilingualResolver->resolveLocalizedModelValue( $this->getName(), $locale, $this->getModel() ); + if ($localizedValue) { + return $localizedValue; + } - return $oldValue ?? ($valueClosure ? $valueClosure($locale) : $modelValue); + return $this->getValue(); } protected function getLocalizedPlaceholder(string $locale): ?string @@ -167,21 +181,21 @@ protected function getLocalizedPlaceholder(string $locale): ?string return $placeholder ? $placeholder . ' (' . mb_strtoupper($locale) . ')' : null; } - protected function getLocalizedValidationClass(string $locale): ?string + protected function getLocalizedPrepend(string $locale): ?string { - if (session()->has('errors')) { - $errorMessageBagKey = $this->multilingualResolver->resolveErrorMessageBagKey($this->getName(), $locale); - - return session()->get('errors')->has($errorMessageBagKey) - ? ($this->getDisplayFailure() ? 'is-invalid' : null) - : ($this->getDisplaySuccess() ? 'is-valid' : null); + if ($this->prepend instanceof Closure) { + return ($this->prepend)($locale); } - return null; + return $this->getPrepend(); } - protected function getLocalizedErrorMessage(string $locale): ?string + protected function getLocalizedAppend(string $locale): ?string { - return $this->multilingualResolver->resolveErrorMessage(parent::getName(), $locale); + if ($this->append instanceof Closure) { + return ($this->append)($locale); + } + + return $this->getAppend(); } } diff --git a/src/Components/Form/Abstracts/RadioAbstract.php b/src/Components/Form/Abstracts/RadioAbstract.php index 5f2253f6..e678ac31 100644 --- a/src/Components/Form/Abstracts/RadioAbstract.php +++ b/src/Components/Form/Abstracts/RadioAbstract.php @@ -11,8 +11,11 @@ abstract class RadioAbstract extends CheckableAbstract protected function getComponentId(): string { - return $this->componentId - ?? $this->getType() . '-' . Str::slug(Str::snake($this->convertArrayNameInNotation('-'), '-') + if ($this->componentId) { + return $this->componentId; + } + + return $this->getType() . '-' . Str::slug(Str::snake($this->convertArrayNameInNotation('-'), '-') . '-' . Str::snake($this->getValue(), '-')); } @@ -22,7 +25,10 @@ protected function getChecked(): bool if (isset($old) && $old !== '') { return $old === (string) $this->value; } + if (isset($this->checked)) { + return $this->checked; + } - return $this->checked ?? optional($this->model)->{$this->getName()} === $this->value; + return optional($this->model)->{$this->getName()} === $this->value; } } diff --git a/src/Components/Form/Abstracts/SelectableAbstract.php b/src/Components/Form/Abstracts/SelectableAbstract.php index 155ddf52..d0a06405 100644 --- a/src/Components/Form/Abstracts/SelectableAbstract.php +++ b/src/Components/Form/Abstracts/SelectableAbstract.php @@ -70,17 +70,14 @@ public function multiple(bool $multiple = true): self return $this; } - protected function getParameters(): array + protected function getViewParams(): array { - $options = $this->getOptions(); - $optionValueField = $this->getOptionValueField(); - $optionLabelField = $this->getOptionLabelField(); - $multiple = $this->getMultiple(); - - return array_merge( - parent::getParameters(), - compact('options', 'optionValueField', 'optionLabelField', 'multiple') - ); + return array_merge(parent::getViewParams(), [ + 'options' => $this->getOptions(), + 'optionValueField' => $this->getOptionValueField(), + 'optionLabelField' => $this->getOptionLabelField(), + 'multiple' => $this->getMultiple(), + ]); } protected function getOptions(): array diff --git a/src/Components/Form/Abstracts/TemporalAbstract.php b/src/Components/Form/Abstracts/TemporalAbstract.php index 3a067e3d..9c4e7fe4 100644 --- a/src/Components/Form/Abstracts/TemporalAbstract.php +++ b/src/Components/Form/Abstracts/TemporalAbstract.php @@ -9,7 +9,7 @@ abstract class TemporalAbstract extends FormAbstract { use TemporalValidityChecks; - protected string $format; + private string $format; public function __construct() { diff --git a/src/Components/Form/Abstracts/UploadableAbstract.php b/src/Components/Form/Abstracts/UploadableAbstract.php index b83adb31..b7832eca 100644 --- a/src/Components/Form/Abstracts/UploadableAbstract.php +++ b/src/Components/Form/Abstracts/UploadableAbstract.php @@ -35,12 +35,12 @@ public function showRemoveCheckbox(bool $showRemoveCheckbox = true, ?string $rem return $this; } - protected function getValues(): array + protected function getViewParams(): array { - return array_merge(parent::getValues(), [ + return array_merge(parent::getViewParams(), [ 'uploadedFileHtml' => $this->getUploadedFileHtml(), 'showRemoveCheckbox' => $this->getShowRemoveCheckbox(), - 'removeCheckboxLabel' => $this->getRemoveCheckboxLabel(parent::getValues()['label']), + 'removeCheckboxLabel' => $this->getRemoveCheckboxLabel(parent::getViewParams()['label']), 'removeCheckboxName' => $this->getShowRemoveCheckboxName(), ]); } diff --git a/src/Components/Form/Multilingual/Resolver.php b/src/Components/Form/Multilingual/Resolver.php index 52de947c..92bd2bc3 100644 --- a/src/Components/Form/Multilingual/Resolver.php +++ b/src/Components/Form/Multilingual/Resolver.php @@ -3,6 +3,7 @@ namespace Okipa\LaravelBootstrapComponents\Components\Form\Multilingual; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\ViewErrorBag; class Resolver { @@ -25,19 +26,19 @@ public function resolveLocalizedOldValue(string $name, string $locale): ?string public function resolveLocalizedModelValue(string $name, string $locale, ?Model $model): ?string { - return data_get(optional($model)->{$name}, $locale); + return data_get($model, "$name.$locale"); } - public function resolveErrorMessage(string $name, string $locale): ?string + public function resolveErrorMessage(string $name, ViewErrorBag $errors, string $locale): ?string { $errorMessageBagKey = $this->resolveErrorMessageBagKey($name, $locale); - $errorMessage = optional(session()->get('errors'))->first($errorMessageBagKey); + $errorMessage = $errors->first($errorMessageBagKey); $errorMessage = $this->undoInputNameLaravelUnderscoreRemovalInErrorMessage($name, $locale, $errorMessage); return $errorMessage ? str_replace( $errorMessageBagKey, - ((string) __('validation.attributes.' . $name)) . ' (' . strtoupper($locale) . ')', + __('validation.attributes.' . $name) . ' (' . strtoupper($locale) . ')', $errorMessage ) : null; diff --git a/src/Components/Form/Traits/MultilingualValidityChecks.php b/src/Components/Form/Traits/MultilingualValidityChecks.php deleted file mode 100644 index 3cad83aa..00000000 --- a/src/Components/Form/Traits/MultilingualValidityChecks.php +++ /dev/null @@ -1,17 +0,0 @@ -value) && $this->value && $this->multilingualMode()) { - throw new InvalidArgumentException(get_class($this) . ' : A multilingual component value has to - be set from this callable result : « ->value(function($locale){}) ».'); - } - } -} diff --git a/src/Components/Form/Traits/RadioValidityChecks.php b/src/Components/Form/Traits/RadioValidityChecks.php index f10ffec8..c674e9e4 100644 --- a/src/Components/Form/Traits/RadioValidityChecks.php +++ b/src/Components/Form/Traits/RadioValidityChecks.php @@ -9,7 +9,8 @@ trait RadioValidityChecks protected function checkValuesValidity(): void { parent::checkValuesValidity(); - if (! isset($this->value) || $this->value === '') { + $value = $this->getValue(); + if (! isset($value) || $value === '') { throw new InvalidArgumentException( get_class($this) . ' : Missing $value property. Please use the value() method to set a value.' ); diff --git a/src/Components/Form/Traits/SelectValidityChecks.php b/src/Components/Form/Traits/SelectValidityChecks.php index 55a814cf..efc8e7b8 100644 --- a/src/Components/Form/Traits/SelectValidityChecks.php +++ b/src/Components/Form/Traits/SelectValidityChecks.php @@ -57,12 +57,12 @@ protected function checkSelectedFieldToCompareExistenceInOption(array $option): protected function checkMultipleModeModelAttributeType(): void { - if ($this->model && isset($this->model->{$this->getName()}) && ! is_array($this->model->{$this->getName()})) { + if ($this->getModel() && $this->getModel()->{$this->getName()} && ! is_array($this->getModel()->{$this->getName()})) { throw new InvalidArgumentException( get_class($this) . ' : The « ' . $this->getName() . ' » attribute from the given « ' - . $this->model->getMorphClass() + . $this->getModel()->getMorphClass() . ' » model has to be an array when the select() component is in multiple mode : « ' - . gettype($this->model->{$this->getName()}) . ' » type given.' + . gettype($this->getModel()->{$this->getName()}) . ' » type given.' ); } } @@ -83,7 +83,7 @@ protected function checkSingleModeSelectedValueToCompareType(): void if ( $this->selectedValueToCompare && ! is_string($this->selectedValueToCompare) - && ! is_integer($this->selectedValueToCompare) + && ! is_int($this->selectedValueToCompare) ) { throw new InvalidArgumentException( get_class($this) . ' : Invalid selected() second $valueToCompare argument. ' diff --git a/src/Components/Form/Traits/TemporalValidityChecks.php b/src/Components/Form/Traits/TemporalValidityChecks.php index 98f0c0d4..bb41410a 100644 --- a/src/Components/Form/Traits/TemporalValidityChecks.php +++ b/src/Components/Form/Traits/TemporalValidityChecks.php @@ -17,9 +17,9 @@ protected function checkValuesValidity(): void protected function checkFormat(): void { - if (! $this->format) { + if (! $this->getFormat()) { throw new RuntimeException(get_class($this) . ' : No config or custom format given for the input' - . ucfirst($this->type) . ' component.'); + . ucfirst($this->getType()) . ' component.'); } } @@ -28,7 +28,7 @@ protected function checkValue(): void try { Carbon::parse(parent::getValue()); } catch (Exception $exception) { - throw new RuntimeException(get_class($this) . ' : The value for the input' . ucfirst($this->type) + throw new RuntimeException(get_class($this) . ' : The value for the input' . ucfirst($this->getType()) . ' component must be a valid DateTime object or a formatted string, « ' . parent::getValue() . ' » given.'); } diff --git a/src/Components/Media/Abstracts/ImageAbstract.php b/src/Components/Media/Abstracts/ImageAbstract.php index e05575e0..834ffb96 100644 --- a/src/Components/Media/Abstracts/ImageAbstract.php +++ b/src/Components/Media/Abstracts/ImageAbstract.php @@ -83,26 +83,31 @@ public function linkHtmlAttributes(array $linkHtmlAttributes): self return $this; } - protected function getValues(): array + protected function getViewParams(): array { - $alt = $this->getAlt(); - $width = $this->getWidth(); - $height = $this->getHeight(); - $linkId = $this->getLinkId(); - $linkClasses = $this->getLinkClasses(); - $linkUrl = $this->getLinkUrl(); - $linkTitle = $this->getLinkTitle(); - $linkHtmlAttributes = $this->getLinkHtmlAttributes(); - - return array_merge( - parent::getValues(), - compact('alt', 'width', 'height', 'linkId', 'linkClasses', 'linkUrl', 'linkTitle', 'linkHtmlAttributes') - ); + return array_merge(parent::getViewParams(), [ + 'alt' => $this->getAlt(), + 'width' => $this->getWidth(), + 'height' => $this->getHeight(), + 'linkId' => $this->getLinkId(), + 'linkClasses' => $this->getLinkClasses(), + 'linkUrl' => $this->getLinkUrl(), + 'linkTitle' => $this->getLinkTitle(), + 'linkHtmlAttributes' => $this->getLinkHtmlAttributes(), + ]); } protected function getAlt(): ?string { - return $this->alt ?: $this->getLabel() ?: $this->linkTitle; + if ($this->alt) { + return $this->alt; + } + $label = $this->getLabel(); + if ($label) { + return $label; + } + + return $this->linkTitle; } protected function getWidth(): ?int @@ -134,7 +139,15 @@ protected function getLinkUrl(): ?string protected function getLinkTitle(): ?string { - return $this->linkTitle ?: $this->getLabel() ?: $this->alt; + if ($this->linkTitle) { + return $this->linkTitle; + } + $label = $this->getLabel(); + if ($label) { + return $label; + } + + return $this->alt; } protected function getLinkHtmlAttributes(): array diff --git a/src/Components/Media/Abstracts/MediaAbstract.php b/src/Components/Media/Abstracts/MediaAbstract.php index 05009a1e..5901ce82 100644 --- a/src/Components/Media/Abstracts/MediaAbstract.php +++ b/src/Components/Media/Abstracts/MediaAbstract.php @@ -39,13 +39,13 @@ public function caption(?string $caption): self return $this; } - protected function getValues(): array + protected function getViewParams(): array { - $label = $this->getLabel(); - $src = $this->getSrc(); - $caption = $this->getCaption(); - - return array_merge(parent::getValues(), compact('label', 'src', 'caption')); + return array_merge(parent::getViewParams(), [ + 'label' => $this->getLabel(), + 'src' => $this->getSrc(), + 'caption' => $this->getCaption(), + ]); } protected function getLabel(): ?string diff --git a/src/Components/Media/Abstracts/VideoAbstract.php b/src/Components/Media/Abstracts/VideoAbstract.php index 9033cf49..9fa6af83 100644 --- a/src/Components/Media/Abstracts/VideoAbstract.php +++ b/src/Components/Media/Abstracts/VideoAbstract.php @@ -19,11 +19,9 @@ public function poster(string $poster): self return $this; } - protected function getValues(): array + protected function getViewParams(): array { - $poster = $this->getPoster(); - - return array_merge(parent::getValues(), compact('poster')); + return array_merge(parent::getViewParams(), ['poster' => $this->getPoster()]); } protected function getPoster(): ?string diff --git a/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php b/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php index 85b267c7..a471cc0c 100644 --- a/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputCheckableTestAbstract.php @@ -147,9 +147,7 @@ public function testSetNullValue(): void public function testSetValueFromClosureWithDisabledMultilingual(): void { - $html = $this->getComponent()->name('name')->value(function () { - return true; - })->toHtml(); + $html = $this->getComponent()->name('name')->value(fn() => true)->toHtml(); self::assertStringContainsString('checked="checked', $html); } @@ -163,51 +161,36 @@ public function testSetValueOverridesModelValue(): void { $user = $this->createUniqueUser(); $html = $this->getComponent()->model($user)->name('active')->value(false)->toHtml(); - self::assertStringContainsString('checked="checked', $html); + self::assertStringNotContainsString('checked="checked', $html); } public function testOldValue(): void { - $oldValue = true; - $value = false; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['active' => (string) $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['active' => '1'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('active')->value($value)->toHtml(); + $html = $this->getComponent()->name('active')->checked(false)->toHtml(); self::assertStringContainsString('checked="checked', $html); } public function testOldArrayValue(): void { - $oldValue = true; - $value = false; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['active' => [0 => (string) $oldValue]]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['active' => ['1']])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('active[0]')->value($value)->toHtml(); + $html = $this->getComponent()->name('active[0]')->checked(false)->toHtml(); self::assertStringContainsString('checked="checked', $html); } public function testOldValueNotChecked(): void { - $oldValue = false; - $value = true; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['active' => (string) $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['active' => '0'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('active')->value($value)->toHtml(); + $html = $this->getComponent()->name('active')->checked(true)->toHtml(); self::assertStringNotContainsString('checked="checked', $html); } diff --git a/tests/Unit/Form/Abstracts/InputFileTestAbstract.php b/tests/Unit/Form/Abstracts/InputFileTestAbstract.php index 923688b1..bc59f87f 100644 --- a/tests/Unit/Form/Abstracts/InputFileTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputFileTestAbstract.php @@ -73,38 +73,28 @@ public function testSetValueFromClosureWithDisabledMultilingual(): void public function testOldValue(): void { - $oldValue = 'old-value'; - $value = 'custom-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => 'old-value'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value($value)->toHtml(); + $html = $this->getComponent()->name('name')->value('custom-value')->toHtml(); self::assertStringContainsString('', $html); + . '-name">old-value', $html); self::assertStringNotContainsString('', $html); + . '-name">custom-value', $html); } public function testOldArrayValue(): void { - $oldValue = 'old-value'; - $value = 'custom-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => [0 => $oldValue]]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => [0 => 'old-value']])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name[0]')->value($value)->toHtml(); + $html = $this->getComponent()->name('name[0]')->value('custom-value')->toHtml(); self::assertStringContainsString('', $html); + . '-name-0">old-value', $html); self::assertStringNotContainsString('', $html); + . '-name-0">custom-value', $html); } public function testDefaultPlaceholder(): void @@ -159,7 +149,6 @@ public function testNoPlaceholderWithNoLabel(): void . '-name">' . __('No file selected.') . '', $html); } - public function testHidePlaceholder(): void { $html = $this->getComponent()->name('name')->placeholder(false)->toHtml(); diff --git a/tests/Unit/Form/Abstracts/InputMultilingualTestAbstract.php b/tests/Unit/Form/Abstracts/InputMultilingualTestAbstract.php index 99723cc4..39ea4b21 100644 --- a/tests/Unit/Form/Abstracts/InputMultilingualTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputMultilingualTestAbstract.php @@ -3,7 +3,7 @@ namespace Okipa\LaravelBootstrapComponents\Tests\Unit\Form\Abstracts; use Illuminate\Support\MessageBag; -use InvalidArgumentException; +use Illuminate\Support\ViewErrorBag; use Okipa\LaravelBootstrapComponents\Components\Form\Abstracts\MultilingualAbstract; use Okipa\LaravelBootstrapComponents\Tests\Dummy\Resolver; use Okipa\LaravelBootstrapComponents\Tests\Models\User; @@ -94,14 +94,6 @@ public function testLocalizedModelValueFromCustomMultilingualResolver(): void } } - public function testSetLocalizedWrongValue(): void - { - $locales = ['fr', 'en']; - $value = 'custom-value'; - $this->expectException(InvalidArgumentException::class); - $this->getComponent()->name('name')->locales($locales)->value($value)->toHtml(); - } - public function testSetLocalizedValue(): void { $locales = ['fr', 'en']; @@ -112,9 +104,7 @@ public function testSetLocalizedValue(): void $html = $this->getComponent() ->name('name') ->locales($locales) - ->value(function ($locale) use ($values) { - return $values[$locale]; - }) + ->value(fn($locale) => $values[$locale]) ->toHtml(); foreach ($locales as $locale) { self::assertStringContainsString(' value="' . $values[$locale] . '"', $html); @@ -131,10 +121,7 @@ public function testLocalizedOldValue(): void $values[$locale] = 'custom-value-' . $locale; } $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValues) { - $request = request()->merge(['name' => $oldValues]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => $oldValues])->flash(), ]); $this->call('GET', 'test'); $html = $this->getComponent()->name('name')->locales($locales)->value(function ($locale) use ($values) { @@ -160,15 +147,10 @@ public function testLocalizedOldValueFromCustomMultilingualResolver(): void $values[$locale] = 'custom-value-' . $locale; } $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValues) { - $request = request()->merge($oldValues); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge($oldValues)->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value(function ($locale) use ($values) { - return $values[$locale]; - })->toHtml(); + $html = $this->getComponent()->name('name')->value(fn($locale) => $values[$locale])->toHtml(); foreach ($resolverLocales as $resolverLocale) { self::assertStringContainsString('value="' . $oldValues['name_' . $resolverLocale] . '"', $html); } @@ -183,9 +165,7 @@ public function testSetLocalizedPrepend(): void $html = $this->getComponent() ->name('name') ->locales($locales) - ->prepend(function ($locale) { - return 'prepend-' . $locale; - }) + ->prepend(fn($locale) => 'prepend-' . $locale) ->toHtml(); foreach ($locales as $locale) { self::assertStringContainsString('prepend-' . $locale . '', $html); @@ -259,9 +239,8 @@ public function testSetLocalizedContainerId(): void public function testLocalizedErrorMessage(): void { $locales = ['fr', 'en']; - $errors = app(MessageBag::class); - $errors->add('name.fr', 'Dummy name.fr error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('name.fr', 'Dummy name.fr error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent()->name('name')->locales($locales)->displayFailure()->render(compact('errors')); self::assertStringContainsString( 'id="' . $this->getComponentType() . '-name-fr" class="component form-control is-invalid"', @@ -281,9 +260,8 @@ public function testLocalizedErrorMessage(): void public function testLocalizedErrorMessageWithSeveralWords(): void { $locales = ['fr', 'en']; - $errors = app(MessageBag::class); - $errors->add('last_name.fr', 'Dummy last name.fr error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('last_name.fr', 'Dummy last name.fr error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent() ->name('last_name') ->locales($locales) @@ -311,9 +289,8 @@ public function testLocalizedErrorMessageWithSeveralWordsAndCustomMultilingualRe { config()->set('bootstrap-components.form.multilingualResolver', Resolver::class); $locales = ['fr', 'en']; - $errors = app(MessageBag::class); - $errors->add('last_name_fr', 'Dummy last name fr error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('last_name_fr', 'Dummy last name fr error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent() ->name('last_name') ->locales($locales) @@ -340,9 +317,8 @@ public function testLocalizedErrorMessageWithSeveralWordsAndCustomMultilingualRe public function testLocalizedErrorMessageFromCustomMultilingualResolver(): void { config()->set('bootstrap-components.form.multilingualResolver', Resolver::class); - $errors = app(MessageBag::class); - $errors->add('name_en', 'Dummy name_en error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('name_en', 'Dummy name_en error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent()->name('name')->displayFailure()->render(compact('errors')); self::assertStringContainsString( 'id="' . $this->getComponentType() . '-name-en" class="component form-control is-invalid"', diff --git a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php index 76ae32bd..4d69a158 100644 --- a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php @@ -2,7 +2,6 @@ namespace Okipa\LaravelBootstrapComponents\Tests\Unit\Form\Abstracts; -use RuntimeException; use InvalidArgumentException; use Okipa\LaravelBootstrapComponents\Components\Form\Abstracts\RadioAbstract; @@ -136,55 +135,39 @@ public function testModelValueChecked(): void public function testOldValue(): void { - $oldValue = 'old-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => 'old-value'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value($oldValue)->checked(false)->toHtml(); + $html = $this->getComponent()->name('name')->value('old-value')->checked(false)->toHtml(); self::assertStringContainsString('checked="checked', $html); } public function testOldZeroValue(): void { - $oldValue = 0; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - // http values are always stored as string - $request = request()->merge(['name' => (string) $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => '0'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value($oldValue)->checked(false)->toHtml(); + $html = $this->getComponent()->name('name')->value(0)->checked(false)->toHtml(); self::assertStringContainsString('checked="checked', $html); } public function testOldValueNotChecked(): void { - $oldValue = 'old-value'; - $value = 'custom-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => 'old-value'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value($value)->checked()->toHtml(); + $html = $this->getComponent()->name('name')->value('custom-value')->checked()->toHtml(); self::assertStringNotContainsString('checked="checked', $html); } public function testSetLabel(): void { - $label = 'custom-label'; - $html = $this->getComponent()->name('name')->label($label)->toHtml(); + $html = $this->getComponent()->name('name')->label('custom-label')->toHtml(); self::assertStringContainsString( - '', + '', $html ); } diff --git a/tests/Unit/Form/Abstracts/InputTestAbstract.php b/tests/Unit/Form/Abstracts/InputTestAbstract.php index e2ac2591..7b7d08ed 100644 --- a/tests/Unit/Form/Abstracts/InputTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputTestAbstract.php @@ -3,6 +3,7 @@ namespace Okipa\LaravelBootstrapComponents\Tests\Unit\Form\Abstracts; use Illuminate\Support\MessageBag; +use Illuminate\Support\ViewErrorBag; use Okipa\LaravelBootstrapComponents\Components\ComponentAbstract; use Okipa\LaravelBootstrapComponents\Components\Form\Abstracts\FormAbstract; use Okipa\LaravelBootstrapComponents\Tests\BootstrapComponentsTestCase; @@ -223,34 +224,24 @@ public function testSetValueFromClosureWithDisabledMultilingual(): void public function testOldValue(): void { - $oldValue = 'old-value'; - $value = 'custom-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => 'old-value'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value($value)->toHtml(); - self::assertStringContainsString(' value="' . $oldValue . '"', $html); - self::assertStringNotContainsString(' value="' . $value . '"', $html); + $html = $this->getComponent()->name('name')->value('custom-value')->toHtml(); + self::assertStringContainsString(' value="old-value"', $html); + self::assertStringNotContainsString(' value="custom-value"', $html); } public function testOldArrayValue(): void { - $oldValue = 'old-value'; - $value = 'custom-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => [0 => $oldValue]]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => ['old-value']])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name[0]')->value($value)->toHtml(); - self::assertStringContainsString(' value="' . $oldValue . '"', $html); - self::assertStringNotContainsString(' value="' . $value . '"', $html); + $html = $this->getComponent()->name('name[0]')->value('custom-value')->toHtml(); + self::assertStringContainsString(' value="old-value"', $html); + self::assertStringNotContainsString(' value="custom-value"', $html); } public function testSetLabel(): void @@ -368,8 +359,8 @@ public function testSetCustomDisplaySuccess(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $errors = app(MessageBag::class)->add('other_name', 'Dummy error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('other_name', 'Dummy error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent()->name('name')->render(compact('errors')); self::assertStringContainsString('is-valid', $html); self::assertStringContainsString('
', $html); @@ -382,8 +373,8 @@ public function testSetDisplaySuccessReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $errors = app(MessageBag::class)->add('other_name', 'Dummy error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('other_name', 'Dummy error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent()->name('name')->displaySuccess(false)->render(compact('errors')); self::assertStringNotContainsString('is-valid', $html); self::assertStringNotContainsString('
', $html); @@ -396,8 +387,8 @@ public function testSetCustomDisplayFailure(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $errors = app(MessageBag::class)->add('name', 'Dummy error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('name', 'Dummy error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent()->name('name')->render(compact('errors')); self::assertStringContainsString('is-invalid', $html); self::assertStringContainsString('
', $html); @@ -410,8 +401,8 @@ public function testSetDisplayFailureReplacesDefault(): void 'bootstrap-components.components.' . $this->getComponentKey(), get_class($this->getCustomComponent()) ); - $errors = app(MessageBag::class)->add('name', 'Dummy error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('name', 'Dummy error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent()->name('name')->displayFailure(false)->render(compact('errors')); self::assertStringNotContainsString('is-invalid', $html); self::assertStringNotContainsString('
', $html); @@ -420,8 +411,8 @@ public function testSetDisplayFailureReplacesDefault(): void public function testDisplayFailureWithArrayName(): void { - $errors = app(MessageBag::class)->add('name.0', 'Dummy error message.'); - session()->put('errors', $errors); + $messageBag = app(MessageBag::class)->add('name.0', 'Dummy error message.'); + $errors = app(ViewErrorBag::class)->put('default', $messageBag); $html = $this->getComponent()->name('name[0]')->render(compact('errors')); self::assertStringContainsString('is-invalid', $html); self::assertStringContainsString('
', $html); diff --git a/tests/Unit/Form/Abstracts/SelectTestAbstract.php b/tests/Unit/Form/Abstracts/SelectTestAbstract.php index 20cad51f..ad2af649 100644 --- a/tests/Unit/Form/Abstracts/SelectTestAbstract.php +++ b/tests/Unit/Form/Abstracts/SelectTestAbstract.php @@ -235,10 +235,7 @@ public function testOldValue(): void $model = $users->get(1); $old = $users->get(2); $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($old) { - $request = request()->merge(['name' => (string) $old->id]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => (string) $old->id])->flash(), ]); $this->call('GET', 'test'); $html = $this->getComponent() @@ -268,10 +265,7 @@ public function testOldArrayValue(): void $model = $users->get(1); $old = $users->get(2); $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($old) { - $request = request()->merge(['name' => [0 => (string) $old->id]]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => [0 => (string) $old->id]])->flash(), ]); $this->call('GET', 'test'); $html = $this->getComponent() @@ -503,10 +497,7 @@ public function testOldMultipleValue(): void $selectedCompanies = $chunk[1]; $oldCompanies = array_map(static fn($id) => (string) $id, $chunk[2]); $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldCompanies) { - $request = request()->merge(['companies' => $oldCompanies]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['companies' => $oldCompanies])->flash(), ]); $this->call('GET', 'test'); $html = $this->getComponent()->name('companies') @@ -539,10 +530,7 @@ public function testOldMultipleArrayValue(): void $selectedCompanies = $chunk[1]; $oldCompanies = array_map(static fn($id) => (string) $id, $chunk[2]); $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldCompanies) { - $request = request()->merge(['companies' => [0 => $oldCompanies]]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['companies' => [0 => $oldCompanies]])->flash(), ]); $this->call('GET', 'test'); $html = $this->getComponent()->name('companies[0]') diff --git a/tests/Unit/Form/Abstracts/TemporalTestAbstract.php b/tests/Unit/Form/Abstracts/TemporalTestAbstract.php index d0378bd3..d7541f3a 100644 --- a/tests/Unit/Form/Abstracts/TemporalTestAbstract.php +++ b/tests/Unit/Form/Abstracts/TemporalTestAbstract.php @@ -3,8 +3,8 @@ namespace Okipa\LaravelBootstrapComponents\Tests\Unit\Form\Abstracts; use Carbon\Carbon; -use RuntimeException; use Okipa\LaravelBootstrapComponents\Components\Form\Abstracts\TemporalAbstract; +use RuntimeException; abstract class TemporalTestAbstract extends InputTestAbstract { @@ -115,10 +115,7 @@ public function testOldValue(): void $oldValue = $this->faker->dateTime->format($this->getFormat()); $value = $this->faker->dateTime->format($this->getFormat()); $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => $oldValue])->flash(), ]); $this->call('GET', 'test'); $html = $this->getComponent()->name('name')->value($value)->toHtml(); @@ -131,10 +128,7 @@ public function testOldArrayValue(): void $oldValue = $this->faker->dateTime->format($this->getFormat()); $value = $this->faker->dateTime->format($this->getFormat()); $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => [0 => $oldValue]]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => [0 => $oldValue]])->flash(), ]); $this->call('GET', 'test'); $html = $this->getComponent()->name('name[0]')->value($value)->toHtml(); diff --git a/tests/Unit/Form/Abstracts/TextareaTestAbstract.php b/tests/Unit/Form/Abstracts/TextareaTestAbstract.php index 0c46695c..242fd740 100644 --- a/tests/Unit/Form/Abstracts/TextareaTestAbstract.php +++ b/tests/Unit/Form/Abstracts/TextareaTestAbstract.php @@ -54,34 +54,24 @@ public function testSetValueFromClosureWithDisabledMultilingual(): void public function testOldValue(): void { - $oldValue = 'old-value'; - $value = 'custom-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => $oldValue]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => 'old-value'])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value($value)->toHtml(); - self::assertStringContainsString($oldValue . '', $html); - self::assertStringNotContainsString($value . '', $html); + $html = $this->getComponent()->name('name')->value('custom-value')->toHtml(); + self::assertStringContainsString('old-value', $html); + self::assertStringNotContainsString('custom-value', $html); } public function testOldArrayValue(): void { - $oldValue = 'old-value'; - $value = 'custom-value'; $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValue) { - $request = request()->merge(['name' => [0 => $oldValue]]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => ['old-value']])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name[0]')->value($value)->toHtml(); - self::assertStringContainsString($oldValue . '', $html); - self::assertStringNotContainsString($value . '', $html); + $html = $this->getComponent()->name('name[0]')->value('custom-value')->toHtml(); + self::assertStringContainsString('old-value', $html); + self::assertStringNotContainsString('custom-value', $html); } public function testSetCustomLabelPositionedAbove(): void @@ -191,15 +181,14 @@ public function testLocalizedOldValue(): void $values[$locale] = 'custom-value-' . $locale; } $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValues) { - $request = request()->merge(['name' => $oldValues]); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge(['name' => $oldValues])->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->locales($locales)->value(function ($locale) use ($values) { - return $values . '-' . $locale; - })->toHtml(); + $html = $this->getComponent() + ->name('name') + ->locales($locales) + ->value(fn($locale) => $values . '-' . $locale) + ->toHtml(); foreach ($locales as $locale) { self::assertStringContainsString($oldValues[$locale] . '', $html); self::assertStringNotContainsString($values[$locale] . '', $html); @@ -220,15 +209,10 @@ public function testLocalizedOldValueFromCustomMultilingualResolver(): void $values[$locale] = 'test-custom-value-' . $locale; } $this->app['router']->get('test', [ - 'middleware' => 'web', 'uses' => function () use ($oldValues) { - $request = request()->merge($oldValues); - $request->flash(); - }, + 'middleware' => 'web', 'uses' => fn() => request()->merge($oldValues)->flash(), ]); $this->call('GET', 'test'); - $html = $this->getComponent()->name('name')->value(function ($locale) use ($values) { - return $values[$locale]; - })->toHtml(); + $html = $this->getComponent()->name('name')->value(fn($locale) => $values[$locale])->toHtml(); foreach ($resolverLocales as $resolverLocale) { self::assertStringContainsString($oldValues['name_' . $resolverLocale] . '', $html); } From 0c081722eada6bd4d3a152960dba398211b37520 Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Mon, 7 Dec 2020 10:30:56 +0100 Subject: [PATCH 04/14] WIP --- CHANGELOG.md | 5 +++- docs/upgrade-guides/from-v4-to-v5.md | 30 +++++++++++++++++-- .../Form/Abstracts/FormAbstract.php | 1 - .../Form/Abstracts/TemporalAbstract.php | 2 +- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b3c6f46..d00349e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,10 @@ 2020-12-02 -* Method signature changes +* Added Livewire support +* Templates updated +* Methods signature update +* Components default config update :point_right: [See the upgrade guide](/docs/upgrade-guides/from-v4-to-v5.md) diff --git a/docs/upgrade-guides/from-v4-to-v5.md b/docs/upgrade-guides/from-v4-to-v5.md index 33593309..aa0d53e6 100644 --- a/docs/upgrade-guides/from-v4-to-v5.md +++ b/docs/upgrade-guides/from-v4-to-v5.md @@ -2,17 +2,41 @@ Follow the steps below to upgrade the package. -## Method signature changes +## Livewire support -The behaviour of the following methods have gained the ability to merge given HTML classes or HTML attributes to the component default ones instead of replacing them. +There was an issue preventing the error message and the validation class to be displayed on form components when they were used into a livewire component. -To trigger this new behaviour, you'll just have to set the second boolean `$mergeMode` attribute to `false`. +This was related to the fact the session was used to detect errors, which can't work with livewire as the `$errors` variable is passed in the blade view on re-rendering. + +This has been fixed and the error message + the validation class are now generated from the `$errors` variable given in the view instead of the session. + +## Templates updated + +Related to the previous point (Livewire support added), the view templates provided with this package have been updated. + +If you have published the views in order to make some customizations, you will have to [re-publish them](../../README.md#templates) and to redo your customizations. + +## Methods signature update + +The following methods have gained the ability to merge given HTML classes or HTML attributes to the component default ones instead of replacing them. + +To use this new behaviour, you'll just have to set the second `$mergeMode` boolean attribute to `true`. * `componentClasses` * `containerClasses` * `componentHtmlAttributes` * `containerHtmlAttributes` +For example, using `inputText()->name('name')->componentClasses(['merged', 'classes'], true)` will merge the `merged classes` classes to the ones defined by default on the input text component. + +## Components default config update + +The `autocomplete="on"` HTML attribute has been added in the default configuration of the following components: + +* Input email +* Input password +* Input url + ## See all changes See all change with the [comparison tool](https://github.com/Okipa/laravel-bootstrap-components/compare/4.0.0...5.0.0). diff --git a/src/Components/Form/Abstracts/FormAbstract.php b/src/Components/Form/Abstracts/FormAbstract.php index 86965d2e..cd310800 100644 --- a/src/Components/Form/Abstracts/FormAbstract.php +++ b/src/Components/Form/Abstracts/FormAbstract.php @@ -47,7 +47,6 @@ public function __construct() $this->append = $this->setAppend(); $this->labelPositionedAbove = $this->setLabelPositionedAbove(); $this->caption = $this->setCaption(); - $this->errors = new ViewErrorBag(); $this->displaySuccess = $this->setDisplaySuccess(); $this->displayFailure = $this->setDisplayFailure(); } diff --git a/src/Components/Form/Abstracts/TemporalAbstract.php b/src/Components/Form/Abstracts/TemporalAbstract.php index 9c4e7fe4..3a067e3d 100644 --- a/src/Components/Form/Abstracts/TemporalAbstract.php +++ b/src/Components/Form/Abstracts/TemporalAbstract.php @@ -9,7 +9,7 @@ abstract class TemporalAbstract extends FormAbstract { use TemporalValidityChecks; - private string $format; + protected string $format; public function __construct() { From 3434bf010154391307cba83aa73eb6f41e97cd38 Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Mon, 7 Dec 2020 10:35:19 +0100 Subject: [PATCH 05/14] WIP --- docs/api/types.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/types.md b/docs/api/types.md index 6bf1c5be..59b343e8 100644 --- a/docs/api/types.md +++ b/docs/api/types.md @@ -30,12 +30,12 @@ ```php - ->componentId('component-id') ->containerId('container-id') - ->componentClasses(['component', 'classes']) ->containerClasses(['container', 'classes']) - ->componentHtmlAttributes(['component', 'html', 'attributes']); ->containerHtmlAttributes(['container', 'html', 'attributes']) + ->componentId('component-id') + ->componentClasses(['component', 'classes']) + ->componentHtmlAttributes(['component', 'html', 'attributes']); ``` ## FormAbstract From 5bfd229652080aed5400a1c2b6f6063a5b1a7c95 Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Mon, 7 Dec 2020 10:37:08 +0100 Subject: [PATCH 06/14] WIP --- docs/upgrade-guides/from-v2-to-v3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/upgrade-guides/from-v2-to-v3.md b/docs/upgrade-guides/from-v2-to-v3.md index e0b720f5..ca7f6fa9 100644 --- a/docs/upgrade-guides/from-v2-to-v3.md +++ b/docs/upgrade-guides/from-v2-to-v3.md @@ -8,7 +8,7 @@ Whereas Laravel 8 is now supported by this package, support for any version befo Support for any version before PHP 7.4 has also been dropped. -As so, you should upgrade your Laravel and PHP versions in order upgrade to V2. +As so, you should upgrade your Laravel and PHP versions in order upgrade to V3. ## See all changes From 669bb9c9878c356a953fd10f31e375da992b784d Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Mon, 7 Dec 2020 10:40:59 +0100 Subject: [PATCH 07/14] WIP --- docs/upgrade-guides/from-v4-to-v5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/upgrade-guides/from-v4-to-v5.md b/docs/upgrade-guides/from-v4-to-v5.md index aa0d53e6..aa65f4f6 100644 --- a/docs/upgrade-guides/from-v4-to-v5.md +++ b/docs/upgrade-guides/from-v4-to-v5.md @@ -31,7 +31,7 @@ For example, using `inputText()->name('name')->componentClasses(['merged', 'clas ## Components default config update -The `autocomplete="on"` HTML attribute has been added in the default configuration of the following components: +The `autocomplete="on"` HTML attribute has been added in the default configuration of the following components, in order to improve the default behavior (see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete): * Input email * Input password From 3f45811cd1dd6f9daddf3b5dd6dcff112c81c87d Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Mon, 7 Dec 2020 10:44:37 +0100 Subject: [PATCH 08/14] WIP --- src/Components/ComponentAbstract.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/ComponentAbstract.php b/src/Components/ComponentAbstract.php index aef4cdc0..bb7a644a 100644 --- a/src/Components/ComponentAbstract.php +++ b/src/Components/ComponentAbstract.php @@ -26,10 +26,10 @@ public function __construct() { $this->type = $this->setType(); $this->view = $this->setView(); - $this->componentClasses = $this->setComponentClasses(); $this->containerClasses = $this->setContainerClasses(); - $this->componentHtmlAttributes = $this->setComponentHtmlAttributes(); $this->containerHtmlAttributes = $this->setContainerHtmlAttributes(); + $this->componentClasses = $this->setComponentClasses(); + $this->componentHtmlAttributes = $this->setComponentHtmlAttributes(); } /** From 0b0f869d51abc63cc95a5c9ec50e22ba3b412994 Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Mon, 7 Dec 2020 11:02:53 +0100 Subject: [PATCH 09/14] WIP --- composer.json | 2 +- src/Components/ComponentAbstract.php | 100 +++++++++--------- .../Form/Abstracts/TemporalAbstract.php | 3 +- .../Form/Abstracts/UploadableAbstract.php | 6 +- .../Form/Traits/SelectValidityChecks.php | 6 +- .../Form/Abstracts/InputRadioTestAbstract.php | 3 +- 6 files changed, 64 insertions(+), 56 deletions(-) diff --git a/composer.json b/composer.json index de529853..d4d11375 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "require-dev": { "nunomaduro/larastan": "^0.6", "orchestra/testbench": "^5.0||^6.0", - "phpmd/phpmd": "^2.8", + "phpmd/phpmd": "^2.9", "squizlabs/php_codesniffer": "^3.5" }, "autoload": { diff --git a/src/Components/ComponentAbstract.php b/src/Components/ComponentAbstract.php index bb7a644a..98770ff4 100644 --- a/src/Components/ComponentAbstract.php +++ b/src/Components/ComponentAbstract.php @@ -58,6 +58,56 @@ public function render(array $extraData = []): string return trim($html); } + public function containerId(string $containerId): self + { + $this->containerId = $containerId; + + return $this; + } + + public function componentId(string $componentId): self + { + $this->componentId = $componentId; + + return $this; + } + + public function componentClasses(array $componentClasses, bool $mergeMode = false): self + { + $this->componentClasses = $mergeMode + ? array_merge($this->componentClasses, $componentClasses) + : $componentClasses; + + return $this; + } + + public function containerClasses(array $containerClasses, bool $mergeMode = false): self + { + $this->containerClasses = $mergeMode + ? array_merge($this->containerClasses, $containerClasses) + : $containerClasses; + + return $this; + } + + public function componentHtmlAttributes(array $componentHtmlAttributes, bool $mergeMode = false): self + { + $this->componentHtmlAttributes = $mergeMode + ? array_merge($this->componentHtmlAttributes, $componentHtmlAttributes) + : $componentHtmlAttributes; + + return $this; + } + + public function containerHtmlAttributes(array $containerHtmlAttributes, bool $mergeMode = false): self + { + $this->containerHtmlAttributes = $mergeMode + ? array_merge($this->containerHtmlAttributes, $containerHtmlAttributes) + : $containerHtmlAttributes; + + return $this; + } + abstract protected function checkValuesValidity(): void; protected function getView(): string @@ -117,56 +167,6 @@ protected function getComponentHtmlAttributes(): array abstract protected function setComponentHtmlAttributes(): array; - public function containerId(string $containerId): self - { - $this->containerId = $containerId; - - return $this; - } - - public function componentId(string $componentId): self - { - $this->componentId = $componentId; - - return $this; - } - - public function componentClasses(array $componentClasses, bool $mergeMode = false): self - { - $this->componentClasses = $mergeMode - ? array_merge($this->componentClasses, $componentClasses) - : $componentClasses; - - return $this; - } - - public function containerClasses(array $containerClasses, bool $mergeMode = false): self - { - $this->containerClasses = $mergeMode - ? array_merge($this->containerClasses, $containerClasses) - : $containerClasses; - - return $this; - } - - public function componentHtmlAttributes(array $componentHtmlAttributes, bool $mergeMode = false): self - { - $this->componentHtmlAttributes = $mergeMode - ? array_merge($this->componentHtmlAttributes, $componentHtmlAttributes) - : $componentHtmlAttributes; - - return $this; - } - - public function containerHtmlAttributes(array $containerHtmlAttributes, bool $mergeMode = false): self - { - $this->containerHtmlAttributes = $mergeMode - ? array_merge($this->containerHtmlAttributes, $containerHtmlAttributes) - : $containerHtmlAttributes; - - return $this; - } - protected function getType(): string { return $this->type; diff --git a/src/Components/Form/Abstracts/TemporalAbstract.php b/src/Components/Form/Abstracts/TemporalAbstract.php index 3a067e3d..6b80a60e 100644 --- a/src/Components/Form/Abstracts/TemporalAbstract.php +++ b/src/Components/Form/Abstracts/TemporalAbstract.php @@ -3,6 +3,7 @@ namespace Okipa\LaravelBootstrapComponents\Components\Form\Abstracts; use Carbon\Carbon; +use DateTime; use Okipa\LaravelBootstrapComponents\Components\Form\Traits\TemporalValidityChecks; abstract class TemporalAbstract extends FormAbstract @@ -31,7 +32,7 @@ protected function getValue(): ?string return null; } - return is_a($value, 'DateTime') + return $value instanceof DateTime ? $value->format($this->getFormat()) : Carbon::parse($value)->format($this->getFormat()); } diff --git a/src/Components/Form/Abstracts/UploadableAbstract.php b/src/Components/Form/Abstracts/UploadableAbstract.php index b7832eca..dc7970e0 100644 --- a/src/Components/Form/Abstracts/UploadableAbstract.php +++ b/src/Components/Form/Abstracts/UploadableAbstract.php @@ -37,10 +37,12 @@ public function showRemoveCheckbox(bool $showRemoveCheckbox = true, ?string $rem protected function getViewParams(): array { - return array_merge(parent::getViewParams(), [ + $parentViewParams = parent::getViewParams(); + + return array_merge($parentViewParams, [ 'uploadedFileHtml' => $this->getUploadedFileHtml(), 'showRemoveCheckbox' => $this->getShowRemoveCheckbox(), - 'removeCheckboxLabel' => $this->getRemoveCheckboxLabel(parent::getViewParams()['label']), + 'removeCheckboxLabel' => $this->getRemoveCheckboxLabel($parentViewParams['label']), 'removeCheckboxName' => $this->getShowRemoveCheckboxName(), ]); } diff --git a/src/Components/Form/Traits/SelectValidityChecks.php b/src/Components/Form/Traits/SelectValidityChecks.php index efc8e7b8..92edb957 100644 --- a/src/Components/Form/Traits/SelectValidityChecks.php +++ b/src/Components/Form/Traits/SelectValidityChecks.php @@ -57,7 +57,11 @@ protected function checkSelectedFieldToCompareExistenceInOption(array $option): protected function checkMultipleModeModelAttributeType(): void { - if ($this->getModel() && $this->getModel()->{$this->getName()} && ! is_array($this->getModel()->{$this->getName()})) { + if ( + $this->getModel() + && $this->getModel()->{$this->getName()} + && ! is_array($this->getModel()->{$this->getName()}) + ) { throw new InvalidArgumentException( get_class($this) . ' : The « ' . $this->getName() . ' » attribute from the given « ' . $this->getModel()->getMorphClass() diff --git a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php index 4d69a158..5fc303b8 100644 --- a/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php +++ b/tests/Unit/Form/Abstracts/InputRadioTestAbstract.php @@ -167,7 +167,8 @@ public function testSetLabel(): void { $html = $this->getComponent()->name('name')->label('custom-label')->toHtml(); self::assertStringContainsString( - '', + '', $html ); } From ba45a1783635dae31a930e0a5aee2cdd7a395d53 Mon Sep 17 00:00:00 2001 From: Artu1000 Date: Mon, 7 Dec 2020 11:52:04 +0100 Subject: [PATCH 10/14] WIP --- docs/upgrade-guides/from-v4-to-v5.md | 14 +- .../Media/Abstracts/ImageAbstract.php | 12 +- .../Buttons/Abstracts/ButtonTestAbstract.php | 62 ++------- .../Buttons/Abstracts/SubmitTestAbstract.php | 121 +++++++++++------- .../Media/Abstracts/ImageTestAbstract.php | 76 +++++++---- .../Media/Abstracts/MediaTestAbstract.php | 113 ++++++++++------ .../Media/Abstracts/VideoTestAbstract.php | 10 +- 7 files changed, 229 insertions(+), 179 deletions(-) diff --git a/docs/upgrade-guides/from-v4-to-v5.md b/docs/upgrade-guides/from-v4-to-v5.md index aa65f4f6..0ae915c8 100644 --- a/docs/upgrade-guides/from-v4-to-v5.md +++ b/docs/upgrade-guides/from-v4-to-v5.md @@ -22,12 +22,14 @@ The following methods have gained the ability to merge given HTML classes or HTM To use this new behaviour, you'll just have to set the second `$mergeMode` boolean attribute to `true`. -* `componentClasses` -* `containerClasses` -* `componentHtmlAttributes` -* `containerHtmlAttributes` - -For example, using `inputText()->name('name')->componentClasses(['merged', 'classes'], true)` will merge the `merged classes` classes to the ones defined by default on the input text component. +* All components: `componentClasses` +* All components: `containerClasses` +* All components: `componentHtmlAttributes` +* All components: `containerHtmlAttributes` +* Image component: `linkClasses` +* Image component: `linkHtmlAttributes` + +For example, using `inputText()->name('name')->componentClasses(['merged', 'classes'], true)` will append the `merged classes` classes to the ones defined by default on the input text component. ## Components default config update diff --git a/src/Components/Media/Abstracts/ImageAbstract.php b/src/Components/Media/Abstracts/ImageAbstract.php index 834ffb96..da73779e 100644 --- a/src/Components/Media/Abstracts/ImageAbstract.php +++ b/src/Components/Media/Abstracts/ImageAbstract.php @@ -69,16 +69,20 @@ public function linkId(string $linkId): self return $this; } - public function linkClasses(array $linkClasses): self + public function linkClasses(array $linkClasses, bool $mergeMode = false): self { - $this->linkClasses = $linkClasses; + $this->linkClasses = $mergeMode + ? array_merge($this->linkClasses, $linkClasses) + : $linkClasses; return $this; } - public function linkHtmlAttributes(array $linkHtmlAttributes): self + public function linkHtmlAttributes(array $linkHtmlAttributes, bool $mergeMode = false): self { - $this->linkHtmlAttributes = $linkHtmlAttributes; + $this->linkHtmlAttributes = $mergeMode + ? array_merge($this->linkHtmlAttributes, $linkHtmlAttributes) + : $linkHtmlAttributes; return $this; } diff --git a/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php b/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php index e2c63f9c..4898bc0e 100644 --- a/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php +++ b/tests/Unit/Buttons/Abstracts/ButtonTestAbstract.php @@ -8,13 +8,13 @@ abstract class ButtonTestAbstract extends SubmitTestAbstract { use RoutesFaker; - public function testType() + public function testType(): void { $html = $this->getComponent()->toHtml(); self::assertStringContainsString('set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -24,7 +24,7 @@ public function setCustomUrl() self::assertStringContainsString('href="default-url"', $html); } - public function testSetUrlReplacesDefault() + public function testSetUrlReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -36,7 +36,7 @@ public function testSetUrlReplacesDefault() self::assertStringNotContainsString('href="default-url"', $html); } - public function testSetRoute() + public function testSetRoute(): void { $this->setRoutes(); $customRoute = 'users.index'; @@ -44,7 +44,7 @@ public function testSetRoute() self::assertStringContainsString('href="' . route($customRoute) . '"', $html); } - public function testSetCustomLabel() + public function testSetCustomLabel(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -55,7 +55,7 @@ public function testSetCustomLabel() self::assertStringContainsString('default-label', $html); } - public function testSetLabelReplacesDefault() + public function testSetLabelReplacesDefault(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -69,14 +69,14 @@ public function testSetLabelReplacesDefault() self::assertStringNotContainsString('default-label', $html); } - public function testNoLabel() + public function testNoLabel(): void { $html = $this->getComponent()->label(null)->toHtml(); self::assertStringNotContainsString('title="', $html); self::assertStringNotContainsString('', $html); } - public function testHideLabel() + public function testHideLabel(): void { config()->set( 'bootstrap-components.components.' . $this->getComponentKey(), @@ -87,58 +87,16 @@ public function testHideLabel() self::assertStringNotContainsString('default-label', $html); } - public function testDefaultComponentId() + public function testDefaultComponentId(): void { $html = $this->getComponent()->toHtml(); self::assertStringNotContainsString('set( - 'bootstrap-components.components.' . $this->getComponentKey(), - get_class($this->getCustomComponent()) - ); - $html = $this->getComponent()->toHtml(); - self::assertStringContainsString('class="component-container default container classes"', $html); - } - - public function testSetContainerClassesReplacesDefault() - { - config()->set( - 'bootstrap-components.components.' . $this->getComponentKey(), - get_class($this->getCustomComponent()) - ); - $html = $this->getComponent()->containerClasses(['custom', 'container', 'classes'])->toHtml(); - self::assertStringContainsString('class="component-container custom container classes"', $html); - self::assertStringNotContainsString('class="component-container default container classes"', $html); - } - - public function testSetCustomComponentClasses() - { - config()->set( - 'bootstrap-components.components.' . $this->getComponentKey(), - get_class($this->getCustomComponent()) - ); - $html = $this->getComponent()->toHtml(); - self::assertStringContainsString('class="component btn default component classes"', $html); - } - - public function testSetComponentClassesReplacesDefault() - { - config()->set( - 'bootstrap-components.components.' . $this->getComponentKey(), - get_class($this->getCustomComponent()) - ); - $html = $this->getComponent()->componentClasses(['custom', 'component', 'classes'])->toHtml(); - self::assertStringContainsString('class="component btn custom component classes"', $html); - self::assertStringNotContainsString('class="component btn default component classes"', $html); - } } diff --git a/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php b/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php index f8cc5655..345913d0 100644 --- a/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php +++ b/tests/Unit/Buttons/Abstracts/SubmitTestAbstract.php @@ -18,28 +18,28 @@ abstract protected function getComponentType(): string; abstract protected function getCustomComponent(): ComponentAbstract; - public function testHelper() + public function testHelper(): void { self::assertInstanceOf(get_class($this->getComponent()), $this->getHelper()); } - public function testFacade() + public function testFacade(): void { self::assertInstanceOf(get_class($this->getComponent()), $this->getFacade()); } - public function testInstance() + public function testInstance(): void { self::assertInstanceOf(SubmitAbstract::class, $this->getComponent()); } - public function testType() + public function testType(): void { $html = $this->getComponent()->toHtml(); self::assertStringContainsString('