Мы напишем простенький плагин, который будет использовать событие "onBeforeCompileHead". Это событие типа "system", которое появилось в версии Joomla 1.6, и позволяет нам изменять HTML-элемент head непосредственно перед его рендерингом. Таким образом, мы можем изменить любой HTML-элемент, который находится в head: meta, link или script.

Что будет делать наш плагин?

Событие "onBeforeCompileHead" вызывается в методе fetchHead() класса JDocumentRendererHtml. Этот метод читает информацию для HTML-элемента head из объекта документа и выводит её в буфер в HTML формате. Следующий код вызывает это событие:
// Trigger the onBeforeCompileHead event
$app = JFactory::getApplication();
$app->triggerEvent('onBeforeCompileHead');


Если мы посмотрим в исходный код HTML-страницы, то увидим неколько элементов meta внутри элемента head:
<meta name="robots" content="index, follow" />
<meta name="keywords" content="My keywords." />
<meta name="rights" content="My rights." />
<meta name="language" content="en-GB" />

 Наш плагин будет добавлять мета-тег "revised", основываясь на параметре, который пользователь введет для плагина. Например, вывод нашего плагина может выглядеть следующим образом:

 
<meta name="revised" content="Dmitry Rekun, 16 октября 2012" />

где атрибут "content" - это текст, который указан в параметре плагина.

Чтобы этого достичь, нам необходимо понять, каким образом объект JDocumentHTML сохраняет данные для HTML-элемента head. Давайте проведем небольшое расследование.

В методе fetchHead() класса JDocumentRendererHead (где вызывается событие "onBeforeCompileHead"), мы видим, что переменная $document находится в сигнатуре метода. Это объект JDocumentHTML, у которого есть метод getHeadData(), который возвращает head-данные для документа или страницы. Если мы добавим команду var_dump($document->getHeadData()); в метод fetchHead() (например, непосредственно перед кодом, который вызывает событие), а потом посмотрим на страницу, то увидим длинный дамп вывода getHeadData(). Частью этого дампа будет следующее:

array
'title' => string 'Home' (length=4)
'description' => string 'My description.' (length=15)
'link' => string '' (length=0)
'metaTags' =>
           array
           'http-equiv' =>
                       array
                       'content-type' => string 'text/html' (length=9)
           'standard' =>
                       array
                       'robots' => string 'index, follow' (length=13)
                       'keywords' => string 'My keywords.' (length=12)
                       'rights' => string 'My rights.' (length=10)
                       'language' => string 'en-GB' (length=5)



Если мы сравним это с HTML кодом, который был показан ранее, мы увидим, что элементы meta с атрибутами "name" хранятся в объекте в качестве ассоциативного массива внутри элемента "standard", который находится внутри элемента "metaTags". Значение атрибута "name" является ключом (например, "robots"), а значение атрибута "content" является значением (например, "index, follow").

Мы хотим, чтобы наш плагин добавлял новый мета-тег "revised" и его значением должен быть текст, который введет пользователь в форме "Менеджера плагинов". Мы хотим сохранить существующие мета-теги и добавить только новый.

Итак, алгоритм работы нашего плагина кода будет следующим:

  1. Прочитать существующие head-данные из документа. Это будет массив, который упоминался выше.
  2. Добавить элемент к ассоциативному массиву, который хранится в элементе "standard" внутри элемента "metaTags". Ключом для этого элемента будет "revised", а значением будут данные, которые пользователь ввел для параметра.
  3. Записать измененный массив в объект документа, используя метод setHeaderData() (по сути, он является зеркальным отражением метода getHeaderData()).
  4. Мы хотим это сделать только тогда, когда есть какие-то данные в параметре плагина. Если данных нет, то ничего не делаем.

Создаем установочный файл (файл манифеста)

Давайте не будем усложнять и назовем наш плагин просто - My Meta.

Создайте для него новую папку (например mymeta), а внутри неё создайте пустой файл index.html и файл mymeta.xml со следующим содержимым:

