diff --git a/modules/cms/classes/CmsCompoundObject.php b/modules/cms/classes/CmsCompoundObject.php index 3b3c16b0a..f9d9c8a57 100644 --- a/modules/cms/classes/CmsCompoundObject.php +++ b/modules/cms/classes/CmsCompoundObject.php @@ -1,13 +1,7 @@ [] + ]; /** * @var array Contains the view bag properties. @@ -50,96 +38,59 @@ class CmsCompoundObject extends CmsObject public $viewBag = []; /** - * @var array Properties that can be set with fill() + * @var array The attributes that are mass assignable. */ - protected static $fillable = [ + protected $fillable = [ 'markup', 'settings', - 'code', - 'fileName' + 'code' ]; - protected $settingsValidationRules = []; + /** + * The methods that should be returned from the collection of all objects. + * + * @var array + */ + protected $passthru = [ + 'lists', + 'where', + 'whereComponent', + 'withComponent' + ]; - protected $settingsValidationMessages = []; - - protected $viewBagValidationRules = []; - - protected $viewBagValidationMessages = []; - - protected $viewBagCache = false; - - protected $originalData = []; + /** + * @var bool Model supports code and settings sections. + */ + protected $isCompoundObject = true; + /** + * @var array|null Cache for component properties. + */ protected static $objectComponentPropertyMap = null; /** - * 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. + * After fetch event */ - public static function load($theme, $fileName) + public function afterFetch() { - if (($obj = parent::load($theme, $fileName)) === null) { - return null; - } - - CmsException::mask($obj, 200); - $parsedData = SectionParser::parse($obj->content); - CmsException::unmask(); - - $obj->settings = $parsedData['settings']; - $obj->code = $parsedData['code']; - $obj->markup = $parsedData['markup']; - - $obj->originalData['settings'] = $obj->settings; - $obj->originalData['code'] = $obj->code; - $obj->originalData['markup'] = $obj->markup; - - $obj->parseComponentSettings(); - $obj->parseSettings(); - - return $obj; + $this->parseComponentSettings(); } /** - * 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. + * Create a new Eloquent Collection instance. * - * @param string $key - * @return void + * @param array $models + * @return \October\Rain\Halcyon\Collection */ - public function __isset($key) + public function newCollection(array $models = []) { - if (parent::__isset($key) === true) { - return true; - } - - if (isset($this->viewBag[$key]) === true) { - return true; - } - - return isset($this->settings[$key]); + return new CmsObjectCollection($models); } + // + // Components + // + /** * Runs components defined in the settings * Process halts if a component returns a value @@ -154,12 +105,14 @@ class CmsCompoundObject extends CmsObject } /** - * Parse component sections. - * Replace the multiple component sections with a single "components" + * Parse component sections. + * Replace the multiple component sections with a single "components" * element in the $settings property. */ - public function parseComponentSettings() + protected function parseComponentSettings() { + $this->settings = $this->getSettingsAttribute(); + $manager = ComponentManager::instance(); $components = []; foreach ($this->settings as $setting => $value) { @@ -177,102 +130,6 @@ class CmsCompoundObject extends CmsObject $this->settings['components'] = $components; } - /** - * Returns name of a PHP class to us a parent for the PHP class created for the object's PHP section. - * @return mixed Returns the class name or null. - */ - public function getCodeClassParent() - { - return null; - } - - /** - * Sets the PHP code content string. - * @param string $value Specifies the PHP code string. - * @return \Cms\Classes\CmsCompoundObject Returns the object instance. - */ - public function setCode($value) - { - $value = trim($value); - $this->code = $value; - } - - /** - * Saves the object to the disk. - */ - public function save() - { - $this->code = trim($this->code); - $this->markup = trim($this->markup); - - $trim = function (&$values) use (&$trim) { - foreach ($values as &$value) { - if (!is_array($value)) { - $value = trim($value); - } - else { - $trim($value); - } - } - }; - - $trim($this->settings); - - if (array_key_exists('components', $this->settings) && count($this->settings['components']) == 0) { - unset($this->settings['components']); - } - - $this->validate(); - - $content = []; - - if ($this->settings) { - $content[] = Ini::render($this->settings); - } - - if ($this->code) { - if ($this->wrapCodeToPhpTags() && array_get($this->originalData, 'code') != $this->code) { - $code = preg_replace('/^\<\?php/', '', $this->code); - $code = preg_replace('/^\<\?/', '', $code); - $code = preg_replace('/\?>$/', '', $code); - - $content[] = 'code.PHP_EOL.'?>'; - } - else { - $content[] = $this->code; - } - } - - $content[] = $this->markup; - - $this->content = trim(implode(PHP_EOL.'=='.PHP_EOL, $content)); - parent::save(); - } - - /** - * 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); - } - /** * Returns a component by its name. * This method is used only in the back-end and for internal system needs when @@ -398,98 +255,6 @@ class CmsCompoundObject extends CmsObject return []; } - /** - * Clears the object cache. - */ - public static function clearCache($theme) - { - $key = crc32($theme->getPath()).'component-properties'; - Cache::forget($key); - } - - /** - * 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(); - } - - /* - * 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; - } - } - - /** - * Initializes the object properties from the cached data. - * @param array $cached The cached data array. - */ - protected function initFromCache($cached) - { - $this->viewBag = array_get($cached, 'viewBag', []); - $this->settings = array_get($cached, 'settings', []); - $this->code = array_get($cached, 'code'); - $this->markup = array_get($cached, 'markup'); - } - - /** - * Initializes a cache item. - * @param array &$item The cached item array. - */ - protected function initCacheItem(&$item) - { - $item['viewBag'] = $this->viewBag; - $item['settings'] = $this->settings; - $item['code'] = $this->code; - $item['markup'] = $this->markup; - } - - /** - * Validates the object properties. - * Throws a ValidationException in case of an error. - */ - protected function validate() - { - $validation = Validator::make( - $this->settings, - $this->settingsValidationRules, - $this->settingsValidationMessages - ); - if ($validation->fails()) { - throw new ValidationException($validation); - } - - if ($this->viewBagValidationRules && isset($this->settings['viewBag'])) { - $validation = Validator::make( - $this->settings['viewBag'], - $this->viewBagValidationRules, - $this->viewBagValidationMessages - ); - if ($validation->fails()) { - throw new ValidationException($validation); - } - } - } - - /** - * Determines if the content of the code section should be wrapped to PHP tags. - * @return boolean - */ - protected function wrapCodeToPhpTags() - { - return true; - } - // // Twig // @@ -522,4 +287,26 @@ class CmsCompoundObject extends CmsObject $stream = $twig->tokenize($markup === false ? $this->markup : $markup, 'getTwigNodeTree'); return $twig->parse($stream); } -} + + // + // Magic + // + + /** + * Dynamically handle calls into the query instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + if (in_array($method, $this->passthru)) { + $collection = $this->get(); + return call_user_func_array(array($collection, $method), $parameters); + } + + return parent::__call($method, $parameters); + } + +} \ No newline at end of file diff --git a/modules/cms/classes/CmsException.php b/modules/cms/classes/CmsException.php index 5f30cda5d..7227d89be 100644 --- a/modules/cms/classes/CmsException.php +++ b/modules/cms/classes/CmsException.php @@ -81,7 +81,7 @@ class CmsException extends ApplicationException break; } if ($result !== false) { - $this->file = $this->compoundObject->getFullPath(); + $this->file = $this->compoundObject->getFilePath(); if (File::isFile($this->file) && is_readable($this->file)) { $this->fileContent = @file($this->file); diff --git a/modules/cms/classes/CmsObject.php b/modules/cms/classes/CmsObject.php index 9316dbc45..75ba1a6c3 100644 --- a/modules/cms/classes/CmsObject.php +++ b/modules/cms/classes/CmsObject.php @@ -1,19 +1,12 @@ theme = $theme; - } - - /** - * 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. - * @param $theme Specifies the theme the object belongs to. - * @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) - { - if (!FileHelper::validatePath($fileName, static::getMaxAllowedPathNesting())) { - throw new ApplicationException(Lang::get('cms::lang.cms_object.invalid_file', ['name'=>$fileName])); - } - - if (!strlen(File::extension($fileName))) { - $fileName .= '.'.static::$defaultExtension; - } - - $filePath = static::getFilePath($theme, $fileName); - if (array_key_exists($filePath, ObjectMemoryCache::$cache)) { - return ObjectMemoryCache::$cache[$filePath]; - } - - $key = self::getObjectTypeDirName().crc32($filePath); - - clearstatcache($filePath); - $cached = Cache::get($key, false); - if ($cached !== false && ($cached = @unserialize($cached)) !== false) { - if ($cached['mtime'] != @File::lastModified($filePath)) { - $cached = false; - } - } - - if ($cached && !File::isFile($filePath)) { - $cached = false; - } - - if ($cached !== false) { - /* - * The cached item exists and successfully unserialized. - * Initialize the object from the cached data. - */ - $obj = new static($theme); - $obj->content = $cached['content']; - $obj->fileName = $fileName; - $obj->mtime = File::lastModified($filePath); - $obj->loadedFromCache = true; - $obj->initFromCache($cached); - - return ObjectMemoryCache::$cache[$filePath] = $obj; - } - - /* - * The cached item doesn't exists. - * Load the object from the file and create the cache. - */ - if (($obj = static::load($theme, $fileName)) === null) { - /* - * If the object cannot be loaded from the disk, delete the cache item. - */ - Cache::forget($key); - return null; - } - - $cached = [ - 'mtime' => @File::lastModified($filePath), - 'content' => $obj->content - ]; - - $obj->loadedFromCache = false; - $obj->initCacheItem($cached); - Cache::put($key, serialize($cached), Config::get('cms.parsedPageCacheTTL', 1440)); - - return ObjectMemoryCache::$cache[$filePath] = $obj; - } + protected $isCompoundObject = false; /** * Loads the object from a file. @@ -160,50 +39,77 @@ class CmsObject extends Extendable implements ArrayAccess, CmsObjectContract */ public static function load($theme, $fileName) { - if (!FileHelper::validatePath($fileName, static::getMaxAllowedPathNesting())) { - throw new ApplicationException(Lang::get('cms::lang.cms_object.invalid_file', ['name'=>$fileName])); - } - - if (!strlen(File::extension($fileName))) { - $fileName .= '.'.static::$defaultExtension; - } - - $fullPath = static::getFilePath($theme, $fileName); - - if (!File::isFile($fullPath)) { - return null; - } - - if (($content = @File::get($fullPath)) === false) { - return null; - } - - $obj = new static($theme); - $obj->fileName = $fileName; - $obj->originalFileName = $fileName; - $obj->mtime = File::lastModified($fullPath); - $obj->content = $content; - return $obj; + return static::inTheme($theme)->find($fileName); } /** - * Returns the maximum allowed path nesting level. - * The default value is 2, meaning that files - * can only exist in the root directory, or in a subdirectory. - * @return mixed Returns the maximum nesting level or null if any level is allowed. + * 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. + * @param $theme Specifies the theme the object belongs to. + * @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. */ - protected static function getMaxAllowedPathNesting() + public static function loadCached($theme, $fileName) { - return 2; + return static::inTheme($theme) + ->remember(Config::get('cms.parsedPageCacheTTL', 1440)) + ->find($fileName) + ; } /** - * Returns the file content. + * 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. + */ + public static function listInTheme($theme, $skipCache = false) + { + return static::inTheme($theme)->get(); + } + + /** + * 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); + } + + return static::on($theme->getDirName()); + } + + /** + * Save the object to the theme. + * + * @param array $options + * @return bool + */ + public function save(array $options = null) + { + try { + parent::save($options); + } + catch (Exception $ex) { + $this->throwHalcyonSaveException($ex); + } + } + + /** + * Returns the full path to the template file corresponding to this object. * @return string */ - public function getContent() + public function getFilePath($fileName = null) { - return $this->content; + if ($fileName === null) { + $fileName = $this->fileName; + } + + return $this->getTheme()->getBasePath().'/'.$this->getObjectTypeDirName().'/'.$fileName; } /** @@ -240,383 +146,69 @@ class CmsObject extends Extendable implements ArrayAccess, CmsObjectContract } /** - * Sets the object file name. - * @param string $fileName Specifies the file name. - * @return \Cms\Classes\CmsObject Returns the object instance. - */ - public function setFileName($fileName) - { - $fileName = trim($fileName); - - if (!strlen($fileName)) { - throw new ValidationException(['fileName' => - Lang::get('cms::lang.cms_object.file_name_required', [ - 'allowed' => implode(', ', static::$allowedExtensions), - 'invalid' => pathinfo($fileName, PATHINFO_EXTENSION) - ]) - ]); - } - - if (!FileHelper::validateExtension($fileName, static::$allowedExtensions)) { - throw new ValidationException(['fileName' => - Lang::get('cms::lang.cms_object.invalid_file_extension', [ - 'allowed' => implode(', ', static::$allowedExtensions), - 'invalid' => pathinfo($fileName, PATHINFO_EXTENSION) - ]) - ]); - } - - if (!FileHelper::validatePath($fileName, static::getMaxAllowedPathNesting())) { - throw new ValidationException([ - 'fileName' => Lang::get('cms::lang.cms_object.invalid_file', ['name'=>$fileName]) - ]); - } - - if (!strlen(File::extension($fileName))) { - $fileName .= '.htm'; - } - - $this->fileName = $fileName; - return $this; - } - - /** - * Returns the full path to the template file corresponding to this object. + * Returns the file content. * @return string */ - public function getFullPath() + public function getContent() { - return static::getFilePath($this->theme, $this->fileName); - } - - /** - * Returns true if the object was loaded from the cache. - * This method is used by the CMS internally. - * @return boolean - */ - public function isLoadedFromCache() - { - return $this->loadedFromCache; + return $this->content; } /** * Returns the Twig content string. + * @return string */ public function getTwigContent() { return $this->content; } - /** - * Sets the object attributes. - * @param array $attributes A list of attributes to set. - */ - public function fill(array $attributes) - { - foreach ($attributes as $key => $value) { - if (!in_array($key, static::$fillable)) { - throw new ApplicationException(Lang::get( - 'cms::lang.cms_object.invalid_property', - ['name' => $key] - )); - } - - $methodName = 'set'.ucfirst($key); - if (method_exists($this, $methodName)) { - $this->$methodName($value); - } - else { - $this->$key = $value; - } - } - } - - /** - * Saves the object to the disk. - */ - public function save() - { - $fullPath = static::getFilePath($this->theme, $this->fileName); - - if (File::isFile($fullPath) && $this->originalFileName !== $this->fileName) { - throw new ApplicationException(Lang::get( - 'cms::lang.cms_object.file_already_exists', - ['name'=>$this->fileName] - )); - } - - $dirPath = rtrim(static::getFilePath($this->theme, ''), '/'); - if (!file_exists($dirPath) || !is_dir($dirPath)) { - if (!File::makeDirectory($dirPath, 0777, true, true)) { - throw new ApplicationException(Lang::get( - 'cms::lang.cms_object.error_creating_directory', - ['name'=>$dirPath] - )); - } - } - - if (($pos = strpos($this->fileName, '/')) !== false) { - $dirPath = static::getFilePath($this->theme, dirname($this->fileName)); - - if (!is_dir($dirPath) && !File::makeDirectory($dirPath, 0777, true, true)) { - throw new ApplicationException(Lang::get( - 'cms::lang.cms_object.error_creating_directory', - ['name'=>$dirPath] - )); - } - } - - $newFullPath = $fullPath; - if (@File::put($fullPath, $this->content) === false) { - throw new ApplicationException(Lang::get( - 'cms::lang.cms_object.error_saving', - ['name'=>$this->fileName] - )); - } - - if (strlen($this->originalFileName) && $this->originalFileName !== $this->fileName) { - $fullPath = static::getFilePath($this->theme, $this->originalFileName); - - if (File::isFile($fullPath)) { - @unlink($fullPath); - } - } - - clearstatcache(); - - $this->mtime = @File::lastModified($newFullPath); - $this->originalFileName = $this->fileName; - } - - /** - * Deletes the object from the disk. - */ - public function delete() - { - $fullPath = static::getFilePath($this->theme, $this->fileName); - if (File::isFile($fullPath) && !is_dir($fullPath) && !@unlink($fullPath)) { - throw new ApplicationException(Lang::get('cms::lang.cms_object.error_deleting', ['name'=>$this->fileName])); - } - } - - /** - * Clears the internal request-level object cache. - */ - public static function clearInternalCache() - { - ObjectMemoryCache::$cache = []; - } - - /** - * 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. - */ - public static function listInTheme($theme, $skipCache = false) - { - if (!$theme) { - throw new ApplicationException(Lang::get('cms::lang.theme.active.not_set')); - } - - $dirPath = $theme->getPath().'/'.static::getObjectTypeDirName(); - $result = []; - - if (!File::isDirectory($dirPath)) { - return $result; - } - - $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath)); - $it->setMaxDepth(1); // Support only a single level of subdirectories - $it->rewind(); - - while ($it->valid()) { - if ($it->isFile() && in_array($it->getExtension(), static::$allowedExtensions)) { - $filePath = $it->getBasename(); - if ($it->getDepth() > 0) { - $filePath = basename($it->getPath()).'/'.$filePath; - } - - $page = $skipCache ? static::load($theme, $filePath) : static::loadCached($theme, $filePath); - $result[] = $page; - } - - $it->next(); - } - - return $result; - } - - /** - * Returns the absolute file path. - * @param $theme Specifies a theme the file belongs to. - * @param string$fileName Specifies the file name to return the path to. - * @return string - */ - protected static function getFilePath($theme, $fileName) - { - return $theme->getPath().'/'.static::getObjectTypeDirName().'/'.$fileName; - } - - /** - * Implements the getter functionality. - * @param string $name - * @return null|string - */ - public function __get($name) - { - $methodName = 'get'.ucfirst($name); - if (method_exists($this, $methodName)) { - return $this->$methodName(); - } - - return null; - } - - /** - * Determine if an attribute exists on the object. - * @param string $key - * @return bool - */ - public function __isset($key) - { - $methodName = 'get'.ucfirst($key); - if (method_exists($this, $methodName)) { - return true; - } - - return false; - } - - /** - * Sets an attribute on the object. - * @param string $key - * @return bool - */ - public function __set($key, $value) - { - $methodName = 'set'.ucfirst($key); - if (method_exists($this, $methodName)) { - $this->$methodName($value); - } - // Do not allow setting protected properties - elseif (!property_exists($this, $key)) { - $this->$key = $value; - } - } - - /** - * Determine if the given attribute exists. - * @param mixed $offset - * @return bool - */ - public function offsetExists($offset) - { - return isset($this->$offset); - } - - /** - * Get the value for a given offset. - * @param mixed $offset - * @return mixed - */ - public function offsetGet($offset) - { - return $this->$offset; - } - - /** - * Set the value for a given offset. - * @param mixed $offset - * @param mixed $value - * @return void - */ - public function offsetSet($offset, $value) - { - $this->$offset = $value; - } - - /** - * Unset the value for a given offset. - * @param mixed $offset - * @return void - */ - public function offsetUnset($offset) - { - unset($this->$offset); - } - // - // Queries + // Internals // /** - * Get a new query builder for the object - * @return CmsObjectQuery + * Converts an exception type thrown by Halcyon to a native CMS exception. + * @param Exception $ex */ - public function newQuery() + protected function throwHalcyonSaveException(Exception $ex) { - $query = new CmsObjectQuery($this, $this->theme); - return $query; - } - - /** - * Handle dynamic method calls into the method. - * @param string $method - * @param array $parameters - * @return mixed - */ - public function __call($method, $parameters) - { - // If this object is populated with a theme, then a query - // cannot be performed on it to reduce overhead on populated objects. - if (!$this->theme) { - $query = $this->newQuery(); - return call_user_func_array(array($query, $method), $parameters); + if ($ex instanceof \October\Rain\Halcyon\Exception\MissingFileNameException) { + throw new ValidationException([ + 'fileName' => Lang::get('cms::lang.cms_object.file_name_required') + ]); + } + 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() + ]) + ]); + } + elseif ($ex instanceof \October\Rain\Halcyon\Exception\InvalidFileNameException) { + throw new ValidationException([ + 'fileName' => Lang::get('cms::lang.cms_object.invalid_file', ['name'=>$ex->getInvalidFileName()]) + ]); + } + elseif ($ex instanceof \October\Rain\Halcyon\Exception\FileExistsException) { + throw new ApplicationException( + Lang::get('cms::lang.cms_object.file_already_exists', ['name' => $ex->getInvalidPath()]) + ); + } + 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; } - - return parent::__call($method, $parameters); } - /** - * Handle dynamic static method calls into the method. - * @param string $method - * @param array $parameters - * @return mixed - */ - public static function __callStatic($method, $parameters) - { - $instance = new static; - return call_user_func_array([$instance, $method], $parameters); - } - - // - // Overrides - // - - /** - * Initializes the object properties from the cached data. - * @param array $cached The cached data array. - */ - protected function initFromCache($cached) - { - } - - /** - * Initializes a cache item. - * @param array &$item The cached item array. - */ - protected function initCacheItem(&$item) - { - } - - /** - * Returns the directory name corresponding to the object type. - * For pages the directory name is "pages", for layouts - "layouts", etc. - * @return string - */ - public static function getObjectTypeDirName() - { - } -} +} \ No newline at end of file diff --git a/modules/cms/classes/CodeParser.php b/modules/cms/classes/CodeParser.php index 8f172b5d8..496300f78 100644 --- a/modules/cms/classes/CodeParser.php +++ b/modules/cms/classes/CodeParser.php @@ -41,7 +41,7 @@ class CodeParser public function __construct(CmsCompoundObject $object) { $this->object = $object; - $this->filePath = $object->getFullPath(); + $this->filePath = $object->getFilePath(); } /** diff --git a/modules/cms/classes/ComponentPartial.php b/modules/cms/classes/ComponentPartial.php index 6dfc7a104..2129b1e49 100644 --- a/modules/cms/classes/ComponentPartial.php +++ b/modules/cms/classes/ComponentPartial.php @@ -226,12 +226,4 @@ class ComponentPartial extends Extendable implements CmsObjectContract return $path; } - - // @deprecated This method should be removed globally - // remove if year >= 2016 - public function getFullPath() - { - return $this->getFilePath(); - } - } diff --git a/modules/cms/classes/Content.php b/modules/cms/classes/Content.php index 7a5f75983..ea6609a93 100644 --- a/modules/cms/classes/Content.php +++ b/modules/cms/classes/Content.php @@ -11,23 +11,21 @@ use Markdown; */ class Content extends CmsCompoundObject { - protected static $allowedExtensions = ['htm', 'txt', 'md']; + /** + * @var string The container name associated with the model, eg: pages. + */ + protected $dirName = 'content'; + + /** + * @var array Allowable file extensions. + */ + protected $allowedExtensions = ['htm', 'txt', 'md']; /** * @var string Contains the parsed markup. */ public $parsedMarkup = null; - /** - * Returns the directory name corresponding to the object type. - * For pages the directory name is "pages", for layouts - "layouts", etc. - * @return string - */ - public static function getObjectTypeDirName() - { - return 'content'; - } - /** * Loads the object from a file. * @param \Cms\Classes\Theme $theme Specifies the theme the object belongs to. diff --git a/modules/cms/classes/Controller.php b/modules/cms/classes/Controller.php index 9663a25c2..855407ef3 100644 --- a/modules/cms/classes/Controller.php +++ b/modules/cms/classes/Controller.php @@ -372,7 +372,7 @@ class Controller */ CmsException::mask($this->page, 400); $this->loader->setObject($this->page); - $template = $this->twig->loadTemplate($this->page->getFullPath()); + $template = $this->twig->loadTemplate($this->page->getFilePath()); $this->pageContents = $template->render($this->vars); CmsException::unmask(); } @@ -382,7 +382,7 @@ class Controller */ CmsException::mask($this->layout, 400); $this->loader->setObject($this->layout); - $template = $this->twig->loadTemplate($this->layout->getFullPath()); + $template = $this->twig->loadTemplate($this->layout->getFilePath()); $result = $template->render($this->vars); CmsException::unmask(); @@ -901,7 +901,7 @@ class Controller */ CmsException::mask($partial, 400); $this->loader->setObject($partial); - $template = $this->twig->loadTemplate($partial->getFullPath()); + $template = $this->twig->loadTemplate($partial->getFilePath()); $result = $template->render(array_merge($this->vars, $parameters)); CmsException::unmask(); diff --git a/modules/cms/classes/Layout.php b/modules/cms/classes/Layout.php index 624c6807e..72505ba83 100644 --- a/modules/cms/classes/Layout.php +++ b/modules/cms/classes/Layout.php @@ -8,22 +8,20 @@ */ class Layout extends CmsCompoundObject { + /** + * Fallback layout name. + */ const FALLBACK_FILE_NAME = 'fallback'; + /** + * @var string The container name associated with the model, eg: pages. + */ + protected $dirName = 'layouts'; + protected function parseSettings() { } - /** - * Returns the directory name corresponding to the object type. - * For pages the directory name is "pages", for layouts - "layouts", etc. - * @return string - */ - public static function getObjectTypeDirName() - { - return 'layouts'; - } - /** * Initializes the fallback layout. * @param \Cms\ClassesTheme $theme Specifies a theme the file belongs to. @@ -31,7 +29,7 @@ class Layout extends CmsCompoundObject */ public static function initFallback($theme) { - $obj = new self($theme); + $obj = self::inTheme($theme); $obj->markup = '{% page %}'; $obj->fileName = self::FALLBACK_FILE_NAME; return $obj; diff --git a/modules/cms/classes/Page.php b/modules/cms/classes/Page.php index b9797f5d2..c63852f33 100644 --- a/modules/cms/classes/Page.php +++ b/modules/cms/classes/Page.php @@ -13,6 +13,25 @@ use ApplicationException; */ class Page extends CmsCompoundObject { + /** + * @var string The container name associated with the model, eg: pages. + */ + protected $dirName = 'pages'; + + /** + * @var array The attributes that are mass assignable. + */ + protected $fillable = [ + 'url', + 'title', + 'description', + 'meta_title', + 'meta_description', + 'markup', + 'settings', + 'code' + ]; + /** * @var array The API bag allows the API handler code to bind arbitrary * data to the page object. @@ -28,9 +47,9 @@ class Page extends CmsCompoundObject * 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. */ - public function __construct(Theme $theme = null) + public function __construct(array $attributes = []) { - parent::__construct($theme); + parent::__construct($attributes); $this->settingsValidationMessages = [ 'url.regex' => Lang::get('cms::lang.page.invalid_url') @@ -41,16 +60,6 @@ class Page extends CmsCompoundObject { } - /** - * Returns the directory name corresponding to the object type. - * For pages the directory name is "pages", for layouts - "layouts", etc. - * @return string - */ - public static function getObjectTypeDirName() - { - return 'pages'; - } - /** * Returns name of a PHP class to us a parent for the PHP class created for the object's PHP section. * @return mixed Returns the class name or null. diff --git a/modules/cms/classes/Partial.php b/modules/cms/classes/Partial.php index 0b422d405..e4e9d55cb 100644 --- a/modules/cms/classes/Partial.php +++ b/modules/cms/classes/Partial.php @@ -9,14 +9,9 @@ class Partial extends CmsCompoundObject { /** - * Returns the directory name corresponding to the object type. - * For pages the directory name is "pages", for layouts - "layouts", etc. - * @return string + * @var string The container name associated with the model, eg: pages. */ - public static function getObjectTypeDirName() - { - return 'partials'; - } + protected $dirName = 'partials'; /** * Returns name of a PHP class to us a parent for the PHP class created for the object's PHP section. diff --git a/modules/cms/contracts/CmsObject.php b/modules/cms/contracts/CmsObject.php index 4e42c9988..7abfeb9ad 100644 --- a/modules/cms/contracts/CmsObject.php +++ b/modules/cms/contracts/CmsObject.php @@ -27,7 +27,25 @@ interface CmsObject * @param string $fileName * @return string */ - // public static function getFilePath($fileName = null); + public function getFilePath($fileName = null); + + /** + * Returns the file name. + * @return string + */ + public function getFileName(); + + /** + * Returns the file name without the extension. + * @return string + */ + public function getBaseFileName(); + + /** + * Returns the file content. + * @return string + */ + public function getContent(); /** * Returns the Twig content string. diff --git a/modules/cms/twig/Loader.php b/modules/cms/twig/Loader.php index 61e019824..bf6c19086 100644 --- a/modules/cms/twig/Loader.php +++ b/modules/cms/twig/Loader.php @@ -49,7 +49,7 @@ class Loader implements Twig_LoaderInterface */ public function getCacheKey($name) { - return $this->obj->getFullPath(); + return $this->obj->getFilePath(); } /**