diff --git a/src/Illuminate/View/Compilers/ComponentTagCompiler.php b/src/Illuminate/View/Compilers/ComponentTagCompiler.php
index 8b360762127e..9c3d6adbec99 100644
--- a/src/Illuminate/View/Compilers/ComponentTagCompiler.php
+++ b/src/Illuminate/View/Compilers/ComponentTagCompiler.php
@@ -259,8 +259,8 @@ protected function componentString(string $component, array $attributes)
}
return "##BEGIN-COMPONENT-CLASS##@component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).'])
-getConstructor()): ?>
-except(collect($constructor->getParameters())->map->getName()->all()); ?>
+
+except(\\'.$class.'::ignoredParameterNames()); ?>
withAttributes(['.$this->attributesToString($attributes->all(), $escapeAttributes = $class !== DynamicComponent::class).']); ?>';
}
diff --git a/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php b/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php
index 88617186fb20..56d1399e85dc 100644
--- a/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php
+++ b/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php
@@ -68,7 +68,7 @@ public static function compileClassComponentOpening(string $component, string $a
return implode("\n", [
'',
'',
- 'getIterator() : [])); ?>',
+ 'all() : [])); ?>',
'withName('.$alias.'); ?>',
'shouldRender()): ?>',
'startComponent($component->resolveView(), $component->data()); ?>',
@@ -157,19 +157,35 @@ protected function compileEndComponentFirst()
*/
protected function compileProps($expression)
{
- return "
-onlyProps{$expression} as \$__key => \$__value) {
- \$\$__key = \$\$__key ?? \$__value;
-} ?>
-exceptProps{$expression}; ?>
- \$__value) {
+ return "all() as \$__key => \$__value) {
+ if (in_array(\$__key, \$__propNames)) {
+ \$\$__key = \$\$__key ?? \$__value;
+ } else {
+ \$__newAttributes[\$__key] = \$__value;
+ }
+}
+
+\$attributes = new \Illuminate\View\ComponentAttributeBag(\$__newAttributes);
+
+unset(\$__propNames);
+unset(\$__newAttributes);
+
+foreach (array_filter({$expression}, 'is_string', ARRAY_FILTER_USE_KEY) as \$__key => \$__value) {
\$\$__key = \$\$__key ?? \$__value;
-} ?>
-
- \$__value) {
+}
+
+\$__defined_vars = get_defined_vars();
+
+foreach (\$attributes->all() as \$__key => \$__value) {
if (array_key_exists(\$__key, \$__defined_vars)) unset(\$\$__key);
-} ?>
-";
+}
+
+unset(\$__defined_vars); ?>";
}
/**
diff --git a/src/Illuminate/View/Component.php b/src/Illuminate/View/Component.php
index 6768fdcbb1c2..fa21f08ab5ff 100644
--- a/src/Illuminate/View/Component.php
+++ b/src/Illuminate/View/Component.php
@@ -75,6 +75,13 @@ abstract class Component
*/
protected static $constructorParametersCache = [];
+ /**
+ * The cache of ignored parameter names.
+ *
+ * @var array
+ */
+ protected static $ignoredParameterNames = [];
+
/**
* Get the view / view contents that represent the component.
*
@@ -417,6 +424,30 @@ protected function factory()
return static::$factory;
}
+ /**
+ * Get the cached set of anonymous component constructor parameter names to exclude.
+ *
+ * @return array
+ */
+ public static function ignoredParameterNames()
+ {
+ if (! isset(static::$ignoredParameterNames[static::class])) {
+ $constructor = (new ReflectionClass(
+ static::class
+ ))->getConstructor();
+
+ if (! $constructor) {
+ return static::$ignoredParameterNames[static::class] = [];
+ }
+
+ static::$ignoredParameterNames[static::class] = collect($constructor->getParameters())
+ ->map->getName()
+ ->all();
+ }
+
+ return static::$ignoredParameterNames[static::class];
+ }
+
/**
* Flush the component's cached state.
*
diff --git a/src/Illuminate/View/ComponentAttributeBag.php b/src/Illuminate/View/ComponentAttributeBag.php
index 368391c038ff..868a97f5aac3 100644
--- a/src/Illuminate/View/ComponentAttributeBag.php
+++ b/src/Illuminate/View/ComponentAttributeBag.php
@@ -37,6 +37,16 @@ public function __construct(array $attributes = [])
$this->attributes = $attributes;
}
+ /**
+ * Get all of the attribute values.
+ *
+ * @return array
+ */
+ public function all()
+ {
+ return $this->attributes;
+ }
+
/**
* Get the first attribute's value.
*
@@ -207,7 +217,7 @@ public function thatStartWith($needles)
*/
public function onlyProps($keys)
{
- return $this->only($this->extractPropNames($keys));
+ return $this->only(static::extractPropNames($keys));
}
/**
@@ -218,27 +228,7 @@ public function onlyProps($keys)
*/
public function exceptProps($keys)
{
- return $this->except($this->extractPropNames($keys));
- }
-
- /**
- * Extract prop names from given keys.
- *
- * @param mixed|array $keys
- * @return array
- */
- protected function extractPropNames($keys)
- {
- $props = [];
-
- foreach ($keys as $key => $defaultValue) {
- $key = is_numeric($key) ? $defaultValue : $key;
-
- $props[] = $key;
- $props[] = Str::kebab($key);
- }
-
- return $props;
+ return $this->except(static::extractPropNames($keys));
}
/**
@@ -401,6 +391,26 @@ public function setAttributes(array $attributes)
$this->attributes = $attributes;
}
+ /**
+ * Extract "prop" names from given keys.
+ *
+ * @param array $keys
+ * @return array
+ */
+ public static function extractPropNames(array $keys)
+ {
+ $props = [];
+
+ foreach ($keys as $key => $default) {
+ $key = is_numeric($key) ? $default : $key;
+
+ $props[] = $key;
+ $props[] = Str::kebab($key);
+ }
+
+ return $props;
+ }
+
/**
* Get content as a string of HTML.
*
diff --git a/src/Illuminate/View/Concerns/ManagesEvents.php b/src/Illuminate/View/Concerns/ManagesEvents.php
index d6cd9d81b113..7ad3c689d00e 100644
--- a/src/Illuminate/View/Concerns/ManagesEvents.php
+++ b/src/Illuminate/View/Concerns/ManagesEvents.php
@@ -174,7 +174,9 @@ protected function addEventListener($name, $callback)
*/
public function callComposer(ViewContract $view)
{
- $this->events->dispatch('composing: '.$view->name(), [$view]);
+ if ($this->events->hasListeners($event = 'composing: '.$view->name())) {
+ $this->events->dispatch($event, [$view]);
+ }
}
/**
@@ -185,6 +187,8 @@ public function callComposer(ViewContract $view)
*/
public function callCreator(ViewContract $view)
{
- $this->events->dispatch('creating: '.$view->name(), [$view]);
+ if ($this->events->hasListeners($event = 'creating: '.$view->name())) {
+ $this->events->dispatch($event, [$view]);
+ }
}
}
diff --git a/tests/View/Blade/BladeComponentTagCompilerTest.php b/tests/View/Blade/BladeComponentTagCompilerTest.php
index 5143ae503c72..38a4a037b21a 100644
--- a/tests/View/Blade/BladeComponentTagCompilerTest.php
+++ b/tests/View/Blade/BladeComponentTagCompilerTest.php
@@ -103,13 +103,13 @@ public function testBasicComponentParsing()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('
');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes(['type' => 'foo','limit' => '5','@click' => 'foo','wire:click' => 'changePlan(\''.e(\$plan).'\')','required' => true,'x-intersect.margin.-50%.0px' => 'visibleSection = \'profile\'']); ?>\n".
"@endComponentClass##END-COMPONENT-CLASS####BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##
', trim($result));
@@ -121,8 +121,8 @@ public function testBasicComponentWithEmptyAttributesParsing()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('
');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes(['type' => '','limit' => '','@click' => '','required' => true]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##
', trim($result));
@@ -134,8 +134,8 @@ public function testDataCamelCasing()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => '1'])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -146,8 +146,8 @@ public function testColonData()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => 1])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -158,8 +158,8 @@ public function testColonDataShortSyntax()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => \$userId])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -170,8 +170,8 @@ public function testColonDataWithStaticClassProperty()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => User::\$id])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -182,16 +182,16 @@ public function testColonDataWithStaticClassPropertyAndMultipleAttributes()
$result = $this->compiler(['input' => TestInputComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestInputComponent', 'input', ['label' => Input::\$label,'name' => \$name,'value' => 'Joe'])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestInputComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
$result = $this->compiler(['input' => TestInputComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestInputComponent', 'input', ['value' => 'Joe','name' => \$name,'label' => Input::\$label])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestInputComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -202,8 +202,8 @@ public function testSelfClosingComponentWithColonDataShortSyntax()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => \$userId])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -215,8 +215,8 @@ public function testSelfClosingComponentWithColonDataAndStaticClassPropertyShort
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => User::\$id])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -228,8 +228,8 @@ public function testSelfClosingComponentWithColonDataMultipleAttributesAndStatic
$result = $this->compiler(['input' => TestInputComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestInputComponent', 'input', ['label' => Input::\$label,'value' => 'Joe','name' => \$name])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestInputComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -237,8 +237,8 @@ public function testSelfClosingComponentWithColonDataMultipleAttributesAndStatic
$result = $this->compiler(['input' => TestInputComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestInputComponent', 'input', ['name' => \$name,'label' => Input::\$label,'value' => 'Joe'])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestInputComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -250,8 +250,8 @@ public function testEscapedColonAttribute()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => 1])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([':title' => 'user.name']); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -262,8 +262,8 @@ public function testColonAttributesIsEscapedIfStrings()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes(['src' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('foo')]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -274,8 +274,8 @@ public function testClassDirective()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('true])>');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes(['class' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\Illuminate\Support\Arr::toCssClasses(['bar'=>true]))]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -286,8 +286,8 @@ public function testStyleDirective()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('true])>');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes(['style' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\Illuminate\Support\Arr::toCssStyles(['bar'=>true]))]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -298,8 +298,8 @@ public function testColonNestedComponentParsing()
$result = $this->compiler(['foo:alert' => TestAlertComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -310,8 +310,8 @@ public function testColonStartingNestedComponentParsing()
$result = $this->compiler(['foo:alert' => TestAlertComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -322,8 +322,8 @@ public function testSelfClosingComponentsCanBeCompiled()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('
');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##
', trim($result));
@@ -364,8 +364,8 @@ public function testComponentsCanBeCompiledWithHyphenAttributes()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes(['class' => 'bar','wire:model' => 'foo','x-on:click' => 'bar','@click' => 'baz']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -377,8 +377,8 @@ public function testSelfClosingComponentsCanBeCompiledWithDataAndAttributes()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo'])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes(['class' => 'bar','wire:model' => 'foo']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -391,8 +391,8 @@ public function testComponentCanReceiveAttributeBag()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes),'wire:model' => 'foo']); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}
@@ -404,8 +404,8 @@ public function testSelfClosingComponentCanReceiveAttributeBag()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('merge([\'class\' => \'test\']) }} wire:model="foo" />
');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo'])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes->merge(['class' => 'test'])),'wire:model' => 'foo']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##
', trim($result));
@@ -417,8 +417,8 @@ public function testComponentsCanHaveAttachedWord()
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('Words');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestProfileComponent::ignoredParameterNames()); ?>
withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##Words", trim($result));
}
@@ -429,8 +429,8 @@ public function testSelfClosingComponentsCanHaveAttachedWord()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('Words');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##Words', trim($result));
@@ -442,8 +442,8 @@ public function testSelfClosingComponentsCanBeCompiledWithBoundData()
$result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => \$title])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes(['class' => 'bar']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -456,8 +456,8 @@ public function testPairedComponentTags()
');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', [])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\Tests\View\Blade\TestAlertComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>
@endComponentClass##END-COMPONENT-CLASS##", trim($result));
@@ -475,8 +475,8 @@ public function testClasslessComponents()
$result = $this->compiler()->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -494,8 +494,8 @@ public function testClasslessComponentsWithIndexView()
$result = $this->compiler()->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component.index','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -513,8 +513,8 @@ public function testPackagesClasslessComponents()
$result = $this->compiler()->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'package::anonymous-component', ['view' => 'package::components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -547,8 +547,8 @@ public function testClasslessComponentsWithAnonymousComponentNamespace()
$result = $compiler->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'frontend::anonymous-component', ['view' => 'public.frontend.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -581,8 +581,8 @@ public function testClasslessComponentsWithAnonymousComponentNamespaceWithIndexV
$result = $compiler->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'admin.auth::anonymous-component', ['view' => 'admin.auth.components.anonymous-component.index','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -614,8 +614,8 @@ public function testClasslessComponentsWithAnonymousComponentPath()
$result = $compiler->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'panel', ['view' => '".md5('test-directory')."::panel.index','data' => []])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
@@ -647,8 +647,8 @@ public function testClasslessIndexComponentsWithAnonymousComponentPath()
$result = $compiler->compileTags('');
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'panel', ['view' => '".md5('test-directory')."::panel','data' => []])
-getConstructor()): ?>
-except(collect(\$constructor->getParameters())->map->getName()->all()); ?>
+
+except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
withAttributes([]); ?>\n".
'@endComponentClass##END-COMPONENT-CLASS##', trim($result));
diff --git a/tests/View/Blade/BladeComponentsTest.php b/tests/View/Blade/BladeComponentsTest.php
index 2615edf91452..64231b4fd098 100644
--- a/tests/View/Blade/BladeComponentsTest.php
+++ b/tests/View/Blade/BladeComponentsTest.php
@@ -18,7 +18,7 @@ public function testClassComponentsAreCompiled()
{
$this->assertSame('
- "bar"] + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? (array) $attributes->getIterator() : [])); ?>
+ "bar"] + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? $attributes->all() : [])); ?>
withName(\'test\'); ?>
shouldRender()): ?>
startComponent($component->resolveView(), $component->data()); ?>', $this->compiler->compileString('@component(\'Illuminate\Tests\View\Blade\ComponentStub::class\', \'test\', ["foo" => "bar"])'));
diff --git a/tests/View/Blade/BladePropsTest.php b/tests/View/Blade/BladePropsTest.php
index a1dfa1cc6653..e9d258e2265f 100644
--- a/tests/View/Blade/BladePropsTest.php
+++ b/tests/View/Blade/BladePropsTest.php
@@ -8,19 +8,35 @@ class BladePropsTest extends AbstractBladeTestCase
{
public function testPropsAreCompiled()
{
- $this->assertSame('
-onlyProps([\'one\' => true, \'two\' => \'string\']) as $__key => $__value) {
- $$__key = $$__key ?? $__value;
-} ?>
-exceptProps([\'one\' => true, \'two\' => \'string\']); ?>
- true, \'two\' => \'string\']), \'is_string\', ARRAY_FILTER_USE_KEY) as $__key => $__value) {
+ $this->assertSame(' true, \'two\' => \'string\']));
+
+foreach ($attributes->all() as $__key => $__value) {
+ if (in_array($__key, $__propNames)) {
+ $$__key = $$__key ?? $__value;
+ } else {
+ $__newAttributes[$__key] = $__value;
+ }
+}
+
+$attributes = new \Illuminate\View\ComponentAttributeBag($__newAttributes);
+
+unset($__propNames);
+unset($__newAttributes);
+
+foreach (array_filter(([\'one\' => true, \'two\' => \'string\']), \'is_string\', ARRAY_FILTER_USE_KEY) as $__key => $__value) {
$$__key = $$__key ?? $__value;
-} ?>
-
- $__value) {
+}
+
+$__defined_vars = get_defined_vars();
+
+foreach ($attributes->all() as $__key => $__value) {
if (array_key_exists($__key, $__defined_vars)) unset($$__key);
-} ?>
-', $this->compiler->compileString('@props([\'one\' => true, \'two\' => \'string\'])'));
+}
+
+unset($__defined_vars); ?>', $this->compiler->compileString('@props([\'one\' => true, \'two\' => \'string\'])'));
}
public function testPropsAreExtractedFromParentAttributesCorrectly()
diff --git a/tests/View/ViewFactoryTest.php b/tests/View/ViewFactoryTest.php
index 85ea0039dfc6..5465c78af0b2 100755
--- a/tests/View/ViewFactoryTest.php
+++ b/tests/View/ViewFactoryTest.php
@@ -148,7 +148,7 @@ public function testEnvironmentAddsExtensionWithCustomResolver()
$factory->getEngineResolver()->shouldReceive('register')->once()->with('bar', $resolver);
$factory->getFinder()->shouldReceive('find')->once()->with('view')->andReturn('path.foo');
$factory->getEngineResolver()->shouldReceive('resolve')->once()->with('bar')->andReturn($engine = m::mock(Engine::class));
- $factory->getDispatcher()->shouldReceive('dispatch');
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false);
$factory->addExtension('foo', 'bar', $resolver);
@@ -185,11 +185,14 @@ public function testPrependedExtensionOverridesExistingExtensions()
public function testCallCreatorsDoesDispatchEventsWhenIsNecessary()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('creating: name', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('creating: name', m::type('array'))
@@ -206,11 +209,14 @@ public function testCallCreatorsDoesDispatchEventsWhenIsNecessary()
public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingNamespacedWildcards()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('creating: namespaced::*', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('creating: namespaced::my-package-view', m::type('array'))
@@ -227,6 +233,7 @@ public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingNamespaced
public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingNamespacedNestedWildcards()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('creating: namespaced::*', m::type(Closure::class))
@@ -237,6 +244,8 @@ public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingNamespaced
->with('creating: welcome', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('creating: namespaced::my-package-view', m::type('array'))
@@ -253,11 +262,14 @@ public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingNamespaced
public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingWildcards()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('creating: *', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('creating: name', m::type('array'))
@@ -274,11 +286,14 @@ public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingWildcards(
public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingNormalizedNames()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('creating: components.button', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('creating: components/button', m::type('array'))
@@ -297,11 +312,14 @@ public function testCallCreatorsDoesDispatchEventsWhenIsNecessaryUsingNormalized
public function testCallComposerDoesDispatchEventsWhenIsNecessary()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('composing: name', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('composing: name', m::type('array'))
@@ -318,11 +336,14 @@ public function testCallComposerDoesDispatchEventsWhenIsNecessary()
public function testCallComposerDoesDispatchEventsWhenIsNecessaryAndUsingTheArrayFormat()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('composing: name', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('composing: name', m::type('array'))
@@ -339,11 +360,14 @@ public function testCallComposerDoesDispatchEventsWhenIsNecessaryAndUsingTheArra
public function testCallComposersDoesDispatchEventsWhenIsNecessaryUsingNamespacedWildcards()
{
$factory = $this->getFactory();
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('composing: namespaced::*', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('composing: namespaced::my-package-view', m::type('array'))
@@ -370,6 +394,8 @@ public function testCallComposersDoesDispatchEventsWhenIsNecessaryUsingNamespace
->with('composing: welcome', m::type(Closure::class))
->once();
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('dispatch')
->with('composing: namespaced::my-package-view', m::type('array'))
@@ -386,6 +412,9 @@ public function testCallComposersDoesDispatchEventsWhenIsNecessaryUsingNamespace
public function testCallComposersDoesDispatchEventsWhenIsNecessaryUsingWildcards()
{
$factory = $this->getFactory();
+
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('composing: *', m::type(Closure::class))
@@ -407,6 +436,9 @@ public function testCallComposersDoesDispatchEventsWhenIsNecessaryUsingWildcards
public function testCallComposersDoesDispatchEventsWhenIsNecessaryUsingNormalizedNames()
{
$factory = $this->getFactory();
+
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
+
$factory->getDispatcher()
->shouldReceive('listen')
->with('composing: components.button', m::type(Closure::class))
@@ -496,6 +528,7 @@ public function testCallComposerCallsProperEvent()
$factory->composer('name', fn () => true);
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(true);
$factory->getDispatcher()->shouldReceive('dispatch')->once()->with('composing: name', [$view]);
$factory->callComposer($view);
@@ -612,7 +645,7 @@ public function testComponentHandling()
$factory = $this->getFactory();
$factory->getFinder()->shouldReceive('find')->andReturn(__DIR__.'/fixtures/component.php');
$factory->getEngineResolver()->shouldReceive('resolve')->andReturn(new PhpEngine(new Filesystem));
- $factory->getDispatcher()->shouldReceive('dispatch');
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false);
$factory->startComponent('component', ['name' => 'Taylor']);
$factory->slot('title');
$factory->slot('website', 'laravel.com', []);
@@ -628,7 +661,7 @@ public function testComponentHandlingUsingViewObject()
$factory = $this->getFactory();
$factory->getFinder()->shouldReceive('find')->andReturn(__DIR__.'/fixtures/component.php');
$factory->getEngineResolver()->shouldReceive('resolve')->andReturn(new PhpEngine(new Filesystem));
- $factory->getDispatcher()->shouldReceive('dispatch');
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false);
$factory->startComponent($factory->make('component'), ['name' => 'Taylor']);
$factory->slot('title');
$factory->slot('website', 'laravel.com', []);
@@ -644,7 +677,7 @@ public function testComponentHandlingUsingClosure()
$factory = $this->getFactory();
$factory->getFinder()->shouldReceive('find')->andReturn(__DIR__.'/fixtures/component.php');
$factory->getEngineResolver()->shouldReceive('resolve')->andReturn(new PhpEngine(new Filesystem));
- $factory->getDispatcher()->shouldReceive('dispatch');
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false);
$factory->startComponent(function ($data) use ($factory) {
$this->assertArrayHasKey('name', $data);
$this->assertSame($data['name'], 'Taylor');
@@ -810,7 +843,7 @@ public function testMakeWithSlashAndDot()
$factory = $this->getFactory();
$factory->getFinder()->shouldReceive('find')->twice()->with('foo.bar')->andReturn('path.php');
$factory->getEngineResolver()->shouldReceive('resolve')->twice()->with('php')->andReturn(m::mock(Engine::class));
- $factory->getDispatcher()->shouldReceive('dispatch');
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false);
$factory->make('foo/bar');
$factory->make('foo.bar');
}
@@ -820,7 +853,7 @@ public function testNamespacedViewNamesAreNormalizedProperly()
$factory = $this->getFactory();
$factory->getFinder()->shouldReceive('find')->twice()->with('vendor/package::foo.bar')->andReturn('path.php');
$factory->getEngineResolver()->shouldReceive('resolve')->twice()->with('php')->andReturn(m::mock(Engine::class));
- $factory->getDispatcher()->shouldReceive('dispatch');
+ $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false);
$factory->make('vendor/package::foo/bar');
$factory->make('vendor/package::foo.bar');
}
@@ -848,7 +881,7 @@ public function testExceptionsInSectionsAreThrown()
$factory->getEngineResolver()->shouldReceive('resolve')->twice()->andReturn($engine);
$factory->getFinder()->shouldReceive('find')->once()->with('layout')->andReturn(__DIR__.'/fixtures/section-exception-layout.php');
$factory->getFinder()->shouldReceive('find')->once()->with('view')->andReturn(__DIR__.'/fixtures/section-exception.php');
- $factory->getDispatcher()->shouldReceive('dispatch')->times(4); // 2 "creating" + 2 "composing"...
+ $factory->getDispatcher()->shouldReceive('hasListeners')->times(4); // 2 "creating" + 2 "composing"...
$factory->make('view')->render();
}