Add bbcode management 1.5

:(
This commit is contained in:
Visman 2020-09-27 21:55:31 +07:00
parent 516534d1d1
commit 559525fe7f
8 changed files with 755 additions and 2 deletions

View file

@ -0,0 +1,235 @@
<?php
namespace ForkBB\Models\BBCodeList;
use ForkBB\Core\Container;
use ForkBB\Models\Model as ParentModel;
use RuntimeException;
class Structure extends ParentModel
{
public function __construct(Container $container)
{
parent::__construct($container);
$this->zDepend = [
'text handler' => ['text_handler'],
'text only' => ['text_only'],
'tags only' => ['tags_only'],
'self nesting' => ['self_nesting'],
'attrs' => ['no_attr', 'def_attr'],
];
}
public function fromString(string $data): Structure
{
return $this->setAttrs(\json_decode($data, true, 512, \JSON_THROW_ON_ERROR));
}
public function toString(): string
{
}
protected function gettype(): string
{
$type = $this->getAttr('type');
return \is_string($type) ? $type : 'inline';
}
protected function getparents(): array
{
$parents = $this->getAttr('parents');
if (\is_array($parents)) {
return $parents;
} elseif ('inline' === $this->type) {
return ['inline', 'block'];
} else {
return ['block'];
}
}
protected function gettext_handler(): ?string
{
return $this->getAttr('text handler');
}
protected function settext_handler(?string $value): void
{
$this->setAttr('text handler', $value);
}
protected function setrecursive($value): void
{
$value = empty($value) ? null : true;
$this->setAttr('recursive', $value);
}
protected function gettext_only(): ?bool
{
return $this->getAttr('text only');
}
protected function settext_only($value): void
{
$value = empty($value) ? null : true;
$this->setAttr('text only', $value);
}
protected function gettags_only(): ?bool
{
return $this->getAttr('tags only');
}
protected function settags_only($value): void
{
$value = empty($value) ? null : true;
$this->setAttr('tags only', $value);
}
protected function setpre($value): void
{
$value = empty($value) ? null : true;
$this->setAttr('pre', $value);
}
protected function setsingle($value): void
{
$value = empty($value) ? null : true;
$this->setAttr('single', $value);
}
protected function getauto(): bool
{
$auto = $this->getAttr('auto');
if (\is_bool($auto)) {
return $auto;
} elseif ('inline' === $this->type) {
return true;
} else {
return false;
}
}
protected function setauto($value): void
{
$value = ! empty($value);
$this->setAttr('auto', $value);
}
protected function getself_nesting() /* : mixed */
{
return $this->getAttr('self nesting');
}
protected function setself_nesting($value): void
{
$value = $value < 1 ? false : (int) $value;
$this->setAttr('self nesting', $value);
}
protected function getBBAttr(/* mixed */ $data, array $fields) /* : mixed */
{
if (true === $data) {
return true;
} elseif (! \is_array($data)) {
return null;
} else {
$result = [];
foreach ($fields as $field) {
switch ($field) {
case 'format':
case 'body format':
$value = isset($data[$field]) && \is_string($data[$field]) ? $data[$field] : null;
break;
case 'required':
case 'text only':
$value = isset($data[$field]) && true === $data[$field] ? true : null;
break;
default:
throw new RuntimeException('Unknown attribute property');
}
$key = \str_replace(' ', '_', $field);
$result[$key] = $value;
}
return $result;
}
}
protected function setBBAttr(/* mixed */ $data, array $fields) /* : mixed */
{
if (
empty($data['allowed'])
|| $data['allowed'] < 1
) {
return null;
}
$result = [];
foreach ($fields as $field) {
switch ($field) {
case 'format':
case 'body format':
$value = isset($data[$field]) && \is_string($data[$field]) ? $data[$field] : null;
break;
case 'required':
case 'text only':
$value = isset($data[$field]) && true === $data[$field] ? true : null;
break;
default:
throw new RuntimeException('Unknown attribute property');
}
if (isset($value)) {
$key = \str_replace(' ', '_', $field);
$result[$key] = $value;
}
}
return empty($result) ? true : $result;
}
protected function getno_attr() /* mixed */
{
return $this->getBBAttr($this->attrs['no attr'] ?? null, ['body format', 'text only']);
}
protected function setno_attr(array $value): void
{
$value = $this->getBBAttr($value, ['body format', 'text only']);
$attrs = $this->getAttr('attrs');
if (null === $value) {
unset($attrs['no attr']);
} else {
$attrs['no attr'] = $value;
}
$this->setAttr('attrs', $attrs);
}
protected function getdef_attr() /* mixed */
{
return $this->getBBAttr($this->attrs['Def'] ?? null, ['required', 'format', 'body format', 'text only']);
}
protected function setdef_attr(array $value): void
{
$value = $this->getBBAttr($value, ['required', 'format', 'body format', 'text only']);
$attrs = $this->getAttr('attrs');
if (null === $value) {
unset($attrs['Def']);
} else {
$attrs['Def'] = $value;
}
$this->setAttr('attrs', $attrs);
}
}

View file

@ -4,8 +4,8 @@ namespace ForkBB\Models\Pages\Admin\Parser;
use ForkBB\Core\Validator;
use ForkBB\Models\Page;
use ForkBB\Models\BBCodeList\Structure;
use ForkBB\Models\Pages\Admin\Parser;
use ForkBB\Models\Config\Model as Config;
use function \ForkBB\__;
class BBCode extends Parser
@ -218,4 +218,266 @@ class BBCode extends Parser
return $this->c->Redirect->page('AdminBBCode')->message('BBCode deleted redirect');
}
/**
* Редактирование/добавление нового bbcode
*/
public function edit(array $args, string $method): Page
{
$this->c->bbcode->load();
$structure = $this->c->BBStructure;
$id = isset($args['id']) ? (int) $args['id'] : 0;
if ($id > 0) {
if (
empty($this->c->bbcode->bbcodeTable[$id])
|| 1 !== $this->c->bbcode->bbcodeTable[$id]['bb_edit']
) {
return $this->c->Message->message('Bad request');
}
$structure = $structure->fromString($this->c->bbcode->bbcodeTable[$id]['bb_structure']);
}
$bbTypes = [];
foreach ($this->c->bbcode->bbcodeTable as $cur) {
$type = $this->c->BBStructure->fromString($cur['bb_structure'])->type;
$bbTypes[$type] = $type;
}
$this->bbTypes = $bbTypes;
if ('POST' === $method) {
}
if ($id > 0) {
$title = __('Edit bbcode head');
$this->formAction = $this->c->Router->link('AdminBBCodeEdit', ['id' => $id]);
$this->formToken = $this->c->Csrf->create('AdminBBCodeEdit', ['id' => $id]);
} else {
$title = __('Add bbcode head');
$this->formAction = $this->c->Router->link('AdminBBCodeNew');
$this->formToken = $this->c->Csrf->create('AdminBBCodeNew');
}
$this->aCrumbs[] = [
$this->formAction,
$title,
];
if ($id > 0) {
$this->aCrumbs[] = __('"%s"', $this->c->bbcode->bbcodeTable[$id]['bb_tag']);
}
$this->aCrumbs[] = [
$this->c->Router->link('AdminBBCode'),
__('BBCode management'),
];
$this->form = $this->formEdit($id, $structure);
$this->titleForm = $title;
$this->classForm = 'editbbcode';
$this->nameTpl = 'admin/form';
return $this;
}
/**
* Формирует данные для формы
*/
protected function formEdit(int $id, Structure $structure): array
{
$form = [
'action' => $this->formAction,
'hidden' => [
'token' => $this->formToken,
],
'sets' => [],
'btns' => [
'save' => [
'type' => 'submit',
'value' => __('Save'),
// 'accesskey' => 's',
],
],
];
$yn = [1 => __('Yes'), 0 => __('No')];
$form['sets']["structure"] = [
'class' => 'structure',
// 'legend' => ,
'fields' => [
'tag' => [
'type' => $id > 0 ? 'str' : 'text',
'value' => $structure->tag,
'caption' => __('Tag label'),
'info' => __('Tag info'),
'maxlength' => 11,
'pattern' => '^[a-z\*][a-z\d-]{0,10}$',
'required' => true,
],
'type' => [
'type' => 'select',
'options' => $this->bbTypes,
'value' => $structure->type,
'caption' => __('Type label'),
'info' => __('Type info'),
],
'type_new' => [
'type' => 'text',
'value' => isset($this->bbTypes[$structure->type]) ? '' : $structure->type,
'caption' => __('Type label'),
'info' => __('New type info'),
'maxlength' => 20,
'pattern' => '^[a-z][a-z\d-]{0,19}$',
],
'parents' => [
'type' => 'multiselect',
'options' => $this->bbTypes,
'value' => $structure->parents,
'caption' => __('Parents label'),
'info' => __('Parents info'),
'size' => \min(15, \count($this->bbTypes)),
'required' => true,
],
'handler' => [
'class' => 'handler',
'type' => 'textarea',
'value' => $structure->handler,
'caption' => __('Handler label'),
'info' => __('Handler info'),
],
'text_handler' => [
'class' => 'handler',
'type' => 'textarea',
'value' => $structure->text_handler,
'caption' => __('Text handler label'),
'info' => __('Text handler info'),
],
'recursive' => [
'type' => 'radio',
'value' => true === $structure->recursive ? 1 : 0,
'values' => $yn,
'caption' => __('Recursive label'),
'info' => __('Recursive info'),
],
'text_only' => [
'type' => 'radio',
'value' => true === $structure->text_only ? 1 : 0,
'values' => $yn,
'caption' => __('Text only label'),
'info' => __('Text only info'),
],
'tags_only' => [
'type' => 'radio',
'value' => true === $structure->tags_only ? 1 : 0,
'values' => $yn,
'caption' => __('Tags only label'),
'info' => __('Tags only info'),
],
'pre' => [
'type' => 'radio',
'value' => true === $structure->pre ? 1 : 0,
'values' => $yn,
'caption' => __('Pre label'),
'info' => __('Pre info'),
],
'single' => [
'type' => 'radio',
'value' => true === $structure->single ? 1 : 0,
'values' => $yn,
'caption' => __('Single label'),
'info' => __('Single info'),
],
'auto' => [
'type' => 'radio',
'value' => true === $structure->auto ? 1 : 0,
'values' => $yn,
'caption' => __('Auto label'),
'info' => __('Auto info'),
],
'self_nesting' => [
'type' => 'number',
'value' => $structure->self_nesting > 0 ? $structure->self_nesting : 0,
'min' => 0,
'max' => 10,
'caption' => __('Self nesting label'),
'info' => __('Self nesting info'),
],
],
];
$tagStr = $id > 0 ? $structure->tag : 'TAG';
$form['sets']["no_attr"] = [
'class' => ['attr', 'no_attr'],
'legend' => __('No attr subhead', $tagStr),
'fields' => [
'no_attr[allowed]' => [
'type' => 'radio',
'value' => null === $structure->no_attr ? 0 : 1,
'values' => $yn,
'caption' => __('Allowed label'),
'info' => __('Allowed no_attr info'),
],
'no_attr[body_format]' => [
'class' => 'format',
'type' => 'text',
'value' => $structure->no_attr['body_format'] ?? '',
'caption' => __('Body format label'),
'info' => __('Body format info'),
],
'no_attr[text_only]' => [
'type' => 'radio',
'value' => empty($structure->no_attr['text_only']) ? 0 : 1,
'values' => $yn,
'caption' => __('Text only label'),
'info' => __('Text only info'),
],
],
];
$form['sets']["def_attr"] = [
'class' => ['attr', 'def_attr'],
'legend' => __('Def attr subhead', $tagStr),
'fields' => [
'def_attr[allowed]' => [
'type' => 'radio',
'value' => null === $structure->def_attr ? 0 : 1,
'values' => $yn,
'caption' => __('Allowed label'),
'info' => __('Allowed def_attr info'),
],
'def_attr[required]' => [
'type' => 'radio',
'value' => empty($structure->def_attr['required']) ? 0 : 1,
'values' => $yn,
'caption' => __('Required label'),
'info' => __('Required info'),
],
'def_attr[format]' => [
'class' => 'format',
'type' => 'text',
'value' => $structure->def_attr['format'] ?? '',
'caption' => __('Format label'),
'info' => __('Format info'),
],
'def_attr[body_format]' => [
'class' => 'format',
'type' => 'text',
'value' => $structure->def_attr['body_format'] ?? '',
'caption' => __('Body format label'),
'info' => __('Body format info'),
],
'def_attr[text_only]' => [
'type' => 'radio',
'value' => empty($structure->def_attr['text_only']) ? 0 : 1,
'values' => $yn,
'caption' => __('Text only label'),
'info' => __('Text only info'),
],
],
];
$fields = [];
return $form;
}
}