<?xml version="1.0" encoding="utf-8"?>
<extension version="2.5" type="plugin" group="system" method="upgrade">
    <name>PLG_SYSTEM_MYMETA</name>
    <author>Ваше имя</author>
    <creationDate>Дата создания</creationDate>
    <copyright>Информация о копирайте</copyright>
    <license>Информация о лицензии</license>
    <authorEmail>Ваш адрес электронной почты</authorEmail>
    <authorUrl>Ваш сайт</authorUrl>
    <version>1.0.0</version>
    <description>PLG_SYSTEM_MYMETA_XML_DESCRIPTION</description>
 
    <files>
        <filename plugin="mymeta">mymeta.php</filename>
        <filename>index.html</filename>
        <folder>language</folder>
    </files>
 
    <config>
        <fields name="params">
            <fieldset name="basic">
                <field name="revised" type="text"
                    description="PLG_SYSTEM_MYMETA_FIELD_REVISED_DESC"
                    label="PLG_SYSTEM_MYMETA_FIELD_REVISED_LABEL"
                    filter="string"
                    default=""
                    size="50"
                />
            </fieldset>
        </fields>
    </config>
</extension>



Обратите внимание на строку:

 
<extension version="2.5" type="plugin" group="system" method="upgrade">

Атрибут "group" указывает на тип нашего плагина. Это значит, что после установки он будет размещен в директории plugins/system.

Также мы создали элемент fields с атрибутом "name", значение которого равно "params". Внутри мы расположили элемент fieldset "basic", который содержит необходимое нам поле. Все это находится внутри элемента config.

Если бы мы не создали элемент fields с атрибутом "name", то не имели бы возможности редактировать параметры плагина. Все дело в том, что для формы редактирования плагина используется файл разметки (administrator/components/com_plugins/views/plugin/tmpl/edit_options.php), который ищет элемент fields с именем "params" и включает содержащиеся в нем элементы fieldset в качестве опций формы.

Внутри элемента fieldset мы определили текстовое поле "revised". Таким образом, пользователь сможет указать свое значение для этого параметра. С помощью filter="string" мы вводим ограничение на допустимые символы в тексте. Фильтрация производится с помощью метода clean() класса JFilterInput.

Файл манифеста готов. Настало время написать непосредственно код плагина.

Создаем код плагина

Создайте в папке mymeta файл mymeta.php со следующим содержимым:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
/**
* Тестовый MyMeta плагин.
*/
class plgSystemMyMeta extends JPlugin
{
    function onBeforeCompileHead()
    {
        if ($this->params->get('revised')) 
        {
            $document = JFactory::getDocument();
            $headData = $document->getHeadData();
            $headData['metaTags']['standard']['revised'] = $this->params->get('revised');
            $document->setHeadData($headData);
        }
    }
}




Мы назвали наш класс plgSystemMyMeta согласно имеющемуся соглашению по именованию плагинов:

 
"plg" + <тип плагина> + <имя файла плагина>

В классе мы создали метод с названием onBeforeCompileHead() и его название в точности совпадает с названием события, на которое мы ориентируемся. Код метода довольно прост для понимания, так как мы уже разобрались со структурой массива метода getHeadData():

  1. Сначала мы проверяем, есть ли что-то в параметре "revised" нашего плагина. Если нет, то пропускаем обработку. К параметрам плагина мы обращаемся через свойство $params. Это объект типа JRegistry, в котором хранятся параметры плагина.
  2. Если что-то есть, то обрабатываем. Мы получаем объект документа и сохраняем результаты метода getHeadData() в переменной $headData.
  3. Мы создаем новый элемент ассоциативного массива под именем "revised" и устанавливаем его значение равным значению параметра плагина. Обратите внимание, наш элемент включен в массив, который в свою очередь включен в ещё один массив. Это мы видели в дампе вывода getHeadData().

Добавляем языковые файлы

Последним шагом перед проверкой нашего плагина будет добавление языковых файлов. Вспомните наш файл манифеста:

<files>
           <filename plugin="mymeta">mymeta.php</filename>
           <filename>index.html</filename>
           <folder>language</folder>
</files>



Элемент folder указывает на то, что в папке нашего плагина дожна быть подпапка "language".

Когда мы создаем плагин, мы можем выбрать: расположить языковые файлы в папке плагина или в папке adminstrator/languages. Для расширений рекомендуется располагать все файлы расширения отдельно от базовых файлов Joomla, поэтому языковые файлы расширения также предпочтительно располагать в папке расширения. Будем придерживаться этой практики и создадим папку language внутри папки mymeta. Внутри папки language создадим ещё две подпапки для каждого из языков: en-GB и ru-RU. Не забудьте разместить в них пустой файл index.html.

