Added full blueprint support and Theme::getFormFieldTypes() just like in plugins

This commit is contained in:
Matias Griese
2021-03-11 12:34:37 +02:00
parent 5c1c68c553
commit 58533c495c
7 changed files with 130 additions and 91 deletions

View File

@@ -3,6 +3,8 @@
1. [](#new)
* Added `ControllerResponseTrait::createDownloadResponse()` method
* Added full blueprint support to theme if you move existing files in `blueprints/` to `blueprints/pages/` folder [#3255](https://github.com/getgrav/grav/issues/3255)
* Added support for `Theme::getFormFieldTypes()` just like in plugins
1. [](#improved)
* Optimized `Flex Pages` for speed
* Optimized saving visible/ordered pages when there are a lot of siblings [#3231](https://github.com/getgrav/grav/issues/3231)

View File

@@ -1174,7 +1174,14 @@ class Pages
$event->types = $types;
$grav->fireEvent('onGetPageBlueprints', $event);
$types->scanBlueprints('theme://blueprints/');
$types->init();
// Try new location first.
$lookup = 'theme://blueprints/pages/';
if (!is_dir($lookup)) {
$lookup = 'theme://blueprints/';
}
$types->scanBlueprints($lookup);
// Scan templates
$event = new Event();

View File

@@ -32,22 +32,23 @@ class Types implements \ArrayAccess, \Iterator, \Countable
/** @var array */
protected $items;
/** @var array */
protected $systemBlueprints;
protected $systemBlueprints = [];
/**
* @param string $type
* @param Blueprint|null $blueprint
* @return void
*/
public function register($type, $blueprint = null)
{
if (!isset($this->items[$type])) {
$this->items[$type] = [];
} elseif (!$blueprint) {
} elseif (null === $blueprint) {
return;
}
if (!$blueprint && $this->systemBlueprints) {
$blueprint = $this->systemBlueprints[$type] ?? $this->systemBlueprints['default'];
if (null === $blueprint) {
$blueprint = $this->systemBlueprints[$type] ?? $this->systemBlueprints['default'] ?? null;
}
if ($blueprint) {
@@ -55,8 +56,23 @@ class Types implements \ArrayAccess, \Iterator, \Countable
}
}
/**
* @return void
*/
public function init()
{
if (null === $this->systemBlueprints) {
// Register all blueprints from the blueprints stream.
$this->systemBlueprints = $this->findBlueprints('blueprints://pages');
foreach ($this->systemBlueprints as $type => $blueprint) {
$this->register($type);
}
}
}
/**
* @param string $uri
* @return void
*/
public function scanBlueprints($uri)
{
@@ -64,15 +80,6 @@ class Types implements \ArrayAccess, \Iterator, \Countable
throw new InvalidArgumentException('First parameter must be URI');
}
if (null === $this->systemBlueprints) {
$this->systemBlueprints = $this->findBlueprints('blueprints://pages');
// Register default by default.
$this->register('default');
$this->register('external');
}
foreach ($this->findBlueprints($uri) as $type => $blueprint) {
$this->register($type, $blueprint);
}
@@ -80,6 +87,7 @@ class Types implements \ArrayAccess, \Iterator, \Countable
/**
* @param string $uri
* @return void
*/
public function scanTemplates($uri)
{

View File

@@ -16,6 +16,7 @@ use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Config\Config;
use LogicException;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use function defined;
@@ -35,11 +36,11 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
/** @var Grav */
protected $grav;
/** @var Config */
/** @var Config|null */
protected $config;
/** @var bool */
protected $active = true;
/** @var Blueprint */
/** @var Blueprint|null */
protected $blueprint;
/**
@@ -127,21 +128,25 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
protected function isPluginActiveAdmin($plugin_route)
{
$should_run = false;
$active = false;
/** @var Uri $uri */
$uri = $this->grav['uri'];
/** @var Config $config */
$config = $this->config ?? $this->grav['config'];
if (strpos($uri->path(), $this->config->get('plugins.admin.route') . '/' . $plugin_route) === false) {
$should_run = false;
if (strpos($uri->path(), $config->get('plugins.admin.route') . '/' . $plugin_route) === false) {
$active = false;
} elseif (isset($uri->paths()[1]) && $uri->paths()[1] === $plugin_route) {
$should_run = true;
$active = true;
}
return $should_run;
return $active;
}
/**
* @param array $events
* @return void
*/
protected function enable(array $events)
{
@@ -164,22 +169,18 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
/**
* @param array $params
* @param string $eventName
* @return int
*/
private function getPriority($params, $eventName)
{
$grav = Grav::instance();
$override = implode('.', ['priorities', $this->name, $eventName, $params[0]]);
if ($grav['config']->get($override) !== null) {
return $grav['config']->get($override);
}
if (isset($params[1])) {
return $params[1];
}
return 0;
return $this->grav['config']->get($override) ?? $params[1] ?? 0;
}
/**
* @param array $events
* @return void
*/
protected function disable(array $events)
{
@@ -207,12 +208,13 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
public function offsetExists($offset)
{
$this->loadBlueprint();
if ($offset === 'title') {
$offset = 'name';
}
return isset($this->blueprint[$offset]);
$blueprint = $this->getBlueprint();
return isset($blueprint[$offset]);
}
/**
@@ -223,12 +225,13 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
public function offsetGet($offset)
{
$this->loadBlueprint();
if ($offset === 'title') {
$offset = 'name';
}
return $this->blueprint[$offset] ?? null;
$blueprint = $this->getBlueprint();
return $blueprint[$offset] ?? null;
}
/**
@@ -281,9 +284,12 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
protected function parseLinks($content, $function, $internal_regex = '(.*)')
{
$regex = '/\[plugin:(?:' . $this->name . ')\]\(' . $internal_regex . '\)/i';
$regex = '/\[plugin:(?:' . preg_quote($this->name, '/') . ')\]\(' . $internal_regex . '\)/i';
return preg_replace_callback($regex, $function, $content);
$result = preg_replace_callback($regex, $function, $content);
\assert($result !== null);
return $result;
}
/**
@@ -301,9 +307,12 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
protected function mergeConfig(PageInterface $page, $deep = false, $params = [], $type = 'plugins')
{
/** @var Config $config */
$config = $this->config ?? $this->grav['config'];
$class_name = $this->name;
$class_name_merged = $class_name . '.merged';
$defaults = $this->config->get($type . '.' . $class_name, []);
$defaults = $config->get($type . '.' . $class_name, []);
$page_header = $page->header();
$header = [];
@@ -356,23 +365,26 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
/**
* Persists to disk the plugin parameters currently stored in the Grav Config object
*
* @param string $plugin_name The name of the plugin whose config it should store.
*
* @param string $name The name of the plugin whose config it should store.
* @return bool
*/
public static function saveConfig($plugin_name)
public static function saveConfig($name)
{
if (!$plugin_name) {
if (!$name) {
return false;
}
$grav = Grav::instance();
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
$filename = 'config://plugins/' . $plugin_name . '.yaml';
$file = YamlFile::instance($locator->findResource($filename, true, true));
$content = $grav['config']->get('plugins.' . $plugin_name);
$filename = 'config://plugins/' . $name . '.yaml';
$file = YamlFile::instance((string)$locator->findResource($filename, true, true));
$content = $grav['config']->get('plugins.' . $name);
$file->save($content);
$file->free();
unset($file);
return true;
}
@@ -384,21 +396,28 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
public function getBlueprint()
{
if (!$this->blueprint) {
if (null === $this->blueprint) {
$this->loadBlueprint();
\assert($this->blueprint instanceof Blueprint);
}
return $this->blueprint;
}
/**
* Load blueprints.
*
* @return void
*/
protected function loadBlueprint()
{
if (!$this->blueprint) {
if (null === $this->blueprint) {
$grav = Grav::instance();
/** @var Plugins $plugins */
$plugins = $grav['plugins'];
$this->blueprint = $plugins->get($this->name)->blueprints();
$data = $plugins->get($this->name);
\assert($data !== null);
$this->blueprint = $data->blueprints();
}
}
}

View File

@@ -17,6 +17,7 @@ use Grav\Common\File\CompiledYamlFile;
use Grav\Events\PluginsLoadedEvent;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RuntimeException;
use SplFileInfo;
use Symfony\Component\EventDispatcher\EventDispatcher;
use function get_class;
use function is_object;
@@ -27,7 +28,7 @@ use function is_object;
*/
class Plugins extends Iterator
{
/** @var array */
/** @var array|null */
public $formFieldTypes;
/** @var bool */
@@ -46,6 +47,7 @@ class Plugins extends Iterator
$iterator = $locator->getIterator('plugins://');
$plugins = [];
/** @var SplFileInfo $directory */
foreach ($iterator as $directory) {
if (!$directory->isDir()) {
continue;
@@ -56,7 +58,10 @@ class Plugins extends Iterator
sort($plugins, SORT_NATURAL | SORT_FLAG_CASE);
foreach ($plugins as $plugin) {
$this->add($this->loadPlugin($plugin));
$object = $this->loadPlugin($plugin);
if ($object) {
$this->add($object);
}
}
}
@@ -158,6 +163,7 @@ class Plugins extends Iterator
* Add a plugin
*
* @param Plugin $plugin
* @return void
*/
public function add($plugin)
{
@@ -183,8 +189,8 @@ class Plugins extends Iterator
*/
public static function getPlugins(): array
{
$grav = Grav::instance();
$plugins = $grav['plugins'];
/** @var Plugins $plugins */
$plugins = Grav::instance()['plugins'];
$list = [];
foreach ($plugins as $instance) {
@@ -208,11 +214,13 @@ class Plugins extends Iterator
/**
* Return list of all plugin data with their blueprints.
*
* @return array<string,Data>
* @return Data[]
*/
public static function all()
{
$grav = Grav::instance();
/** @var Plugins $plugins */
$plugins = $grav['plugins'];
$list = [];

View File

@@ -9,9 +9,9 @@
namespace Grav\Common;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Config\Config;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Class Theme
@@ -44,53 +44,30 @@ class Theme extends Plugin
/**
* Persists to disk the theme parameters currently stored in the Grav Config object
*
* @param string $theme_name The name of the theme whose config it should store.
* @param string $name The name of the theme whose config it should store.
* @return bool
*/
public static function saveConfig($theme_name)
public static function saveConfig($name)
{
if (!$theme_name) {
if (!$name) {
return false;
}
$grav = Grav::instance();
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
$filename = 'config://themes/' . $theme_name . '.yaml';
$file = YamlFile::instance($locator->findResource($filename, true, true));
$content = $grav['config']->get('themes.' . $theme_name);
$filename = 'config://themes/' . $name . '.yaml';
$file = YamlFile::instance((string)$locator->findResource($filename, true, true));
$content = $grav['config']->get('themes.' . $name);
$file->save($content);
$file->free();
unset($file);
return true;
}
/**
* Override the mergeConfig method to work for themes
*
* @param PageInterface $page
* @param string $deep
* @param array $params
* @param string $type
* @return Data\Data
*/
protected function mergeConfig(PageInterface $page, $deep = 'merge', $params = [], $type = 'themes')
{
return parent::mergeConfig($page, $deep, $params, $type);
}
/**
* Simpler getter for the theme blueprint
*
* @return mixed
*/
public function getBlueprint()
{
if (!$this->blueprint) {
$this->loadBlueprint();
}
return $this->blueprint;
}
/**
* Load blueprints.
*
@@ -100,8 +77,11 @@ class Theme extends Plugin
{
if (!$this->blueprint) {
$grav = Grav::instance();
/** @var Themes $themes */
$themes = $grav['themes'];
$this->blueprint = $themes->get($this->name)->blueprints();
$data = $themes->get($this->name);
\assert($data !== null);
$this->blueprint = $data->blueprints();
}
}
}

View File

@@ -33,10 +33,8 @@ class Themes extends Iterator
{
/** @var Grav */
protected $grav;
/** @var Config */
protected $config;
/** @var bool */
protected $inited = false;
@@ -95,6 +93,20 @@ class Themes extends Iterator
$events->addSubscriber($instance);
}
// Register blueprints.
if (is_dir('theme://blueprints/pages')) {
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$locator->addPath('blueprints', '', ['theme://blueprints'], ['user', 'blueprints']);
}
// Register form fields.
if (method_exists($instance, 'getFormFieldTypes')) {
/** @var Plugins $plugins */
$plugins = $this->grav['plugins'];
$plugins->formFieldTypes = $instance->getFormFieldTypes() + $plugins->formFieldTypes;
}
$this->grav['theme'] = $instance;
$this->grav->fireEvent('onThemeInitialized');
@@ -382,7 +394,10 @@ class Themes extends Iterator
}
// Try Old style theme classes
$path = strtolower(preg_replace('#\\\|_(?!.+\\\)#', '/', $class));
$path = preg_replace('#\\\|_(?!.+\\\)#', '/', $class);
\assert(null !== $path);
$path = strtolower($path);
$file = $locator("themes://{$path}/theme.php") ?: $locator("themes://{$path}/{$path}.php");
// Load class