winter/modules/cms/models/ThemeData.php
Ben Thomson a59d3b83eb Code quality clean up (#4449)
Credit to @bennothommo
2019-07-18 08:50:37 -06:00

263 lines
6.3 KiB
PHP

<?php namespace Cms\Models;
use Lang;
use Model;
use Cms\Classes\Theme as CmsTheme;
use System\Classes\CombineAssets;
use Exception;
use System\Models\File;
/**
* Customization data used by a theme
*
* @package october\cms
* @author Alexey Bobkov, Samuel Georges
*/
class ThemeData extends Model
{
use \October\Rain\Database\Traits\Validation;
/**
* @var string The database table used by the model.
*/
public $table = 'cms_theme_data';
/**
* @var array Guarded fields
*/
protected $guarded = [];
/**
* @var array Fillable fields
*/
protected $fillable = [];
/**
* @var array List of attribute names which are json encoded and decoded from the database.
*/
protected $jsonable = ['data'];
/**
* @var array The rules to be applied to the data.
*/
public $rules = [];
/**
* @var array Relations
*/
public $attachOne = [];
/**
* @var ThemeData Cached array of objects
*/
protected static $instances = [];
/**
* Before saving the model, strip dynamic attributes applied from config.
* @return void
*/
public function beforeSave()
{
/*
* Dynamic attributes are stored in the jsonable attribute 'data'.
*/
$staticAttributes = ['id', 'theme', 'data', 'created_at', 'updated_at'];
$dynamicAttributes = array_except($this->getAttributes(), $staticAttributes);
$this->data = $dynamicAttributes;
$this->setRawAttributes(array_only($this->getAttributes(), $staticAttributes));
}
/**
* Clear asset cache after saving to ensure `assetVar` form fields take
* immediate effect.
*/
public function afterSave()
{
try {
CombineAssets::resetCache();
}
catch (Exception $ex) {
}
}
/**
* Returns a cached version of this model, based on a Theme object.
* @param $theme Cms\Classes\Theme
* @return self
*/
public static function forTheme($theme)
{
$dirName = $theme->getDirName();
if ($themeData = array_get(self::$instances, $dirName)) {
return $themeData;
}
try {
$themeData = self::firstOrCreate(['theme' => $dirName]);
}
catch (Exception $ex) {
// Database failed
$themeData = new self(['theme' => $dirName]);
}
return self::$instances[$dirName] = $themeData;
}
/**
* After fetching the model, intiialize model relationships based
* on form field definitions.
* @return void
*/
public function afterFetch()
{
$data = (array) $this->data + $this->getDefaultValues();
/*
* Repeater form fields store arrays and must be jsonable.
*/
foreach ($this->getFormFields() as $id => $field) {
if (!isset($field['type'])) {
continue;
}
if ($field['type'] === 'repeater') {
$this->jsonable[] = $id;
}
elseif ($field['type'] === 'fileupload') {
$this->attachOne[$id] = File::class;
unset($data[$id]);
}
}
/*
* Fill this model with the jsonable attributes kept in 'data'.
*/
$this->setRawAttributes((array) $this->getAttributes() + $data, true);
}
/**
* Before model is validated, set the default values.
* @return void
*/
public function beforeValidate()
{
if (!$this->exists) {
$this->setDefaultValues();
}
}
/**
* Creates relationships for this model based on form field definitions.
*/
public function initFormFields()
{
}
/**
* Sets default values on this model based on form field definitions.
*/
public function setDefaultValues()
{
foreach ($this->getDefaultValues() as $attribute => $value) {
$this->{$attribute} = $value;
}
}
/**
* Gets default values for this model based on form field definitions.
* @return array
*/
public function getDefaultValues()
{
$result = [];
foreach ($this->getFormFields() as $attribute => $field) {
if (($value = array_get($field, 'default')) === null) {
continue;
}
$result[$attribute] = $value;
}
return $result;
}
/**
* Returns all fields defined for this model, based on form field definitions.
* @return array
*/
public function getFormFields()
{
if (!$theme = CmsTheme::load($this->theme)) {
throw new Exception(Lang::get('Unable to find theme with name :name', $this->theme));
}
$config = $theme->getFormConfig();
return array_get($config, 'fields', []) +
array_get($config, 'tabs.fields', []) +
array_get($config, 'secondaryTabs.fields', []);
}
/**
* Returns variables that should be passed to the asset combiner.
* @return array
*/
public function getAssetVariables()
{
$result = [];
foreach ($this->getFormFields() as $attribute => $field) {
if (!$varName = array_get($field, 'assetVar')) {
continue;
}
$result[$varName] = $this->{$attribute};
}
return $result;
}
/**
* Applies asset variables to the combiner filters that support it.
* @return void
*/
public static function applyAssetVariablesToCombinerFilters($filters)
{
$theme = CmsTheme::getActiveTheme();
if (!$theme) {
return;
}
if (!$theme->hasCustomData()) {
return;
}
$assetVars = $theme->getCustomData()->getAssetVariables();
foreach ($filters as $filter) {
if (method_exists($filter, 'setPresets')) {
$filter->setPresets($assetVars);
}
}
}
/**
* Generate a cache key for the combiner, this allows variables to bust the cache.
* @return string
*/
public static function getCombinerCacheKey()
{
$theme = CmsTheme::getActiveTheme();
if (!$theme->hasCustomData()) {
return '';
}
$customData = $theme->getCustomData();
return (string) $customData->updated_at ?: '';
}
}