FEATURE #1453: add registration of templates
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 10:33
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\TemplatePath;
|
||||
|
||||
class TemplatePaths extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$paths = TemplatePath::all(['id', 'path']);
|
||||
|
||||
foreach ($paths as $path) {
|
||||
self::push($path->id, $path->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 10:33
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\TemplatePath;
|
||||
|
||||
class TemplatePathsHumanReadable extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$paths = TemplatePath::all(['id', 'name']);
|
||||
|
||||
foreach ($paths as $path) {
|
||||
self::push($path->id, $path->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 10:33
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\TemplatePath;
|
||||
|
||||
class TemplatePathsHumanReadableRootOnly extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$paths = TemplatePath::where('parent_id', null)
|
||||
->select(['id', 'name'])
|
||||
->get();
|
||||
|
||||
foreach ($paths as $path) {
|
||||
self::push($path->id, $path->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: michal
|
||||
* Date: 18.2.16
|
||||
* Time: 15:50
|
||||
*/
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Models\Template;
|
||||
|
||||
class Templates extends BaseEnumeration
|
||||
{
|
||||
protected static function init()
|
||||
{
|
||||
$templates = Template::all(['id', 'template_name']);
|
||||
|
||||
foreach ($templates as $template) {
|
||||
self::push($template->id, $template->template_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
namespace App\Handlers\Registrators;
|
||||
|
||||
use App\Enumerations\TemplatePaths;
|
||||
use App\Enumerations\Templates;
|
||||
use App\Models\Template;
|
||||
use App\Models\TemplatePath;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||
|
||||
class TemplateRegistrator
|
||||
{
|
||||
/**
|
||||
* @var string absolute path to base directory of registered template paths
|
||||
*/
|
||||
protected $baseDirectory;
|
||||
/**
|
||||
* @var string namespace of registered templates
|
||||
*/
|
||||
protected $namespace;
|
||||
/**
|
||||
* @var string absolute path to currently registered directory
|
||||
*
|
||||
* This variable is set in register() method as $baseDirectory/$path
|
||||
*/
|
||||
protected $registeredPath;
|
||||
|
||||
/**
|
||||
* Set base path
|
||||
*
|
||||
* @param mixed $baseDirectory
|
||||
*/
|
||||
public function setBaseDirectory($baseDirectory)
|
||||
{
|
||||
$baseDirectory = str_replace('/', DIRECTORY_SEPARATOR, $baseDirectory);
|
||||
$baseDirectory = base_path($baseDirectory);
|
||||
$baseDirectory = rtrim($baseDirectory, DIRECTORY_SEPARATOR);
|
||||
|
||||
if (!is_dir($baseDirectory)) {
|
||||
throw new InvalidArgumentException('Invalid path ' . $baseDirectory);
|
||||
}
|
||||
|
||||
$this->baseDirectory = $baseDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set namespace for registered template path
|
||||
*
|
||||
* @param string $namespace
|
||||
*/
|
||||
public function setNamespace($namespace)
|
||||
{
|
||||
$this->namespace = $namespace . '::';
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets namespace
|
||||
*/
|
||||
public function unsetNamespace()
|
||||
{
|
||||
$this->namespace = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new template path.
|
||||
*
|
||||
* This method registeres given path itself with all subdirectories
|
||||
*
|
||||
* @param string $path path relatively to root of the project
|
||||
* @param string $name human readable identification of given template path
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function register($path, $name)
|
||||
{
|
||||
// check if base directory was set
|
||||
if (!$this->baseDirectory || !is_dir($this->baseDirectory)) {
|
||||
throw new \Exception('Set $baseDirectory before registering template path.');
|
||||
}
|
||||
|
||||
$this->registeredPath = $this->baseDirectory . DIRECTORY_SEPARATOR . $path;
|
||||
|
||||
// register path
|
||||
$this->registerPath($this->registeredPath, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relative path to project root
|
||||
*
|
||||
* @param $directory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function relativePath($directory)
|
||||
{
|
||||
return trim(str_replace(base_path(), '', $directory), '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Crawl subdirectories and register them
|
||||
*
|
||||
* @param string $directory path relative to $baseDirectory variable
|
||||
* @param string $name name of parent directory
|
||||
*/
|
||||
protected function scanForSubdirectories($directory, $name)
|
||||
{
|
||||
$directories = File::directories($directory);
|
||||
|
||||
foreach ($directories as $dir) {
|
||||
$base = basename($dir);
|
||||
$name = preg_replace('/\.(.+)/', '.' . $base, $name);
|
||||
|
||||
$this->registerPath($dir, $name, $directory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers template path and templates into system
|
||||
*
|
||||
* @param string $path relative path to $baseDirectory variable
|
||||
* @param string $name human readable name of this path (used in overview)
|
||||
* @param null|string $parent path to parent directory
|
||||
*/
|
||||
protected function registerPath($path, $name, $parent = null)
|
||||
{
|
||||
// skip custom directories (contains updated templates only)
|
||||
$dirName = basename($path);
|
||||
if ($dirName == Template::EDITED_TEMPLATES_DIRECTORY) {
|
||||
return;
|
||||
}
|
||||
|
||||
// save template path into database
|
||||
$templatePathId = $this->saveTemplatePath($path, $name, $parent);
|
||||
|
||||
// save all templates into database
|
||||
$this->registerTemplates($path, $templatePathId);
|
||||
|
||||
// try to find some subdirectories and other templates
|
||||
$this->scanForSubdirectories($path, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all templates
|
||||
*
|
||||
* This method takes all templates in given directory and registers them into database. Templates registered in
|
||||
* this way may be used for further manipulation.
|
||||
*
|
||||
* @param $path
|
||||
* @param $templatePathId
|
||||
*
|
||||
* @throws \App\Enumerations\Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected function registerTemplates($path, $templatePathId)
|
||||
{
|
||||
$templates = File::files($path);
|
||||
|
||||
foreach ($templates as $template) {
|
||||
|
||||
// skip all non-template files - we assume that every file with suffix ".blade.php" is Blade template
|
||||
if (!Str::endsWith($template, Template::TEMPLATE_SUFFIX)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get all templates and template name (path/to/template.blade.php -> path.to.template)
|
||||
$templateName = $this->getTemplateName($template);
|
||||
$registeredTemplates = Templates::getWithTranslations();
|
||||
|
||||
if (!in_array($templateName, $registeredTemplates)) {
|
||||
|
||||
$params = [
|
||||
'template_name' => $templateName,
|
||||
'name' => $templateName,
|
||||
'path' => $templatePathId,
|
||||
'description' => '',
|
||||
'editable' => 1
|
||||
];
|
||||
|
||||
// save template into database
|
||||
$newTemplate = Template::create($params);
|
||||
|
||||
// push template into enumeration - so it will not be registered again
|
||||
Templates::push($newTemplate->id, $templateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save template into database and return its ID
|
||||
*
|
||||
* @param $path
|
||||
* @param $name
|
||||
* @param null $parent
|
||||
*
|
||||
* @return mixed|null
|
||||
* @throws \App\Enumerations\Exceptions\EnumerationExistsException
|
||||
*/
|
||||
protected function saveTemplatePath($path, $name, $parent = null)
|
||||
{
|
||||
$registeredPaths = TemplatePaths::getWithTranslations();
|
||||
$relativePath = $this->relativePath($path);
|
||||
|
||||
if (!in_array($relativePath, $registeredPaths)) {
|
||||
$parentId = $this->getId($this->relativePath($parent));
|
||||
|
||||
$params = [
|
||||
'path' => $relativePath,
|
||||
'name' => $name,
|
||||
'namespace' => $this->namespace,
|
||||
'parent_id' => $parentId
|
||||
];
|
||||
|
||||
// save into database
|
||||
$path = TemplatePath::create($params);
|
||||
|
||||
// add to enumeration
|
||||
TemplatePaths::push($path->id, $relativePath);
|
||||
|
||||
return $path->id;
|
||||
}
|
||||
|
||||
return $this->getId($relativePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ID of registered template
|
||||
*
|
||||
* @param $path
|
||||
*
|
||||
* @return null|int null when parent not found, ID of parent otherwise
|
||||
*/
|
||||
private function getId($path)
|
||||
{
|
||||
// get registered paths
|
||||
$paths = TemplatePaths::getWithTranslations();
|
||||
$paths = array_flip($paths);
|
||||
|
||||
if (is_null($path) || !!isset($paths[$path])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $paths[$path];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template name
|
||||
*
|
||||
* Converts path to template to corresponding name
|
||||
*
|
||||
* @param $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getTemplateName($template)
|
||||
{
|
||||
$templateName = str_replace($this->registeredPath . DIRECTORY_SEPARATOR, '', $template);
|
||||
$templateName = str_replace(DIRECTORY_SEPARATOR, '.', $templateName);
|
||||
$templateName = str_replace(Template::TEMPLATE_SUFFIX, '', $templateName);
|
||||
|
||||
return $this->namespace . $templateName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class CustomFieldType
|
||||
*/
|
||||
class Template extends Model
|
||||
{
|
||||
public $timestamps = true;
|
||||
protected $fillable = [
|
||||
'template_name',
|
||||
'name',
|
||||
'path',
|
||||
'description',
|
||||
'editable'
|
||||
];
|
||||
protected $guarded = [];
|
||||
|
||||
const EDITED_TEMPLATES_DIRECTORY = 'custom';
|
||||
const TEMPLATE_SUFFIX = '.blade.php';
|
||||
|
||||
|
||||
/**
|
||||
* In one path may be many templates
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function template()
|
||||
{
|
||||
return $this->belongsTo('App\Models\TemplatePath', 'id');
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,15 @@ use Illuminate\Database\Eloquent\Model;
|
||||
class TemplatePath extends Model
|
||||
{
|
||||
public $timestamps = true;
|
||||
protected $fillable = ['name'];
|
||||
protected $fillable = ['name', 'path', 'parent_id', 'namespace'];
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* In one path may be many templates
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function templates() {
|
||||
return $this->hasMany('App\Models\Template', 'path');
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Handlers\Registrators\TemplateRegistrator;
|
||||
use App\Handlers\Registrators\WidgetRegistrator;
|
||||
use App\Widgets\HtmlCode\HtmlCode;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
@@ -16,6 +17,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
public function boot()
|
||||
{
|
||||
$this->registerWidgets();
|
||||
$this->registerTemplates();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,6 +40,11 @@ class AppServiceProvider extends ServiceProvider
|
||||
$this->app->singleton('registerWidget', function ($app) {
|
||||
return new WidgetRegistrator($app);
|
||||
});
|
||||
|
||||
// create registrator for template directories
|
||||
$this->app->singleton('registerTemplateDir', function ($app) {
|
||||
return new TemplateRegistrator($app);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,4 +60,18 @@ class AppServiceProvider extends ServiceProvider
|
||||
// register all available widgets
|
||||
$registrator->register(HtmlCode::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register path with editable contents
|
||||
*/
|
||||
private function registerTemplates()
|
||||
{
|
||||
/**
|
||||
* @var $registrator TemplateRegistrator
|
||||
*/
|
||||
$registrator = $this->app->make('registerTemplateDir');
|
||||
$registrator->setBaseDirectory('resources/views/visitor');
|
||||
|
||||
$registrator->register(config('app.theme'), trans('admin/templates.core'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class AddNamespaceToTemplatePaths extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('template_paths', function (Blueprint $table) {
|
||||
$table->string('namespace', 64)
|
||||
->comment('Namespace used for all templates in this path')
|
||||
->nullable()
|
||||
->default(null)
|
||||
->after('path');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('template_paths', function (Blueprint $table) {
|
||||
$table->dropColumn('namespace');
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user