Last active
August 29, 2018 18:21
-
-
Save kevyworks/8a6575a02c2dd5b2f800f9c64aae350a to your computer and use it in GitHub Desktop.
A Laravel 5.3 Blade Component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Libraries; | |
use Illuminate\Support\HtmlString; | |
use Illuminate\View\Compilers\BladeCompiler; | |
use Illuminate\View\Factory; | |
/** | |
* Class BladeComponentsFactory | |
* | |
* This library is for Laravel 5.3 which does not have components. Also, this is a override factory | |
* from the default laravel 5.3 View Factory a copy of the ManagesComponents. I have some old projects | |
* that needs some changes and I miss components, so I created this. Yes, just a QUICK FIX, | |
* traits would be better imho. | |
* | |
* Installation `app/Providers/AppServiceProvider.php` | |
* | |
* use BladeComponentsFactory as BladeFactory; | |
* use Illuminate\Support\ServiceProvider; | |
* | |
* class AppServiceProvider extends ServiceProvider | |
* { | |
* public function register() | |
* { | |
* BladeFactory@register(); | |
* } | |
* | |
* public function boot() | |
* { | |
* BladeFactory@boot(); | |
* } | |
* } | |
* | |
* @package App\Libraries | |
*/ | |
class BladeComponentsFactory extends Factory | |
{ | |
/** | |
* The components being rendered. | |
* | |
* @var array | |
*/ | |
protected $componentStack = []; | |
/** | |
* The original data passed to the component. | |
* | |
* @var array | |
*/ | |
protected $componentData = []; | |
/** | |
* The slot contents for the component. | |
* | |
* @var array | |
*/ | |
protected $slots = []; | |
/** | |
* The names of the slots being rendered. | |
* | |
* @var array | |
*/ | |
protected $slotStack = []; | |
/** | |
* Register | |
*/ | |
public static function register() | |
{ | |
app()->singleton( | |
'view', | |
function ($app) { | |
$resolver = $app['view.engine.resolver']; | |
$finder = $app['view.finder']; | |
$factory = new static($resolver, $finder, $app['events']); | |
$factory->setContainer($app); | |
$factory->share('app', $app); | |
return $factory; | |
} | |
); | |
} | |
/** | |
* Boot | |
*/ | |
public static function boot() | |
{ | |
$directives = [ | |
'component' => function ($expression) { | |
return "<?php \$__env->startComponent({$expression}); ?>"; | |
}, | |
'endcomponent' => function () { | |
return '<?php echo $__env->renderComponent(); ?>'; | |
}, | |
'slot' => function ($expression) { | |
return "<?php \$__env->slot({$expression}); ?>"; | |
}, | |
'endslot' => function () { | |
return '<?php $__env->endSlot(); ?>'; | |
}, | |
]; | |
/** @var BladeCompiler $compiler */ | |
$compiler = app('blade.compiler'); | |
foreach ($directives as $name => $closure) { | |
$compiler->directive($name, $closure); | |
}; | |
} | |
/** | |
* Start a component rendering process. | |
* | |
* @param string $name | |
* @param array $data | |
* | |
* @return void | |
*/ | |
public function startComponent($name, array $data = []) | |
{ | |
if (ob_start()) { | |
$this->componentStack[] = $name; | |
$this->componentData[$this->currentComponent()] = $data; | |
$this->slots[$this->currentComponent()] = []; | |
} | |
} | |
/** | |
* Get the index for the current component. | |
* | |
* @return int | |
*/ | |
protected function currentComponent() | |
{ | |
return count($this->componentStack) - 1; | |
} | |
/** | |
* Render the current component. | |
* | |
* @return string | |
*/ | |
public function renderComponent() | |
{ | |
$name = array_pop($this->componentStack); | |
return $this->make($name, $this->componentData($name))->render(); | |
} | |
/** | |
* Get the data for the given component. | |
* | |
* @param string $name | |
* | |
* @return array | |
*/ | |
protected function componentData($name) | |
{ | |
return array_merge( | |
$this->componentData[count($this->componentStack)], | |
['slot' => new HtmlString(trim(ob_get_clean()))], | |
$this->slots[count($this->componentStack)] | |
); | |
} | |
/** | |
* Get Component Data | |
* | |
* @return array | |
*/ | |
public function getComponentData() | |
{ | |
return $this->componentData[count($this->componentStack)]; | |
} | |
/** | |
* Start the slot rendering process. | |
* | |
* @param string $name | |
* @param string|null $content | |
* | |
* @return void | |
*/ | |
public function slot($name, $content = null) | |
{ | |
if (func_num_args() === 2) { | |
$this->slots[$this->currentComponent()][$name] = $content; | |
} else { | |
if (ob_start()) { | |
$this->slots[$this->currentComponent()][$name] = ''; | |
$this->slotStack[$this->currentComponent()][] = $name; | |
} | |
} | |
} | |
/** | |
* Save the slot content for rendering. | |
* | |
* @return void | |
*/ | |
public function endSlot() | |
{ | |
last($this->componentStack); | |
$currentSlot = array_pop($this->slotStack[$this->currentComponent()]); | |
$this->slots[$this->currentComponent()][$currentSlot] = new HtmlString(trim(ob_get_clean())); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment