Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[11.x] Additonal Blade Loop Improvements #51217

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/Illuminate/Events/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ class Dispatcher implements DispatcherContract
*/
protected $transactionManagerResolver;

/**
* The cache of events that have listeners.
*
* @var array
*/
protected $listenerCache = [];

/**
* Create a new event dispatcher instance.
*
Expand Down Expand Up @@ -107,6 +114,8 @@ public function listen($events, $listener = null)
$this->listeners[$event][] = $listener;
}
}

$this->listenerCache = [];
}

/**
Expand All @@ -131,9 +140,15 @@ protected function setupWildcardListen($event, $listener)
*/
public function hasListeners($eventName)
{
return isset($this->listeners[$eventName]) ||
if (isset($this->listenerCache[$eventName])) {
return $this->listenerCache[$eventName];
}

$this->listenerCache[$eventName] = isset($this->listeners[$eventName]) ||
isset($this->wildcards[$eventName]) ||
$this->hasWildcardListeners($eventName);

return $this->listenerCache[$eventName];
}

/**
Expand Down Expand Up @@ -703,6 +718,8 @@ public function forget($event)
unset($this->wildcardsCache[$key]);
}
}

$this->listenerCache = [];
}

/**
Expand Down
26 changes: 25 additions & 1 deletion src/Illuminate/View/AnonymousComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ class AnonymousComponent extends Component
* @param array $data
* @return void
*/
public function __construct($view, $data)
public function __construct($view, $data, Factory $factory)
{
$this->view = $view;
$this->data = $data;
self::$factory = $factory;
}

/**
Expand All @@ -41,6 +42,29 @@ public function render()
return $this->view;
}

/**
* Resolve the component instance with the given data.
*
* @param array $data
* @return static
*/
public static function resolve($data)
{
return new static($data['view'], $data['data'], $data['factory']);
}

/**
* Resolve the Blade view or view file that should be used when rendering the component.
*
* @return string
*/
public function resolveView()
{
$view = $this->render();

return $this->extractBladeViewFromString($view);
}

/**
* Get the data that should be supplied to the view.
*
Expand Down
9 changes: 8 additions & 1 deletion src/Illuminate/View/Compilers/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ abstract class Compiler
*/
protected $compiledExtension = 'php';

/**
* The cache of compiled paths.
*
* @var array
*/
protected $compiledPathCache = [];

/**
* Create a new compiler instance.
*
Expand Down Expand Up @@ -82,7 +89,7 @@ public function __construct(
*/
public function getCompiledPath($path)
{
return $this->cachePath.'/'.hash('xxh128', 'v2'.Str::after($path, $this->basePath)).'.'.$this->compiledExtension;
return $this->compiledPathCache[$path] ??= $this->cachePath.'/'.hash('xxh128', 'v2'.Str::after($path, $this->basePath)).'.'.$this->compiledExtension;
}

/**
Expand Down
15 changes: 12 additions & 3 deletions src/Illuminate/View/Compilers/ComponentTagCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ protected function componentString(string $component, array $attributes)
$parameters = [
'view' => $view,
'data' => '['.$this->attributesToString($data->all(), $escapeBound = false).']',
'factory' => '$__env',
];

$class = AnonymousComponent::class;
Expand Down Expand Up @@ -776,9 +777,17 @@ protected function attributesToString(array $attributes, $escapeBound = true)
{
return collect($attributes)
->map(function (string $value, string $attribute) use ($escapeBound) {
return $escapeBound && isset($this->boundAttributes[$attribute]) && $value !== 'true' && ! is_numeric($value)
? "'{$attribute}' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute({$value})"
: "'{$attribute}' => {$value}";
$shouldSanitize = $escapeBound && isset($this->boundAttributes[$attribute]) && $value !== 'true' && ! is_numeric($value);

if ($shouldSanitize) {
$value = \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute($value);

if (is_string($value)) {
return "'{$attribute}' => '{$value}'";
}
}

return "'{$attribute}' => {$value}";
})
->implode(',');
}
Expand Down
6 changes: 4 additions & 2 deletions src/Illuminate/View/Concerns/ManagesComponents.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ public function startComponent($view, array $data = [])
if (ob_start()) {
$this->componentStack[] = $view;

$this->componentData[$this->currentComponent()] = $data;
$currentComponent = $this->currentComponent();

$this->slots[$this->currentComponent()] = [];
$this->componentData[$currentComponent] = $data;

$this->slots[$currentComponent] = [];
}
}

Expand Down
45 changes: 40 additions & 5 deletions src/Illuminate/View/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

namespace Illuminate\View;

use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\View\Factory as FactoryContract;
use Illuminate\Support\Arr;
use InvalidArgumentException;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\View\Engines\EngineResolver;
use InvalidArgumentException;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\View\Factory as FactoryContract;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the order of import is alphabetical ascending and not by length.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks crynobone. I'll adjust it when I go through the failing tests.


class Factory implements FactoryContract
{
Expand Down Expand Up @@ -104,6 +105,20 @@ class Factory implements FactoryContract
*/
protected $normalizedNameCache = [];

