Finishing porting old functionality

- Add validation to Cms Objects
- Add local viewBag logic
- Implement new initCacheItem process
- Implement getter for viewBag/settings properties
This commit is contained in:
Samuel Georges 2016-03-17 19:25:50 +11:00
parent dcc63baffd
commit 045d186960
5 changed files with 189 additions and 39 deletions

View File

@ -54,6 +54,7 @@ class CmsCompoundObject extends CmsObject
protected $passthru = [
'lists',
'where',
'sortBy',
'whereComponent',
'withComponent'
];
@ -69,15 +70,22 @@ class CmsCompoundObject extends CmsObject
protected static $objectComponentPropertyMap = null;
/**
* After fetch event
* @var mixed Cache store for the getViewBag method.
*/
protected $viewBagCache = false;
/**
* Triggered after the object is loaded.
* @return void
*/
public function afterFetch()
{
$this->parseComponentSettings();
$this->parseSettings();
}
/**
* Create a new Eloquent Collection instance.
* Create a new Collection instance.
*
* @param array $models
* @return \October\Rain\Halcyon\Collection
@ -87,6 +95,17 @@ class CmsCompoundObject extends CmsObject
return new CmsObjectCollection($models);
}
/**
* Parses the settings array.
* Child classes can override this method in order to update
* the content of the $settings property after the object
* is loaded from a file.
*/
protected function parseSettings()
{
$this->fillViewBagArray();
}
//
// Components
//
@ -255,6 +274,57 @@ class CmsCompoundObject extends CmsObject
return [];
}
/**
* Clears the object cache.
* @param \Cms\Classes\Theme $theme Specifies a parent theme.
* @return void
*/
public static function clearCache($theme)
{
$key = crc32($theme->getPath()).'component-properties';
Cache::forget($key);
}
//
// View Bag
//
/**
* Returns the configured view bag component.
* This method is used only in the back-end and for internal system needs when
* the standard way to access components is not an option.
* @return \Cms\Classes\ViewBag Returns the view bag component instance.
*/
public function getViewBag()
{
if ($this->viewBagCache !== false) {
return $this->viewBagCache;
}
$componentName = 'viewBag';
if (!isset($this->settings['components'][$componentName])) {
$viewBag = new ViewBag(null, []);
$viewBag->name = $componentName;
return $this->viewBagCache = $viewBag;
}
return $this->viewBagCache = $this->getComponent($componentName);
}
/*
* Copies view bag properties to the view bag array.
* This is required for the back-end editors.
*/
protected function fillViewBagArray()
{
$viewBag = $this->getViewBag();
foreach ($viewBag->getProperties() as $name => $value) {
$this->viewBag[$name] = $value;
}
}
//
// Twig
//
@ -292,6 +362,42 @@ class CmsCompoundObject extends CmsObject
// Magic
//
/**
* Implements getter functionality for visible properties defined in
* the settings section or view bag array.
*/
public function __get($name)
{
if (is_array($this->settings) && array_key_exists($name, $this->settings)) {
return $this->settings[$name];
}
if (is_array($this->viewBag) && array_key_exists($name, $this->viewBag)) {
return $this->viewBag[$name];
}
return parent::__get($name);
}
/**
* Determine if an attribute exists on the object.
*
* @param string $key
* @return void
*/
public function __isset($key)
{
if (parent::__isset($key) === true) {
return true;
}
if (isset($this->viewBag[$key]) === true) {
return true;
}
return isset($this->settings[$key]);
}
/**
* Dynamically handle calls into the query instance.
*

View File

@ -6,6 +6,7 @@ use October\Rain\Halcyon\Model as HalcyonModel;
use Cms\Contracts\CmsObject as CmsObjectContract;
use ApplicationException;
use ValidationException;
use SystemException;
use Exception;
/**
@ -17,6 +18,23 @@ use Exception;
*/
class CmsObject extends HalcyonModel implements CmsObjectContract
{
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 = [];
/**
* @var array The attributes that are mass assignable.
*/
@ -29,6 +47,22 @@ class CmsObject extends HalcyonModel implements CmsObjectContract
*/
protected $isCompoundObject = false;
/**
* @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);
}
/**
* Loads the object from a file.
* This method is used in the CMS back-end. It doesn't use any caching.
@ -99,6 +133,22 @@ class CmsObject extends HalcyonModel implements CmsObjectContract
}
}
/**
* 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);
}
/**
* Returns the full path to the template file corresponding to this object.
* @return string
@ -109,7 +159,7 @@ class CmsObject extends HalcyonModel implements CmsObjectContract
$fileName = $this->fileName;
}
return $this->getTheme()->getBasePath().'/'.$this->getObjectTypeDirName().'/'.$fileName;
return $this->theme->getPath().'/'.$this->getObjectTypeDirName().'/'.$fileName;
}
/**

View File

@ -22,50 +22,38 @@ class Content extends CmsCompoundObject
protected $allowedExtensions = ['htm', 'txt', 'md'];
/**
* @var string Contains the parsed markup.
* @var array List of attribute names which are not considered "settings".
*/
public $parsedMarkup = null;
protected $purgeable = ['parsedMarkup'];
/**
* Loads the object from a file.
* @param \Cms\Classes\Theme $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 boolean Returns true if the object was successfully loaded. Otherwise returns false.
*/
public static function load($theme, $fileName)
{
if ($obj = parent::load($theme, $fileName)) {
$obj->parsedMarkup = $obj->parseMarkup();
}
return $obj;
}
/**
* Initializes the object properties from the cached data.
* Initializes the object properties from the cached data. The extra data
* set here becomes available as attributes set on the model after fetch.
* @param array $cached The cached data array.
*/
protected function initFromCache($cached)
public static function initCacheItem(&$item)
{
parent::initFromCache($cached);
$this->parsedMarkup = array_key_exists('parsed-markup', $cached)
? $cached['parsed-markup']
: $this->parseMarkup($this->markup);
$item['parsedMarkup'] = (new static($item))->parseMarkup();
}
/**
* Initializes a cache item.
* @param array &$item The cached item array.
* Returns a default value for parsedMarkup attribute.
* @return string
*/
protected function initCacheItem(&$item)
public function getParsedMarkupAttribute()
{
parent::initCacheItem($item);
$item['parsed-markup'] = $this->parsedMarkup;
if (array_key_exists('parsedMarkup', $this->attributes)) {
return $this->attributes['parsedMarkup'];
}
return $this->attributes['parsedMarkup'] = $this->parseMarkup();
}
protected function parseMarkup()
/**
* Parses the content markup according to the file type.
* @return string
*/
public function parseMarkup()
{
$extension = strtolower(File::extension($this->fileName));
@ -82,4 +70,5 @@ class Content extends CmsCompoundObject
return $result;
}
}

