Skip to content

Commit

Permalink
[10.x] Improved Handling of Empty Component Slots with HTML Comments …
Browse files Browse the repository at this point in the history
…or Line Breaks (#49966)

* implement alternative solution for PR#49935

* style ci

* style ci

* formatting

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
comes and taylorotwell committed Feb 9, 2024
1 parent 0a8c91b commit 856d1bf
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/Illuminate/View/ComponentSlot.php
Expand Up @@ -3,6 +3,7 @@
namespace Illuminate\View;

use Illuminate\Contracts\Support\Htmlable;
use InvalidArgumentException;

class ComponentSlot implements Htmlable
{
Expand Down Expand Up @@ -77,6 +78,25 @@ public function isNotEmpty()
return ! $this->isEmpty();
}

/**
* Determine if the slot has non-comment content.
*
* @param callable|string|null $callable
* @return bool
*/
public function hasActualContent(callable|string|null $callable = null)
{
if (is_string($callable) && ! function_exists($callable)) {
throw new InvalidArgumentException('Callable does not exist.');
}

return filter_var(
$this->contents,
FILTER_CALLBACK,
['options' => $callable ?? fn ($input) => trim(preg_replace("/<!--([\s\S]*?)-->/", '', $input))]
) !== '';
}

/**
* Get the slot's HTML string.
*
Expand Down
58 changes: 58 additions & 0 deletions tests/View/ComponentTest.php
Expand Up @@ -11,6 +11,7 @@
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\HtmlString;
use Illuminate\View\Component;
use Illuminate\View\ComponentSlot;
use Illuminate\View\Factory;
use Illuminate\View\View;
use Mockery as m;
Expand Down Expand Up @@ -305,6 +306,63 @@ public function testFactoryGetsSharedBetweenComponents()
Component::forgetFactory();
$this->assertNotSame($this->viewFactory, $getFactory($inline));
}

public function testComponentSlotIsEmpty()
{
$slot = new ComponentSlot();

$this->assertTrue((bool) $slot->isEmpty());
}

public function testComponentSlotSanitizedEmpty()
{
// default sanitizer should remove all html tags
$slot = new ComponentSlot('<!-- test -->');

$linebreakingSlot = new ComponentSlot("\n \t");

$moreComplexSlot = new ComponentSlot('<!--
<p>commented HTML</p>
<img border="0" src="" alt="">
-->');

$this->assertFalse((bool) $slot->hasActualContent());
$this->assertFalse((bool) $linebreakingSlot->hasActualContent('trim'));
$this->assertFalse((bool) $moreComplexSlot->hasActualContent());
}

public function testComponentSlotSanitizedNotEmpty()
{
// default sanitizer should remove all html tags
$slot = new ComponentSlot('<!-- test -->not empty');

$linebreakingSlot = new ComponentSlot("\ntest \t");

$moreComplexSlot = new ComponentSlot('before<!--
<p>commented HTML</p>
<img border="0" src="" alt="">
-->after');

$this->assertTrue((bool) $slot->hasActualContent());
$this->assertTrue((bool) $linebreakingSlot->hasActualContent('trim'));
$this->assertTrue((bool) $moreComplexSlot->hasActualContent());
}

public function testComponentSlotIsNotEmpty()
{
$slot = new ComponentSlot('test');

$anotherSlot = new ComponentSlot('test<!-- test -->');

$moreComplexSlot = new ComponentSlot('t<!--
<p>Look at this cool image:</p>
<img border="0" src="pic_trulli.jpg" alt="Trulli">
-->est');

$this->assertTrue((bool) $slot->hasActualContent());
$this->assertTrue((bool) $anotherSlot->hasActualContent());
$this->assertTrue((bool) $moreComplexSlot->hasActualContent());
}
}

class TestInlineViewComponent extends Component
Expand Down

0 comments on commit 856d1bf

Please sign in to comment.