Skip to content
Oleg Grigoriev edited this page Jan 17, 2014 · 3 revisions

Написание своих тегов

Чтобы добавить тег [MyTag] нужно создать класс для него (например, my\ns\Tag) и добавить его в список:

$parser = new Parser(null, [
    'mytag' => '\my\ns\Tag',
]);

Класс должен расширять базовый axy\ml\tags\Base. Единственный метод, который следует обязательно определить - getHtml(void):string.

Пример:

namespace my\ns;

class MyTag exnteds \axy\ml\tags\Base
{
    public function getHTML()
    {
        return 'Oh, shit, this is my tag!!';
    }
}

Общий алгоритм

Пример, тег: [MyTag:arg1:arg2 this is value].

Вначале устанавливаются следующие protected-переменные:

  • $name: имя тега в нижнем регистре (mytag).
  • $args: массив аргументов (["arg1", "arg2"]).
  • $value: значение тега (this is value, крайние пробелы обрезаются).

После чего вызывается protected-метод parse(), который можно переопределить.

Затем при отрисовке всего документа вызывается метод getHTML(), либо getPlain(), если запрашивается простой текст (см. Result).

Подразумевается, что parse() может быть вызван только единожды, а getHTML() и getPlain() могут вызываться неоднократно, в том числе ни разу. Поэтому основной разбор следует сделать в parse(), а в getHTML() уже просто компоновать вывод.

$args (array): аргументы

Сюда попадают аргументы тега.

Разбор аргументов можно отключить:

class MyTag exnteds \axy\ml\tags\Base
{
    protected $args = false;
}

В этом случае в $value останется всё исходное содержимое тега после имени. В примере - :arg1:arg2 this is value.

getArg([int $num [, mixed $default = NULL]):string

Возвращает аргумент с порядковым номером $num (начиная от нуля). Если такого нет, возвращает $default.

По сравнению с прямым доступом к $this->args - не нужно проверять наличие аргумента.

$options (array): опции

В этом массиве указываются возможные опции и их значения по умолчанию. Если в настройках парсера указываются другие опции для тега, они накладываются поверх этих.

class MyTag exnteds \axy\ml\tags\Base
{
    protected $options = [
        'one' => 1,
        'two' => 2,
    ];
}

$parser = new Parser(null, [
    'mytag' => [
        'classname' => '\my\ns\MyTag',
        'options' => [
            'two' => 22,
            'three' => 3,
        ],
    ],
]);

Итоговые опции:

[
    'one' => 1,
    'two' => 22,
    'three' => 3,
]

$context (array): глобальный контекст

Объект, содержащий следующие поля:

  • result - текущий объект результата. Уже содержит в себе мета-данные, заголовки и токены. Не рекомендуется трогать в нём свойства html и plain.
  • options - глобальные настройки используемые разборщиком. Объект, где настройки доступны, как read-only свойства.
  • tags - список доступных тегов (см. ниже).
  • custom - пользовательский контекст (см. ниже).
$context->tags

Объект, из полезных методов - create($name, $content, $context).

Внутри своего тега можно создать экземпляр другого и использовать его вывод.

  • $name - имя тега.
  • $content - содержимое тега (для тега [name:arg value] это будет :arg value).
  • $context - следует не забыть передать $this->context.
$img = $this->context->tags->create('img', ' /i/a.png', $this->context);
return $img->getHTML();
$context->custom

Пользовательский контекст можно использовать для передачи каких-то элементов системы. Например, наш тег выводит что-то из БД, подключение к ней можно передать через эти настройки.

$customContext = [
    'db' => $db,
];
$parser = new Parser(null, null, $customContext);

class MyTag exnteds \axy\ml\tags\Base
{
    public function getHTML() 
    {
        return $this->context->custom['db']->query('SELECT ...');
    }
}

$name (string): имя тега

Может быть полезно, если один класс обслуживает несколько тегов.

$value (string): значение тега

Текст из содержимого тега, кроме аргументов (если они используются).

$errors (array): ошибки

Если содержимое тега имеет неверный формат, ошибки можно складывать сюда. Просто порядковый массив сообщений.

protected function parse()
{
    if (!isset($this->args[0])) {
        $this->errors[] = 'Arguments is empty';
    }
}

escape(string $text):string

Метод, экранирующий текст в соответствии с глобальной опцией escape.

Следует не забывать экранировать HTML.

return '<a href="'.$this->escape($this->url).'">'.$this->escape($caption).'</a>';

getNextComponent(void):string и getLastComponent(void):string

Считывают очередной и, соответственно, последний компоненты значения.

Например, тег: [MyTag:arg one "two three" four five].

$this->getNextComponent(); // one
$this->getNextComponent(); // two three
$this->getLastComponent(); // four five

Если компонентов не осталось, возвращают пустую строку.

Вырезают компоненты из $value, так что считать таким образом структуру тега можно только один раз.

shouldSplitBlock(void):boolean и $splitBlock

Метод shouldSplitBlock() возвращает указание на то, следует ли разбивать блок по этому тегу.

Например: This is code: [code 2 + 2]. Это строчный тег (<code>), блок не разбивается и выводится один абзац.

Или:

This is code:
[[[code
$x = 1;
$y = $x + 2;
]]].

Здесь уже блочный код (<pre>, он разорвёт текущий блок):

<p>This is code:</p>

<pre>
[[[code
$x = 1;
$y = $x + 2;
]]]
</pre>

<p>.</p>

По умолчанию $splitBlock=FALSE (блок не разрывается). shouldSplitBlock() возвращает $this->splitBlock.

Если блок следует разорвать, переопределяется либо метод, либо значение свойства.

shouldCreateBlock(void):boolean и $createBlock

Вызывается для тега, если он оказывается единственным в блоке. По умолчанию для такого тега создаётся абзац.

[url http://example.loc/ Link]

[code 2 + 2]

[code
x = 1;
y = x + 2;
]

[<div>
Text
</div>]

Результат:

<p>[url http://example.loc/ Link]</p>

<p>[code 2 + 2]</p>

<pre>
x = 1;
y = x + 2;
</pre>

<div>
Text
</div>

Для ссылки создался абзац, для строчного кода тоже, для блокового кода нет. Для html абзац никогда не создаётся.

parse(void):void

Вызывается из конструктора. Здесь следует определить основные действия по разбору тега.

getHTML(void):string

Вызывается при отрисовке документа. Здесь следует скомпоновать вёрстку из уже разобранных данных.

getPlain(void):string

Возвращает plain-текст, обычно используемый для поисковых движков. По умолчанию переадресовывает на getHTML(), но можно определить что-нибудь более подходящее. Обычно, не нужно выводить никакие HTML-теги и другие оформительские штучки, просто голый текст.

Clone this wiki locally