Skip to content

Commit

Permalink
[8.x] Consume Blade Directive (laravel#39100)
Browse files Browse the repository at this point in the history
* initial pass at consume directive

* rename method

* Track render data for consume

* Add more variety to tests

* formatting

* Update tests

* Handle flushComponents

* rename to aware

* formatting

* formatting

Co-authored-by: Taylor Otwell <taylorotwell@gmail.com>
  • Loading branch information
2 people authored and chu121su12 committed Oct 7, 2021
1 parent 507ec62 commit 36ab66f
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 9 deletions.
14 changes: 14 additions & 0 deletions src/Illuminate/View/Compilers/Concerns/CompilesComponents.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,20 @@ protected function compileProps($expression)
<?php unset(\$__defined_vars); ?>";
}

/**
* Compile the aware statement into valid PHP.
*
* @param string $expression
* @return string
*/
protected function compileAware($expression)
{
return "<?php foreach ({$expression} as \$__key => \$__value) {
\$__consumeVariable = is_string(\$__key) ? \$__key : \$__value;
\$\$__consumeVariable = is_string(\$__key) ? \$__env->getConsumableComponentData(\$__key, \$__value) : \$__env->getConsumableComponentData(\$__value);
} ?>";
}

/**
* Sanitize the given component attribute value.
*
Expand Down
74 changes: 65 additions & 9 deletions src/Illuminate/View/Concerns/ManagesComponents.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ trait ManagesComponents
*/
protected $componentData = [];

/**
* The component data for the component that is currently being rendered.
*
* @var array
*/
protected $currentComponentData = [];

/**
* The slot contents for the component.
*
Expand Down Expand Up @@ -81,16 +88,23 @@ public function renderComponent()
{
$view = array_pop($this->componentStack);

$data = $this->componentData();

$view = value($view, $data);
$this->currentComponentData = array_merge(
$previousComponentData = $this->currentComponentData,
$data = $this->componentData()
);

if ($view instanceof View) {
return $view->with($data)->render();
} elseif ($view instanceof Htmlable) {
return $view->toHtml();
} else {
return $this->make($view, $data)->render();
try {
$view = value($view, $data);

if ($view instanceof View) {
return $view->with($data)->render();
} elseif ($view instanceof Htmlable) {
return $view->toHtml();
} else {
return $this->make($view, $data)->render();
}
} finally {
$this->currentComponentData = $previousComponentData;
}
}

Expand All @@ -115,6 +129,36 @@ protected function componentData()
);
}

/**
* Get an item from the component data that exists above the current component.
*
* @param string $key
* @param mixed $default
* @return mixed|null
*/
public function getConsumableComponentData($key, $default = null)
{
if (array_key_exists($key, $this->currentComponentData)) {
return $this->currentComponentData[$key];
}

$currentComponent = count($this->componentStack);

if ($currentComponent === 0) {
return value($default);
}

for ($i = $currentComponent - 1; $i >= 0; $i--) {
$data = $this->componentData[$i] ?? [];

if (array_key_exists($key, $data)) {
return $data[$key];
}
}

return value($default);
}

/**
* Start the slot rendering process.
*
Expand Down Expand Up @@ -163,4 +207,16 @@ protected function currentComponent()
{
return count($this->componentStack) - 1;
}

/**
* Flush all of the component state.
*
* @return void
*/
protected function flushComponents()
{
$this->componentStack = [];
$this->componentData = [];
$this->currentComponentData = [];
}
}
26 changes: 26 additions & 0 deletions tests/Integration/View/BladeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,32 @@ public function tested_nested_anonymous_attribute_proxying_works_correctly()
$this->assertSame('<input class="disabled-class" foo="bar" type="text" disabled />', trim($view));
}

public function test_consume_defaults()
{
$view = View::make('consume')->render();

$this->assertSame('<h1>Menu</h1>
<div>Slot: A, Color: orange, Default: foo</div>
<div>Slot: B, Color: red, Default: foo</div>
<div>Slot: C, Color: blue, Default: foo</div>
<div>Slot: D, Color: red, Default: foo</div>
<div>Slot: E, Color: red, Default: foo</div>
<div>Slot: F, Color: yellow, Default: foo</div>', trim($view));
}

public function test_consume_with_props()
{
$view = View::make('consume', ['color' => 'rebeccapurple'])->render();

$this->assertSame('<h1>Menu</h1>
<div>Slot: A, Color: orange, Default: foo</div>
<div>Slot: B, Color: rebeccapurple, Default: foo</div>
<div>Slot: C, Color: blue, Default: foo</div>
<div>Slot: D, Color: rebeccapurple, Default: foo</div>
<div>Slot: E, Color: rebeccapurple, Default: foo</div>
<div>Slot: F, Color: yellow, Default: foo</div>', trim($view));
}

protected function getEnvironmentSetUp($app)
{
$app['config']->set('view.paths', [__DIR__.'/templates']);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@aware(['color' => 'red', 'default' => 'foo'])
<div>Slot: {{ $slot }}, Color: {{ $color }}, Default: {{ $default }}</div>
6 changes: 6 additions & 0 deletions tests/Integration/View/templates/components/menu.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<h1>Menu</h1>
<x-menu-item color="orange">A</x-menu-item>
<x-menu-item>B</x-menu-item>
{{ $slot }}
<x-menu-item>E</x-menu-item>
<x-menu-item color="yellow">F</x-menu-item>
15 changes: 15 additions & 0 deletions tests/Integration/View/templates/consume.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@isset($color)

<x-menu :color="$color">
<x-menu-item color="blue">C</x-menu-item>
<x-menu-item>D</x-menu-item>
</x-menu>

@else

<x-menu>
<x-menu-item color="blue">C</x-menu-item>
<x-menu-item>D</x-menu-item>
</x-menu>

@endisset

0 comments on commit 36ab66f

Please sign in to comment.