winter/modules/cms/classes/CmsObject.php

323 lines
8.8 KiB
PHP
Raw Normal View History

2014-05-14 23:24:20 +10:00
<?php namespace Cms\Classes;
use App;
2014-05-14 23:24:20 +10:00
use Lang;
use Config;
use October\Rain\Halcyon\Model as HalcyonModel;
use Cms\Contracts\CmsObject as CmsObjectContract;
2015-01-28 18:03:35 +11:00
use ApplicationException;
use ValidationException;
2014-08-01 17:42:00 +10:00
use Exception;
2014-05-14 23:24:20 +10:00
/**
* This is a base class for all CMS objects - content files, pages, partials and layouts.
* The class implements basic operations with file-based templates.
*
* @package october\cms
* @author Alexey Bobkov, Samuel Georges
*/
class CmsObject extends HalcyonModel implements CmsObjectContract
2014-05-14 23:24:20 +10:00
{
use \October\Rain\Halcyon\Traits\Validation;
/**
* @var array The rules to be applied to the data.
*/
public $rules = [];
/**
* @var array The array of custom attribute names.
*/
public $attributeNames = [];
/**
* @var array The array of custom error messages.
*/
public $customMessages = [];
2014-05-14 23:24:20 +10:00
/**
* @var array The attributes that are mass assignable.
2014-05-14 23:24:20 +10:00
*/
protected $fillable = [
'content'
2014-05-14 23:24:20 +10:00
];
/**
* @var bool Model supports code and settings sections.
2014-05-14 23:24:20 +10:00
*/
protected $isCompoundObject = false;
2014-05-14 23:24:20 +10:00
/**
* @var \Cms\Classes\Theme A reference to the CMS theme containing the object.
*/
protected $themeCache;
/**
* Create a new CMS object instance.
*
* @param array $attributes
* @return void
*/
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
}
/**
* The "booting" method of the model.
* @return void
*/
protected static function boot()
{
parent::boot();
static::bootDefaultTheme();
}
/**
* Boot all of the bootable traits on the model.
* @return void
*/
protected static function bootDefaultTheme()
{
$resolver = static::getDatasourceResolver();
if ($resolver->getDefaultDatasource()) {
return;
}
$defaultTheme = App::runningInBackend()
? Theme::getEditThemeCode()
: Theme::getActiveThemeCode();
Theme::load($defaultTheme);
$resolver->setDefaultDatasource($defaultTheme);
}
2014-05-14 23:24:20 +10:00
/**
* Loads the object from a file.
* This method is used in the CMS back-end. It doesn't use any caching.
2016-03-25 18:42:39 +11:00
* @param mixed $theme Specifies the theme the object belongs to.
* @param string $fileName Specifies the file name, with the extension.
* The file name can contain only alphanumeric symbols, dashes and dots.
* @return mixed Returns a CMS object instance or null if the object wasn't found.
2014-05-14 23:24:20 +10:00
*/
public static function load($theme, $fileName)
2014-05-14 23:24:20 +10:00
{
return static::inTheme($theme)->find($fileName);
2014-05-14 23:24:20 +10:00
}
/**
* Loads the object from a cache.
* This method is used by the CMS in the runtime. If the cache is not found, it is created.
2016-03-28 15:41:47 +02:00
* @param \Cms\Classes\Theme $theme Specifies the theme the object belongs to.
2014-05-14 23:24:20 +10:00
* @param string $fileName Specifies the file name, with the extension.
* @return mixed Returns a CMS object instance or null if the object wasn't found.
*/
public static function loadCached($theme, $fileName)
{
return static::inTheme($theme)
->remember(Config::get('cms.parsedPageCacheTTL', 1440))
->find($fileName)
;
2014-05-14 23:24:20 +10:00
}
/**
* Returns the list of objects in the specified theme.
* This method is used internally by the system.
* @param \Cms\Classes\Theme $theme Specifies a parent theme.
* @param boolean $skipCache Indicates if objects should be reloaded from the disk bypassing the cache.
* @return array Returns an array of CMS objects.
2014-05-14 23:24:20 +10:00
*/
public static function listInTheme($theme, $skipCache = false)
2014-05-14 23:24:20 +10:00
{
$instance = static::inTheme($theme);
if ($skipCache) {
return $instance->get();
}
$result = [];
$items = $instance->newQuery()->lists('fileName');
foreach ($items as $item) {
$result[] = static::loadCached($theme, $item);
}
return $instance->newCollection($result);
}
2014-05-14 23:24:20 +10:00
/**
* Prepares the theme datasource for the model.
* @param \Cms\Classes\Theme $theme Specifies a parent theme.
* @return $this
*/
public static function inTheme($theme)
{
if (is_string($theme)) {
$theme = Theme::load($theme);
2014-10-11 01:22:03 +02:00
}
2014-05-14 23:24:20 +10:00
return static::on($theme->getDirName());
2014-05-14 23:24:20 +10:00
}
/**
* Save the object to the theme.
*
* @param array $options
* @return bool
2014-05-14 23:24:20 +10:00
*/
public function save(array $options = null)
2014-05-14 23:24:20 +10:00
{
try {
parent::save($options);
}
catch (Exception $ex) {
$this->throwHalcyonSaveException($ex);
}
2014-05-14 23:24:20 +10:00
}
/**
* Returns the CMS theme this object belongs to.
* @return \Cms\Classes\Theme
*/
public function getThemeAttribute()
{
if ($this->themeCache !== null) {
return $this->themeCache;
}
$themeName = $this->getDatasourceName()
?: static::getDatasourceResolver()->getDefaultDatasource();
return $this->themeCache = Theme::load($themeName);
}
2014-05-14 23:24:20 +10:00
/**
* Returns the full path to the template file corresponding to this object.
2016-03-30 18:17:18 +02:00
* @param string $fileName
2014-05-14 23:24:20 +10:00
* @return string
*/
public function getFilePath($fileName = null)
2014-05-14 23:24:20 +10:00
{
if ($fileName === null) {
$fileName = $this->fileName;
}
return $this->theme->getPath().'/'.$this->getObjectTypeDirName().'/'.$fileName;
2014-05-14 23:24:20 +10:00
}
/**
* Returns the file name.
* @return string
*/
public function getFileName()
{
return $this->fileName;
}
/**
* Returns the file name without the extension.
* @return string
*/
public function getBaseFileName()
{
$pos = strrpos($this->fileName, '.');
2014-10-11 01:22:03 +02:00
if ($pos === false) {
2014-05-14 23:24:20 +10:00
return $this->fileName;
2014-10-11 01:22:03 +02:00
}
2014-05-14 23:24:20 +10:00
return substr($this->fileName, 0, $pos);
}
/**
* Helper for {{ page.id }} or {{ layout.id }} twig vars
2014-05-17 18:08:01 +02:00
* Returns a unique string for this object.
2014-05-14 23:24:20 +10:00
* @return string
*/
public function getId()
{
return str_replace('/', '-', $this->getBaseFileName());
}
/**
* Returns the file content.
2014-05-14 23:24:20 +10:00
* @return string
*/
public function getContent()
2014-05-14 23:24:20 +10:00
{
return $this->content;
2014-05-14 23:24:20 +10:00
}
/**
* Returns the Twig content string.
* @return string
2014-05-14 23:24:20 +10:00
*/
public function getTwigContent()
{
return $this->content;
}
/**
* Returns the key used by the Twig cache.
* @return string
*/
public function getTwigCacheKey()
{
$key = $this->getFilePath();
if ($event = $this->fireEvent('cmsObject.getTwigCacheKey', compact('key'), true)) {
$key = $event;
}
return $key;
}
//
// Internals
//
2014-05-14 23:24:20 +10:00
/**
* Converts an exception type thrown by Halcyon to a native CMS exception.
* @param Exception $ex
2014-05-14 23:24:20 +10:00
*/
protected function throwHalcyonSaveException(Exception $ex)
2014-05-14 23:24:20 +10:00
{
if ($ex instanceof \October\Rain\Halcyon\Exception\MissingFileNameException) {
throw new ValidationException([
'fileName' => Lang::get('cms::lang.cms_object.file_name_required')
]);
2014-10-11 01:22:03 +02:00
}
elseif ($ex instanceof \October\Rain\Halcyon\Exception\InvalidExtensionException) {
throw new ValidationException(['fileName' =>
Lang::get('cms::lang.cms_object.invalid_file_extension', [
'allowed' => implode(', ', $ex->getAllowedExtensions()),
'invalid' => $ex->getInvalidExtension()
])
]);
2014-05-14 23:24:20 +10:00
}
elseif ($ex instanceof \October\Rain\Halcyon\Exception\InvalidFileNameException) {
throw new ValidationException([
'fileName' => Lang::get('cms::lang.cms_object.invalid_file', ['name'=>$ex->getInvalidFileName()])
]);
2014-10-11 01:22:03 +02:00
}
elseif ($ex instanceof \October\Rain\Halcyon\Exception\FileExistsException) {
throw new ApplicationException(
Lang::get('cms::lang.cms_object.file_already_exists', ['name' => $ex->getInvalidPath()])
);
2014-10-11 01:22:03 +02:00
}
elseif ($ex instanceof \October\Rain\Halcyon\Exception\CreateDirectoryException) {
throw new ApplicationException(
Lang::get('cms::lang.cms_object.error_creating_directory', ['name' => $ex->getInvalidPath()])
);
}
elseif ($ex instanceof \October\Rain\Halcyon\Exception\CreateFileException) {
throw new ApplicationException(
Lang::get('cms::lang.cms_object.error_saving', ['name' => $ex->getInvalidPath()])
);
}
else {
throw $ex;
}
}
}