mirror of
https://github.com/avecms/AVE.cms.git
synced 2026-08-01 00:45:44 +00:00
142 lines
6.1 KiB
PHP
142 lines
6.1 KiB
PHP
<?php
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------------------
|
|
| AVE.cms
|
|
|--------------------------------------------------------------------------------------
|
|
| @package AVE.cms
|
|
| @file system/App/Content/Blocks/ContentBlockRegistry.php
|
|
| @author AVE.cms <support@ave-cms.ru>
|
|
| @copyright 2007-2026 (c) AVE.cms
|
|
| @link https://ave-cms.ru
|
|
| @version 3.3
|
|
*/
|
|
|
|
namespace App\Content\Blocks;
|
|
|
|
defined('BASEPATH') || die('Direct access to this location is not allowed.');
|
|
|
|
/** Declarative block types for future structured, repeatable content fields. */
|
|
class ContentBlockRegistry
|
|
{
|
|
protected static $blocks = array();
|
|
protected static $defaultsRegistered = false;
|
|
|
|
public static function register($code, array $definition, $source = 'core', $available = true)
|
|
{
|
|
self::ensureDefaults();
|
|
$code = strtolower(trim((string) $code));
|
|
if (!preg_match('/^[a-z][a-z0-9_-]{1,63}$/', $code)) {
|
|
throw new \InvalidArgumentException('Некорректный код блока контента: ' . $code);
|
|
}
|
|
|
|
if (isset(self::$blocks[$code]) && (string) self::$blocks[$code]['source'] !== (string) $source) {
|
|
throw new \RuntimeException('Код блока контента уже зарегистрирован: ' . $code);
|
|
}
|
|
|
|
$block = self::normalize($code, $definition);
|
|
$block['source'] = (string) $source;
|
|
$block['available'] = (bool) $available;
|
|
self::$blocks[$code] = $block;
|
|
return $block;
|
|
}
|
|
|
|
public static function registerMany($source, array $definitions, $available = true)
|
|
{
|
|
$registered = array();
|
|
foreach ($definitions as $key => $definition) {
|
|
if (!is_array($definition)) { continue; }
|
|
$code = is_string($key) ? $key : (isset($definition['code']) ? $definition['code'] : '');
|
|
$registered[] = self::register($code, $definition, $source, $available);
|
|
}
|
|
|
|
return $registered;
|
|
}
|
|
|
|
public static function get($code, $includeUnavailable = false)
|
|
{
|
|
self::ensureDefaults();
|
|
$code = strtolower(trim((string) $code));
|
|
if (!isset(self::$blocks[$code])) { return null; }
|
|
if (!$includeUnavailable && empty(self::$blocks[$code]['available'])) { return null; }
|
|
return self::$blocks[$code];
|
|
}
|
|
|
|
public static function all($includeUnavailable = false)
|
|
{
|
|
self::ensureDefaults();
|
|
$blocks = array();
|
|
foreach (self::$blocks as $block) {
|
|
if ($includeUnavailable || !empty($block['available'])) { $blocks[] = $block; }
|
|
}
|
|
|
|
usort($blocks, function ($left, $right) {
|
|
$priority = (int) $left['priority'] <=> (int) $right['priority'];
|
|
return $priority !== 0 ? $priority : strcasecmp((string) $left['title'], (string) $right['title']);
|
|
});
|
|
return $blocks;
|
|
}
|
|
|
|
public static function reset()
|
|
{
|
|
self::$blocks = array();
|
|
self::$defaultsRegistered = false;
|
|
}
|
|
|
|
protected static function ensureDefaults()
|
|
{
|
|
if (self::$defaultsRegistered) { return; }
|
|
self::$defaultsRegistered = true;
|
|
$definitions = array(
|
|
'paragraph' => array('title' => 'Текст', 'icon' => 'ti-align-left', 'priority' => 10, 'fields' => array(array('key' => 'text', 'type' => 'multi_line', 'required' => true))),
|
|
'rich_text' => array('title' => 'Форматированный текст', 'icon' => 'ti-text-size', 'priority' => 20, 'fields' => array(array('key' => 'html', 'type' => 'rich_text', 'required' => true))),
|
|
'image' => array('title' => 'Изображение', 'icon' => 'ti-photo', 'priority' => 30, 'fields' => array(array('key' => 'image', 'type' => 'image_single', 'required' => true), array('key' => 'caption', 'type' => 'single_line'))),
|
|
'quote' => array('title' => 'Цитата', 'icon' => 'ti-quote', 'priority' => 40, 'fields' => array(array('key' => 'text', 'type' => 'multi_line', 'required' => true), array('key' => 'author', 'type' => 'single_line'))),
|
|
'document_relation' => array('title' => 'Связанные материалы', 'icon' => 'ti-link', 'priority' => 50, 'fields' => array(array('key' => 'documents', 'type' => 'doc_from_rub_search', 'required' => true))),
|
|
);
|
|
foreach ($definitions as $code => $definition) {
|
|
$block = self::normalize($code, $definition);
|
|
$block['source'] = 'core';
|
|
$block['available'] = true;
|
|
self::$blocks[$code] = $block;
|
|
}
|
|
}
|
|
|
|
protected static function normalize($code, array $definition)
|
|
{
|
|
$title = trim(isset($definition['title']) ? (string) $definition['title'] : '');
|
|
if ($title === '') { throw new \InvalidArgumentException('У блока контента отсутствует название: ' . $code); }
|
|
$fields = array();
|
|
$keys = array();
|
|
foreach (isset($definition['fields']) && is_array($definition['fields']) ? $definition['fields'] : array() as $field) {
|
|
if (!is_array($field)) { continue; }
|
|
$key = strtolower(trim(isset($field['key']) ? (string) $field['key'] : ''));
|
|
$type = trim(isset($field['type']) ? (string) $field['type'] : '');
|
|
if (!preg_match('/^[a-z][a-z0-9_]{1,63}$/', $key) || $type === '' || isset($keys[$key])) {
|
|
throw new \InvalidArgumentException('Некорректное поле блока ' . $code . ': ' . ($key !== '' ? $key : '(без ключа)'));
|
|
}
|
|
|
|
$keys[$key] = true;
|
|
$fields[] = array(
|
|
'key' => $key,
|
|
'type' => $type,
|
|
'label' => isset($field['label']) ? trim((string) $field['label']) : '',
|
|
'required' => !empty($field['required']),
|
|
'settings' => isset($field['settings']) && is_array($field['settings']) ? $field['settings'] : array(),
|
|
);
|
|
}
|
|
|
|
if (!$fields) { throw new \InvalidArgumentException('Блок контента не содержит полей: ' . $code); }
|
|
|
|
return array(
|
|
'code' => $code,
|
|
'title' => $title,
|
|
'description' => isset($definition['description']) ? trim((string) $definition['description']) : '',
|
|
'icon' => isset($definition['icon']) ? trim((string) $definition['icon']) : 'ti-box',
|
|
'priority' => isset($definition['priority']) ? (int) $definition['priority'] : 100,
|
|
'fields' => $fields,
|
|
'settings' => isset($definition['settings']) && is_array($definition['settings']) ? $definition['settings'] : array(),
|
|
);
|
|
}
|
|
}
|