FEATURE #1431: add template edit

This commit is contained in:
Michal Kváček
2016-02-19 15:10:39 +01:00
parent 53395bc47a
commit 57e08b76a8
12 changed files with 413 additions and 14 deletions
+179
View File
@@ -0,0 +1,179 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests;
use App\Http\Requests\EditTemplateRequest;
use App\Models\Template;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
class EditTemplate extends Controller
{
/**
* Render form for editing template
*
* @param $template
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getEdit($template)
{
$template = Template::findOrFail($template);
$path = $template->getPath();
// load template content
$absolutePath = $template->getPathToTemplate();
$content = file_get_contents($absolutePath);
return view('admin.templates.edit', [
'template' => $template,
'templateContent' => $content,
'isWritable' => is_writable(dirname($absolutePath)),
'path' => $path,
]);
}
/**
* Save meta information about template and edited content
*
* @param EditTemplateRequest $request
* @param $templateId
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postEdit(EditTemplateRequest $request, $templateId)
{
// find template
$template = Template::findOrFail($templateId);
// setup meta information
$template->name = $request->name;
if ($request->description) {
$template->description = $request->description;
}
// save meta information into database
$template->save();
// try to save content
return $this->saveContent($template, $request);
}
/**
* Save physical content of given template
*
* @param Template $template
* @param EditTemplateRequest $request
*
* @return \Illuminate\Http\RedirectResponse
*/
private function saveContent(Template $template, EditTemplateRequest $request)
{
// get templates with paths
$originalTemplate = $template->getPathToTemplate(Template::ORIGINAL_DIRECTORY);
$customTemplate = $template->getPathToTemplate(Template::CUSTOM_EDIT_DIRECTORY);
// get paths
$originalDir = dirname($originalTemplate);
$customDir = dirname($customTemplate);
// try to save content
if (!is_writable($customDir) && !is_writable($originalDir)) {
return redirect()
->route('templates.edit', ['id' => $request->id])
->withInput()
->with('error', trans('admin/templates.cannotWriteContent'));
}
// save new content only if something was changed
if ($this->isContentDifferent($originalTemplate, $customTemplate, $request->templateContent)) {
// create directory for custom updates
if (!is_dir($customDir)) {
File::makeDirectory($customDir);
}
// make copy of existing template (if exists)
$this->backupTemplates($customTemplate);
// save content
File::put($customTemplate, $request->templateContent);
}
return redirect()
->route('templates.overview', ['id' => $template->path])
->with('success', trans('admin/templates.editSuccessfull'));
}
/**
* Get last "revision" of edited template.
*
* Template changes are not discarded, however new file is created. Last template is renamed to
* <template>.blade.php.<num>, where <num> is result of this method.
*
* @param $template
*
* @return int
*/
private function getNewRevisionNumber($template)
{
$number = 0;
while (File::exists($template . '.' . $number)) {
$number++;
}
return $number;
}
/**
* If exists previously edited template, rename it to <template>.blade.php.<number>
*
* @param $template
*/
private function backupTemplates($template)
{
// get last sequence number
$number = $this->getNewRevisionNumber($template);
// nothing to backup
if ($number == 0) {
return;
}
// rename template
File::move($template, $template . '.' . $number);
}
/**
* Compare data from previous/original template
*
* @param $originalTemplate
* @param $customTemplate
* @param $currentContent
*
* @return bool
*/
private function isContentDifferent($originalTemplate, $customTemplate, $currentContent)
{
/**
* get last revision of template - we need to substract 1 from result from getNewRevisionNumber(),
* because this method returns number of first non-existing template
*/
$lastRevision = $this->getNewRevisionNumber($customTemplate) - 1;
// select compared file
if ($lastRevision < 0) {
$diffFile = $originalTemplate;
} else {
$diffFile = $customTemplate . '.' . $lastRevision;
}
// get content
$originalContent = file_get_contents($diffFile);
return $originalContent != $currentContent;
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace App\Http\Requests;
class EditTemplateRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|max:128',
'templateContent' => 'required'
];
}
}
+2 -2
View File
@@ -61,10 +61,10 @@ Route::group([
Route::get('templates/new/{pathId}', 'TemplateOverview@getPath')
->name('templates.new');
Route::get('templates/edit/{id}', 'TemplateOverview@getPath')
Route::get('templates/edit/{id}', 'EditTemplate@getEdit')
->name('templates.edit');
Route::post('templates/edit/{id}', 'TemplateOverview@getPath')
Route::post('templates/edit/{id}', 'EditTemplate@postEdit')
->name('templates.postEdit');
});
+64 -4
View File
@@ -18,18 +18,78 @@ class Template extends Model
'editable'
];
protected $guarded = [];
protected $pathModel = null;
const EDITED_TEMPLATES_DIRECTORY = 'custom';
const TEMPLATE_SUFFIX = '.blade.php';
const CUSTOM_EDIT_DIRECTORY = 1;
const ORIGINAL_DIRECTORY = 2;
/**
* In one path may be many templates
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function template()
public function getPath()
{
return $this->belongsTo('App\Models\TemplatePath', 'id');
if (!$this->pathModel) {
$this->pathModel = TemplatePath::where('id', $this->path)
->first();
}
return $this->pathModel;
}
/**
* Getter for absolute path to template
*
* @param null $mode
*
* @return string
*/
public function getPathToTemplate($mode = null)
{
$templateName = $this->template_name;
$path = $this->getPath();
// delete namespace if given
if (strpos($this->template_name, '::')) {
list(, $templateName) = explode('::', $templateName);
}
// get template name, do not care about directories (they are already contained in path)
$parts = explode('.', $templateName);
$templateName = last($parts);
// just a shortcut for this unbelievable long constant name...
$_ = DIRECTORY_SEPARATOR;
// path parts
$absolutePath = base_path($path->path);
$templatePath = str_replace('.', $_, $templateName);
$file = $templatePath . self::TEMPLATE_SUFFIX;
// compose two versions of path - original and with "custom" directory
$original = $absolutePath . $_ . $file;
$edited = $absolutePath . $_ . self::EDITED_TEMPLATES_DIRECTORY . $_ . $file;
// decide which path will be returned
switch ($mode) {
case self::CUSTOM_EDIT_DIRECTORY:
return $edited;
break;
case self::ORIGINAL_DIRECTORY:
return $original;
break;
default:
if (file_exists($absolutePath . $_ . self::EDITED_TEMPLATES_DIRECTORY . $_ . $file)) {
return $edited;
}
return $original;
break;
}
}
}