/**
* Flag to determine if renderable shared data cache is set.
*
* @var boolean
*/
protected $renderableSharedCacheIsSet = false;

/**
* The cache of shared data with objects cast to strings.
*
* @var array
*/
protected $renderableSharedCache = [];

/**
* Create a new view factory instance.
*
Expand Down Expand Up @@ -358,6 +373,8 @@ public function share($key, $value = null)
$this->shared[$key] = $value;
}

$this->renderableSharedCacheIsSet = false;

return $value;
}

Expand Down Expand Up @@ -631,4 +648,22 @@ public function getShared()
{
return $this->shared;
}

public function getRenderableShared()
{
if ($this->renderableSharedCacheIsSet) {
return $this->renderableSharedCache;
}

$this->renderableSharedCache = $this->getShared();
foreach ($this->renderableSharedCache as $key => $value) {
if ($value instanceof Renderable) {
$this->renderableSharedCache[$key] = $value->render();
}
}

$this->renderableSharedCacheIsSet = true;

return $this->renderableSharedCache;
}
}
6 changes: 3 additions & 3 deletions src/Illuminate/View/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,15 +215,15 @@ protected function getContents()
*/
public function gatherData()
{
$data = array_merge($this->factory->getShared(), $this->data);
$data = $this->data;

foreach ($data as $key => $value) {
if ($value instanceof Renderable) {
$data[$key] = $value->render();
}
}

return $data;
return array_merge($this->factory->getRenderableShared(), $data);
}

/**
Expand Down Expand Up @@ -305,7 +305,7 @@ protected function formatErrors($provider)
*/
public function name()
{
return $this->getName();
return $this->view;
}

/**
Expand Down
14 changes: 7 additions & 7 deletions tests/View/Blade/BladeComponentTagCompilerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ public function testClasslessComponents()

$result = $this->compiler()->compileTags('<x-anonymous-component :name="\'Taylor\'" :age="31" wire:model="foo" />');

$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo'],'factory' => \$__env])
<?php if (isset(\$attributes) && \$attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php \$attributes = \$attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
Expand All @@ -493,7 +493,7 @@ public function testClasslessComponentsWithIndexView()

$result = $this->compiler()->compileTags('<x-anonymous-component :name="\'Taylor\'" :age="31" wire:model="foo" />');

$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component.index','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']])
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component.index','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo'],'factory' => \$__env])
<?php if (isset(\$attributes) && \$attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php \$attributes = \$attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
Expand All @@ -512,7 +512,7 @@ public function testPackagesClasslessComponents()

$result = $this->compiler()->compileTags('<x-package::anonymous-component :name="\'Taylor\'" :age="31" wire:model="foo" />');

$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']])
$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'],'factory' => \$__env])
<?php if (isset(\$attributes) && \$attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php \$attributes = \$attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
Expand Down Expand Up @@ -546,7 +546,7 @@ public function testClasslessComponentsWithAnonymousComponentNamespace()

$result = $compiler->compileTags('<x-frontend::anonymous-component :name="\'Taylor\'" :age="31" wire:model="foo" />');

$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']])
$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'],'factory' => \$__env])
<?php if (isset(\$attributes) && \$attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php \$attributes = \$attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
Expand Down Expand Up @@ -580,7 +580,7 @@ public function testClasslessComponentsWithAnonymousComponentNamespaceWithIndexV

$result = $compiler->compileTags('<x-admin.auth::anonymous-component :name="\'Taylor\'" :age="31" wire:model="foo" />');

$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']])
$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'],'factory' => \$__env])
<?php if (isset(\$attributes) && \$attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php \$attributes = \$attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
Expand Down Expand Up @@ -613,7 +613,7 @@ public function testClasslessComponentsWithAnonymousComponentPath()

$result = $compiler->compileTags('<x-panel />');

$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'panel', ['view' => '".md5('test-directory')."::panel.index','data' => []])
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'panel', ['view' => '".md5('test-directory')."::panel.index','data' => [],'factory' => \$__env])
<?php if (isset(\$attributes) && \$attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php \$attributes = \$attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
Expand Down Expand Up @@ -646,7 +646,7 @@ public function testClasslessIndexComponentsWithAnonymousComponentPath()

$result = $compiler->compileTags('<x-panel />');

$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'panel', ['view' => '".md5('test-directory')."::panel','data' => []])
$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'panel', ['view' => '".md5('test-directory')."::panel','data' => [],'factory' => \$__env])
<?php if (isset(\$attributes) && \$attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php \$attributes = \$attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
Expand Down
Loading