В нашем примере у нас будет четыре языковых файла, по два для каждого из языков:

en-GB.plg_system_mymeta.ini
en-GB.plg_system_mymeta.sys.ini

Будут располагаться в mymeta/language/en-GB.

ru-RU.plg_system_mymeta.ini
ru-RU.plg_system_mymeta.sys.ini

Будут располагаться в mymeta/language/ru-RU.

После установки плагина они будут располагаться в plugins/system/mymeta/language/en-GB/ и plugins/system/mymeta/language/ru-RU/ соответственно.

Обратите внимание на то, что наименование языковых файлов тоже придерживается соглашения именования плагинов.

Файл plg_system_mymeta.ini является главным языковым файлом и содержит языковые строки, которые будут использоваться во время выполнения кода плагина, а также тогда, когда плагин будет открыт для изменения в Менеджере плагинов.

Содержимое файла en-GB.plg_system_mymeta.ini:

 
PLG_SYSTEM_MYMETA_FIELD_REVISED_LABEL="Revised сontent"
PLG_SYSTEM_MYMETA_FIELD_REVISED_DESC="Meta revised text for content attribute."

Содержимое файла ru-RU.plg_system_mymeta.ini:

 
PLG_SYSTEM_MYMETA_FIELD_REVISED_LABEL="Содержимое revised"
PLG_SYSTEM_MYMETA_FIELD_REVISED_DESC="Текст для атрибута content meta-элемента revised."

Файл с .sys в названии используется для перевода имени, когда его просматривают в списке Менеджера расширений или в списке Менеджера плагинов. Также мы размещаем описание нашего плагина в этом файле для того, чтобы перевести описание в сообщении, которое отображается при установке плагина.

Содержимое файла en-GB.plg_system_mymeta.sys.ini:

 
PLG_SYSTEM_MYMETA="System - My Meta"
PLG_SYSTEM_MYMETA_XML_DESCRIPTION="Adds meta element with the name revised."

Содержимое файла ru-RU.plg_system_mymeta.sys.ini:

 
PLG_SYSTEM_MYMETA="Система - My Meta"
PLG_SYSTEM_MYMETA_XML_DESCRIPTION="Добавляет meta-элемент c именем revised."

Подробнее об использовании языковых файлах в расширениях вы можете прочитать в статье "Создание компонента для Joomla 2.5 - языковые файлы".

Все - теперь наш плагин полностью готов. Давайте протестируем его работу.

Тестируем плагин

Запакуйте содержимое папки mymeta в архив (zip, tar, tar.gz, bz2) или скачайте его напрямую с нашего сайта и установите, используя Менеджер расширений.

Зайдите в "Расширения – Менеджер плагинов" и в фильтре "- выбор типа -" выберите "system". В списке вы должны увидеть наш плагин "Систем – My Meta". Кликните на него, и вы попадете в редактирование параметров плагина:

sozdanie plagina edit screen
Измените состояние плагина на "Включено", введите текст для содержимого "revised" и сохраните. Теперь пройдите на главную страницу и просмотрите исходный код с помощью браузера. Вы увидите что-то похожее на это:

 
<meta name="robots" content="index, follow" />
<meta name="keywords" content="My keywords." />
<meta name="rights" content="My rights." />
<meta name="language" content="en-GB" />
<meta name="revised" content="Dmitry Rekun, 16 октября 2012 года" />
<meta name="description" content="My description." />

Мы видим, что мета-тег "revised" присутствует в списке мета-тегов. В качестве финального теста, вернитесь в "Менеджер плагинов" и сотрите содержимое параметра "revised". Теперь сделайте рефреш страницы и проверьте исходный код. Мета-тег с именем "revised" должен был пропасть, так как мы стерли его содержимое в параметрах плагина.

Поздравляю! Вы успешно справились с созданием собственного плагина для Joomla 2.5. В следующей части мы рассмотрим, каким образом можно переопределить базовые классы Joomla с помощью плагина.

{phocadownload view=file|id=151|target=s}