View file

@ -825,4 +825,21 @@ class Update extends Admin
return null;
}
/**
* rev.17 to rev.18
*/
protected function stageNumber17(array $args): ?int
{
$coreConfig = new CoreConfig($this->c->DIR_CONFIG . '/' . self::CONFIG_FILE);
$coreConfig->add(
'multiple=>BBStructure',
'\\ForkBB\\Models\\BBCodeList\\Structure::class'
);
$coreConfig->save();
return null;
}
}

View file

@ -42,7 +42,7 @@ if (
}
$c->PUBLIC_URL = $c->BASE_URL . $forkPublicPrefix;
$c->FORK_REVISION = 17;
$c->FORK_REVISION = 18;
$c->START = $forkStart;
$c->DIR_APP = __DIR__;
$c->DIR_PUBLIC = $forkPublic;

View file

@ -310,5 +310,7 @@ return [
'SearchModelTruncateIndex' => \ForkBB\Models\Search\TruncateIndex::class,
'SearchModelPrepare' => \ForkBB\Models\Search\Prepare::class,
'SearchModelExecute' => \ForkBB\Models\Search\Execute::class,
'BBStructure' => \ForkBB\Models\BBCodeList\Structure::class,
],
];

View file

@ -155,3 +155,117 @@ msgstr "In signatures"
msgid "BBCode deleted redirect"
msgstr "BBCode deleted."
msgid "Add bbcode head"
msgstr "Add BBCode"
msgid "Edit bbcode head"
msgstr "Edit BBCode"
msgid "Tag label"
msgstr "Tag"
msgid "Tag info"
msgstr "BB-code name. Name format: <code>^[a-z\*][a-z\d-]{0,10}$</code>"
msgid "Type label"
msgstr "Type"
msgid "Type info"
msgstr "BBCode type ..."
msgid "New type info"
msgstr "... or new type. Format: <code>^[a-z][a-z\d-]{0,19}$</code>"
msgid "Parents label"
msgstr "Parents type"
msgid "Parents info"
msgstr "Types of parent BBCode. You can specify multiple types."
msgid "Handler label"
msgstr "Handler"
msgid "Handler info"
msgstr "PHP code for converting BBCode to HTML."
msgid "Text handler label"
msgstr "Text handler"
msgid "Text handler info"
msgstr "PHP code for converting BBCode to plain text."
msgid "Recursive label"
msgstr "Recursive"
msgid "Recursive info"
msgstr "This is the recursive BBCode. Until the end of the recursion, the parser does not respond to other BBCode."
msgid "Text only label"
msgstr "Text only"
msgid "Text only info"
msgstr "This BBCode contains text only."
msgid "Tags only label"
msgstr "Tags only"
msgid "Tags only info"
msgstr "This BBCode contains other BBCode only."
msgid "Pre label"
msgstr "Pre"
msgid "Pre info"
msgstr "In this BBCode, line feeds, tabs and adjacent spaces will not be changed."
msgid "Single label"
msgstr "Single"
msgid "Single info"
msgstr "Single tag. This BBCode has no body and no end tag."
msgid "Auto label"
msgstr "Auto"
msgid "Auto info"
msgstr "Autoclosing of this tag with other BBCode."
msgid "Self nesting label"
msgstr "Self nesting"
msgid "Self nesting info"
msgstr "How many times can this BBCode be embedded in the same one."
msgid "No attr subhead"
msgstr "Settings for BBCode type [%s]..."
msgid "Allowed label"
msgstr "Allowed"
msgid "Allowed no_attr info"
msgstr "Allow use of this BBCode without attributes."
msgid "Body format label"
msgstr "Body format"
msgid "Body format info"
msgstr "The regular expression, sets the rule for body of this BBCode."
msgid "Def attr subhead"
msgstr "Settings for BBCode type [%s=<i>value</i>]..."
msgid "Allowed def_attr info"
msgstr "Allow use of this BBCode with primary attribute."
msgid "Required label"
msgstr "Required"
msgid "Required info"
msgstr "Required attribute."
msgid "Format label"
msgstr "Format"
msgid "Format info"
msgstr "The regular expression, sets the rule for this attribute."