View File

@ -23,8 +23,10 @@ class Page extends CmsCompoundObject
*/
protected $fillable = [
'url',
'layout',
'title',
'description',
'is_hidden',
'meta_title',
'meta_description',
'markup',
@ -38,20 +40,23 @@ class Page extends CmsCompoundObject
*/
public $apiBag = [];
protected $settingsValidationRules = [
/**
* @var array The rules to be applied to the data.
*/
public $rules = [
'title' => 'required',
'url' => ['required', 'regex:/^\/[a-z0-9\/\:_\-\*\[\]\+\?\|\.\^\\\$]*$/i']
];
/**
* Creates an instance of the object and associates it with a CMS theme.
* @param \Cms\Classes\Theme $theme Specifies the theme the object belongs to.
* @param array $attributes
*/
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->settingsValidationMessages = [
$this->customMessages = [
'url.regex' => Lang::get('cms::lang.page.invalid_url')
];
}

View File

@ -273,7 +273,7 @@ class Index extends Controller
{
$this->validateRequestTheme();
$page = new Page($this->theme);
$page = Page::inTheme($this->theme);
return [
'layouts' => $page->getLayoutOptions()
];
@ -356,7 +356,7 @@ class Index extends Controller
{
$class = $this->resolveTypeClassName($type);
if (!($template = new $class($this->theme))) {
if (!($template = $class::inTheme($this->theme))) {
throw new ApplicationException(trans('cms::lang.template.not_found'));
}