Refactor Blade implementation. Use Container

This commit is contained in:
QWp6t
2016-12-06 03:28:41 -08:00
parent c69431efa5
commit 0d83ed4b8b
14 changed files with 250 additions and 257 deletions

View File

@@ -2,10 +2,6 @@
namespace App;
use Illuminate\Container\Container;
use Illuminate\Filesystem\Filesystem;
use Roots\Sage\Template\ViewServiceProvider;
/**
* Add <body> classes
*/
@@ -33,62 +29,28 @@ add_filter('excerpt_more', function () {
});
/**
* Use Blade template engine
* Template Hierarchy should search for .blade.php files
*/
array_map(function ($tag) {
add_filter("{$tag}_template_hierarchy", function($templates) {
add_filter("{$tag}_template_hierarchy", function ($templates) {
return array_merge(str_replace('.php', '.blade.php', $templates), $templates);
});
}, [
'index', '404', 'archive', 'author', 'category', 'tag', 'taxonomy', 'date', 'home',
'front_page', 'page', 'paged', 'search', 'single', 'singular', 'attachment'
]);
/**
* Render page using Blade
*/
add_filter('template_include', function ($template) {
$blade_template = (!strpos($template, '.blade.php')) ? str_replace('.php', '.blade.php', $template) : $template;
$blade_template = locate_template(basename($blade_template));
echo template($template);
if (!file_exists($blade_template)) {
return $template;
}
$container = Container::getInstance();
$container->singleton('files', function () {
return new Filesystem;
});
$provider = new ViewServiceProvider($container);
$provider->register();
$template_engine = $container->make('view');
$template_name = basename(str_replace('.blade', '', $blade_template));
$template_name = str_replace('.php', '', $template_name);
$html = $template_engine->make($template_name, apply_filters('laravel/blade/template_data', []))->render();
if (!$html) {
return $template;
}
echo $html;
return false;
// Return a blank file to make WordPress happy
return get_template_directory() . '/index.php';
}, 1000);
add_filter('comments_template', function ($theme_template) {
$container = Container::getInstance();
$template_engine = $container->make('view');
$template_name = basename(str_replace('.blade.php', '', $theme_template));
$html = $template_engine->make('partials/'.$template_name, []);
var_dump($template_engine->exists('partials/'.$template_name));
$engine = $html->getEngine();
$compiler = $engine->getCompiler();
$template = $compiler->getCompiledPath($compiler->getPath());
if ($compiler->isExpired($template)) {
$compiler->compile($theme_template);
}
return $template;
});
/**
* Tell WordPress how to find the compiled path of comments.blade.php
*/
add_filter('comments_template', 'App\\template_path');

View File

@@ -2,30 +2,50 @@
namespace App;
use Roots\Sage\Asset;
use Roots\Sage\Assets\JsonManifest;
use Roots\Sage\Template;
use Roots\Sage\Container;
function template($layout = 'base')
/**
* @param string $name
* @return Container|mixed
*/
function sage($name = '')
{
return Template::$instances[$layout];
}
function template_part($template, array $context = [], $layout = 'base')
{
extract($context);
include template($layout)->partial($template);
static $container;
if (!$container) {
$container = new Container;
}
return $name ? (isset($container[$name]) ? $container[$name] : $container["sage.{$name}"]) : $container;
}
/**
* @param $filename
*
* @param string $file
* @param array $data
* @return string
*/
function asset_path($filename)
function template($file, $data = [])
{
static $manifest;
isset($manifest) || $manifest = new JsonManifest(get_stylesheet_directory() . '/' . Asset::$dist . '/assets.json');
return (string) new Asset($filename, $manifest);
return sage('blade')->render($file, $data);
}
/**
* Retrieve path to a compiled blade view
* @param $file
* @param array $data
* @return string
*/
function template_path($file, $data = [])
{
return sage('blade')->compiledPath($file, $data);
}
/**
* @param $asset
* @return string
*/
function asset_path($asset)
{
return sage('assets')->getUri($asset);
}
/**

View File

@@ -1,39 +0,0 @@
<?php
namespace Roots\Sage;
use Roots\Sage\Assets\ManifestInterface;
/**
* Class Template
* @package Roots\Sage
* @author QWp6t
*/
class Asset
{
public static $dist = '/dist';
/** @var ManifestInterface Currently used manifest */
protected $manifest;
protected $asset;
protected $dir;
public function __construct($file, ManifestInterface $manifest = null)
{
$this->manifest = $manifest;
$this->asset = $file;
}
public function __toString()
{
return $this->getUri();
}
public function getUri()
{
$file = ($this->manifest ? $this->manifest->get($this->asset) : $this->asset);
return get_template_directory_uri() . self::$dist . "/$file";
}
}

View File

@@ -10,26 +10,32 @@ namespace Roots\Sage\Assets;
class JsonManifest implements ManifestInterface
{
/** @var array */
protected $manifest = [];
public $manifest;
/** @var string */
public $dist;
/**
* JsonManifest constructor
*
* @param string $manifestPath Local filesystem path to JSON-encoded manifest
* @param string $distUri Remote URI to assets root
*/
public function __construct($manifestPath)
public function __construct($manifestPath, $distUri)
{
$this->manifest = file_exists($manifestPath) ? json_decode(file_get_contents($manifestPath), true) : [];
$this->dist = $distUri;
}
/** @inheritdoc */
public function get($file)
public function get($asset)
{
return isset($this->manifest[$file]) ? $this->manifest[$file] : $file;
return isset($this->manifest[$asset]) ? $this->manifest[$asset] : $asset;
}
/** @inheritdoc */
public function getAll()
public function getUri($asset)
{
return $this->manifest;
return "{$this->dist}/{$this->get($asset)}";
}
}

View File

@@ -12,17 +12,20 @@ interface ManifestInterface
/**
* Get the cache-busted filename
*
* If the manifest does not have an entry for $file, then return $file
* If the manifest does not have an entry for $asset, then return $asset
*
* @param string $file The original name of the file before cache-busting
* @param string $asset The original name of the file before cache-busting
* @return string
*/
public function get($file);
public function get($asset);
/**
* Get the asset manifest
* Get the cache-busted URI
*
* @return array
* If the manifest does not have an entry for $asset, then return URI for $asset
*
* @param string $asset The original name of the file before cache-busting
* @return string
*/
public function getAll();
public function getUri($asset);
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Roots\Sage;
use Illuminate\Container\Container as BaseContainer;
class Container extends BaseContainer
{
}

View File

@@ -0,0 +1,80 @@
<?php
namespace Roots\Sage\Template;
use Jenssegers\Blade\Blade;
use Illuminate\View\Engines\CompilerEngine;
class BladeProvider extends Blade
{
/** @var Blade */
public $blade;
/** @var string */
protected $cachePath;
/**
* @param string $view
* @param array $data
* @param array $mergeData
* @return \Illuminate\View\View
*/
public function make($view, $data = [], $mergeData = [])
{
return $this->container['view']->make($this->normalizeViewPath($view), $data, $mergeData);
}
/**
* @param string $view
* @param array $data
* @param array $mergeData
* @return string
*/
public function render($view, $data = [], $mergeData = [])
{
return $this->make($view, $data, $mergeData)->render();
}
/**
* @param string $file
* @param array $data
* @param array $mergeData
* @return string
*/
public function compiledPath($file, $data = [], $mergeData = [])
{
$rendered = $this->make($file, $data, $mergeData);
$engine = $rendered->getEngine();
if (!($engine instanceof CompilerEngine)) {
// Using PhpEngine, so just return the file
return $file;
}
$compiler = $engine->getCompiler();
$compiledPath = $compiler->getCompiledPath($rendered->getPath());
if ($compiler->isExpired($compiledPath)) {
$compiler->compile($file);
}
return $compiledPath;
}
/**
* @param string $file
* @return string
*/
public function normalizeViewPath($file)
{
// Convert `\` to `/`
$view = str_replace('\\', '/', $file);
// Remove unnecessary parts of the path
$view = str_replace(array_merge((array) $this->viewPaths, ['.blade.php', '.php']), '', $view);
// Remove leading slashes
$view = ltrim($view, '/');
// Convert `/` to `.`
return str_replace('/', '.', $view);
}
}

View File

@@ -1,132 +0,0 @@
<?php
namespace Roots\Sage\Template;
use Illuminate\View\Factory;
use Illuminate\Events\Dispatcher;
use Illuminate\View\FileViewFinder;
use Illuminate\View\Engines\PhpEngine;
use Illuminate\Support\ServiceProvider;
use Illuminate\View\Engines\CompilerEngine;
use Illuminate\View\Engines\EngineResolver;
use Illuminate\View\Compilers\BladeCompiler;
class ViewServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerEngineResolver();
$this->registerViewFinder();
$this->registerFactory();
}
/**
* Register the engine resolver instance.
*
* @return void
*/
public function registerEngineResolver()
{
$this->app->singleton('view.engine.resolver', function () {
$resolver = new EngineResolver;
// Next we will register the various engines with the resolver so that the
// environment can resolve the engines it needs for various views based
// on the extension of view files. We call a method for each engines.
foreach (['php', 'blade'] as $engine) {
$this->{'register'.ucfirst($engine).'Engine'}($resolver);
}
return $resolver;
});
}
/**
* Register the PHP engine implementation.
*
* @param \Illuminate\View\Engines\EngineResolver $resolver
* @return void
*/
public function registerPhpEngine($resolver)
{
$resolver->register('php', function () {
return new PhpEngine;
});
}
/**
* Register the Blade engine implementation.
*
* @param \Illuminate\View\Engines\EngineResolver $resolver
* @return void
*/
public function registerBladeEngine($resolver)
{
$app = $this->app;
// The Compiler engine requires an instance of the CompilerInterface, which in
// this case will be the Blade compiler, so we'll first create the compiler
// instance to pass into the engine so it can compile the views properly.
$app->singleton('blade.compiler', function ($app) {
$cache = apply_filters('roots/views/blade/compiled_path', wp_upload_dir()['basedir'] . '/cache/compiled');
if (!file_exists($cache)) {
wp_mkdir_p($cache);
}
return new BladeCompiler($app->make('Illuminate\\Filesystem\\Filesystem'), $cache);
});
$resolver->register('blade', function () use ($app) {
return new CompilerEngine($app['blade.compiler']);
});
}
/**
* Register the view finder implementation.
*
* @return void
*/
public function registerViewFinder()
{
$this->app->bind('view.finder', function ($app) {
$paths = apply_filters('roots/views/blade/template_directories', [TEMPLATEPATH]);
return new FileViewFinder($app['files'], $paths);
});
}
/**
* Register the view environment.
*
* @return void
*/
public function registerFactory()
{
$this->app->singleton('view', function ($app) {
// Next we need to grab the engine resolver instance that will be used by the
// environment. The resolver will be used by an environment to get each of
// the various engine implementations such as plain PHP or Blade engine.
$resolver = $app['view.engine.resolver'];
$finder = $app['view.finder'];
$env = new Factory($resolver, $finder, new Dispatcher($app));
// We will also set the container instance on this view environment since the
// view composers may be classes registered in the container, which allows
// for great testable, flexible composers for the application developer.
$env->setContainer($app);
$env->share('app', $app);
return $env;
});
}
}

View File

@@ -2,6 +2,37 @@
namespace App;
use Roots\Sage\Assets\JsonManifest;
use Roots\Sage\Template\BladeProvider;
/**
* Add JsonManifest to Sage container
*/
sage()->singleton('sage.assets', function () {
return new JsonManifest(
get_stylesheet_directory().'/dist/assets.json',
get_stylesheet_directory_uri().'/dist'
);
});
/**
* Add Blade to Sage container
*/
sage()->singleton('sage.blade', function () {
$cachePath = wp_upload_dir()['basedir'].'/cache/compiled';
if (!file_exists($cachePath)) {
wp_mkdir_p($cachePath);
}
return new BladeProvider(TEMPLATEPATH, $cachePath, sage());
});
/**
* Create @asset() Blade directive
*/
sage('blade')->compiler()->directive('asset', function ($asset) {
return '<?= App\\asset_path(\''.trim($asset, '\'"').'\'); ?>';
});
/**
* Theme assets
*/