View file

@ -155,3 +155,117 @@ msgstr "В подписях"
msgid "BBCode deleted redirect"
msgstr "BB-код удален."
msgid "Add bbcode head"
msgstr "Добавление BB-кода"
msgid "Edit bbcode head"
msgstr "Редактирование BB-кода"
msgid "Tag label"
msgstr "Tag"
msgid "Tag info"
msgstr "Имя BB-кода. Формат имени: <code>^[a-z\*][a-z\d-]{0,10}$</code>"
msgid "Type label"
msgstr "Type"
msgid "Type info"
msgstr "Тип BB-кода ..."
msgid "New type info"
msgstr "... или новый тип. Формат: <code>^[a-z][a-z\d-]{0,19}$</code>"
msgid "Parents label"
msgstr "Parents type"
msgid "Parents info"
msgstr "Типы родительского BB-кода. Можно указать несколько типов."
msgid "Handler label"
msgstr "Handler"
msgid "Handler info"
msgstr "Код PHP для преобразования BB-кода в HTML."
msgid "Text handler label"
msgstr "Text handler"
msgid "Text handler info"
msgstr "Код PHP для преобразования BB-кода в простой текст."
msgid "Recursive label"
msgstr "Recursive"
msgid "Recursive info"
msgstr "Это рекурсивный BB-код. До окончания рекурсии парсер не реагирует на другие BB-коды."
msgid "Text only label"
msgstr "Text only"
msgid "Text only info"
msgstr "Этот BB-код содержит только текст."
msgid "Tags only label"
msgstr "Tags only"
msgid "Tags only info"
msgstr "Этот BB-код содержит только другие bb-коды."
msgid "Pre label"
msgstr "Pre"
msgid "Pre info"
msgstr "В этом BB-коде символы перевода строки, табуляции и пробелы стоящие рядом не будут изменены."
msgid "Single label"
msgstr "Single"
msgid "Single info"
msgstr "Одиночный тег. В этом BB-коде нет тела и закрывающего тега."
msgid "Auto label"
msgstr "Auto"
msgid "Auto info"
msgstr "Автозакрытие тега другим BB-кодом."
msgid "Self nesting label"
msgstr "Self nesting"
msgid "Self nesting info"
msgstr "Сколько раз этот BB-код может быть вложен в такой же."
msgid "No attr subhead"
msgstr "Настройки для BB-кода вида [%s]..."
msgid "Allowed label"
msgstr "Allowed"
msgid "Allowed no_attr info"
msgstr "Разрешить использовать этот BB-код без атрибутов."
msgid "Body format label"
msgstr "Body format"
msgid "Body format info"
msgstr "Регулярное выражение, задает правило для тела BB-кода."
msgid "Def attr subhead"
msgstr "Настройки для BB-кода вида [%s=<i>значение</i>]..."
msgid "Allowed def_attr info"
msgstr "Разрешить использовать этот BB-код с первичным атрибутом."
msgid "Required label"
msgstr "Required"
msgid "Required info"
msgstr "Обязательный атрибут."
msgid "Format label"
msgstr "Format"
msgid "Format info"
msgstr "Регулярное выражение, задает правило для атрибута."

View file

@ -3006,6 +3006,15 @@ body,
display: block;
}
#fork .f-field-handler textarea {
font-family: "DejaVu Sans Mono", Consolas, "Droid Sans Mono", Monospace, Monaco, "Courier New", Courier;
height: 15rem;
}
#fork .f-field-format input {
font-family: "DejaVu Sans Mono", Consolas, "Droid Sans Mono", Monospace, Monaco, "Courier New", Courier;
}
@media screen and (min-width: 25rem) {
#fork .f-bbcode-form .f-fs-bbcode {
display: flex;