src/ServiceProvider.php
<?php
namespace Bkwld\LaravelPug;
// Dependencies
use Closure;
use Illuminate\View\Engines\CompilerEngine;
use Illuminate\View\Engines\EngineResolver;
use Phug\Component\ComponentExtension;
use Pug\Assets;
use Pug\Pug;
class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
/**
* @var Assets
*/
protected $assets;
/**
* @var ComponentExtension
*/
protected $componentExtension;
protected function setDefaultOption(Pug $pug, string $name, $value): void
{
if (!$pug->hasOption($name)) {
$pug->setOption($name, call_user_func($value));
}
}
protected function getDefaultCache(): string
{
return storage_path('/framework/views');
}
protected function getAssetsDirectories(): array
{
return array_map(function ($params) {
[$function, $arg] = $params;
return function_exists($function) ? call_user_func($function, $arg) : null;
}, [
['resource_path', 'assets'],
['app_path', 'views/assets'],
['app_path', 'assets'],
['app_path', 'views'],
['app_path', ''],
['base_path', ''],
]);
}
public function getPugEngine(): Pug
{
$config = $this->getConfig();
if (!isset($config['extensions']) && $this->app['view']) {
$extensions = array_keys(array_filter($this->app['view']->getExtensions(), function ($engine) {
$engines = explode('.', $engine);
return in_array('pug', $engines);
}));
$config['extensions'] = array_map(function ($extension) {
return ".$extension";
}, $extensions);
}
$pug = new Pug($config);
if ($config['assets'] ?? true) {
$this->assets = new Assets($pug);
$getEnv = ['App', 'environment'];
$this->assets->setEnvironment(is_callable($getEnv) ? call_user_func($getEnv) : 'production');
}
if ($config['component'] ?? true) {
ComponentExtension::enable($pug);
$this->componentExtension = $pug->getModule(ComponentExtension::class);
}
// Determine the cache dir if not configured
$this->setDefaultOption($pug, 'defaultCache', [$this, 'getDefaultCache']);
// Determine assets input directory
$this->setDefaultOption($pug, 'assetDirectory', [$this, 'getAssetsDirectories']);
// Determine assets output directory
$this->setDefaultOption($pug, 'outputDirectory', [$this, 'getOutputDirectory']);
// Optimize paths
$this->setDefaultOption($pug, 'paths', array_unique($pug->getOption('paths')));
$pug->getCompiler()->setOption('mixin_keyword', $pug->getOption('mixin_keyword'));
return $pug;
}
protected function getPugAssets(): ?Assets
{
return $this->app['laravel-pug.pug'] ? $this->assets : null;
}
protected function getOutputDirectory(): ?string
{
return function_exists('public_path') ? public_path() : null;
}
protected function getCompilerCreator($compilerClass): Closure
{
return function ($app) use ($compilerClass) {
return new $compilerClass(
[$app, 'laravel-pug.pug'],
$app['files'],
$this->getConfig(),
$this->getDefaultCache(),
$this->app['blade.compiler'] ?? null
);
};
}
/**
* Register the service provider.
*/
public function register(): void
{
$this->mergeConfigFrom(__DIR__.'/../config/config.php', 'laravel-pug');
// Bind the pug assets module
$this->app->singleton('laravel-pug.pug-assets', function () {
return $this->getPugAssets();
});
// Bind the package-configured Pug instance
$this->app->singleton('laravel-pug.pug', function () {
return $this->getPugEngine();
});
// Bind the Pug compiler
$this->app->singleton(
PugCompiler::class,
$this->getCompilerCreator(PugCompiler::class)
);
// Bind the Pug Blade compiler
$this->app->singleton(
PugBladeCompiler::class,
$this->getCompilerCreator(PugBladeCompiler::class)
);
}
/**
* Bootstrap the application events.
*
* @throws Exception for unsupported Laravel version
*/
public function boot(): void
{
if (function_exists('config_path')) {
$this->publishes([
__DIR__.'/../config/config.php' => config_path('laravel-pug.php'),
], 'laravel-pug');
}
// Register compilers
$this->registerPugCompiler();
$this->registerPugBladeCompiler();
}
/**
* Returns the view engine resolver according to current framework (laravel/lumen).
*/
public function getEngineResolver(): EngineResolver
{
return isset($this->app['view.engine.resolver'])
? $this->app['view.engine.resolver']
: $this->app['view']->getEngineResolver();
}
/**
* Register the regular Pug compiler.
*/
public function registerPugCompiler(string $subExtension = ''): void
{
$mainExtension = 'pug'.$subExtension;
// Add resolver
$this->getEngineResolver()->register($mainExtension, function () use ($subExtension) {
return new CompilerEngine(
$this->app['Bkwld\LaravelPug\Pug'.ucfirst(ltrim($subExtension, '.')).'Compiler']
);
});
$this->app['view']->addExtension($mainExtension, $mainExtension);
if ($subExtension !== '') {
$this->app['view']->addExtension(substr($subExtension, 1).'.pug', $mainExtension);
}
}
/**
* Register the blade compiler compiler.
*/
public function registerPugBladeCompiler(): void
{
$this->registerPugCompiler('.blade');
}
/**
* Get the configuration from the current app config file.
*/
public function getConfig(): array
{
$config = $this->app->make('config');
return array_merge([
'allow_composite_extensions' => true,
], [
'paths' => $config->get('view.paths'),
'debug' => $config->get('app.debug'),
], $this->app->make('config')->get('laravel-pug'));
}
/**
* Get the services provided by the provider.
*/
public function provides(): array
{
return [
PugCompiler::class,
PugBladeCompiler::class,
'laravel-pug.pug',
];
}
}