Опубликован: 02.10.2012 | Доступ: свободный | Студентов: 1916 / 85 | Длительность: 11:48:00
Теги: joomla, mvc, php, xhtml, xml
Лекция 8:

Файл-манифест

Аннотация: Рассмотрена структура файла-манифеста. Приведен практический пример создания установочного пакета для модуля и для компонента.

Цель лекции: Изучить структуру файла-манифеста и процесс создания установочных пакетов для модулей и компонентов.

Структура манифеста

Для каждого расширения Joomla может существовать файл-манифест. Манифест - это файл XML, содержащий метаданные о расширении, данные для установки и/или описание его настроек. Манифест должен называться <имя расширения>.xml и находиться в корневой директории установочного пакета.

Иерархия элементов в манифесте приведена на рис. 8.1.

Иерархия элементов в файле-манифесте

увеличить изображение
Рис. 8.1. Иерархия элементов в файле-манифесте

Корневым тегом манифеста является тег <extension></extension>. Он может иметь следующие атрибуты:

type - тип расширения: component, file, language, library, module, package, plugin;
version - версия Joomla, для которой написано расширение: 1.6, 2.5 и т.д.;
method - будут ли при установке перезаписаны файлы расширения, если они уже существуют: upgrade (да), new (сообщить в таком случае об ошибке);
client - для модулей: задает, предназначен этот модуль для бэкенда (administrator) или фронтенда (site);
group - для плагинов: группа.

Внутри тега <extension> в первую очередь обычно задаются метаданные: <name>, <author>, <copyright>, <license>, <authorEmail>, <authorUrl>, <version>, <description>, однако их можно опустить.

Элемент <scriptfile> задает PHP-скрипт, который будет выполнен до, во время и/или после установки, удаления или обновления расширения. Этот скрипт должен содержать класс <префикс><имя расширения>IntallerScript, где префикс зависит от типа расширения (com_, mod_ и т.д.). Данный класс должен содержать следующие public-методы:

__constructor(JAdapterInstance $adapter);
bool preflight(string $route, JAdapterInstance $adapter);
bool postflight(string $route, JAdapterInstance $adapter);
bool install(JAdapterInstance $adapter);
bool update(JAdapterInstance $adapter);
bool uninstall(JAdapterInstance $adapter);
    

где

adapter - объект, отвечающий за запуск этого скрипта;
$route - какое событие происходит: install, uninstall, discover_install. Событие discover_install происходит при поиске расширений из менеджера расширений в панели управления (эта функция Joomla позволяет установить расширения, файлы которых предварительно были загружены на сайт вручную).

Методы preflight() и postflight() будут вызваны соответственно до и после установки/удаления/обновления расширения.

Элементы <install> и <uninstall> задают SQL-скрипты, которые должны быть выполнены при установке и удалении расширения. Таким путем в базе данных создаются таблицы, хранящие данные, использующиеся расширением. Атрибут folder задает папку, в которой находятся эти скрипты в установочном пакете, например, "admin". В эти элементы должен быть вложен элемент <sql>, содержащий по одному элементу <file> для каждого файла SQL. Атрибуты тега <file>: driver - драйвер базы данных и charset - кодировка базы данных. Например:

<install>
  <sql>
    <file driver="mysql" charset="utf8">sql/install.sql</file>
  </sql>
</install>
<uninstall>
  <sql>
    <file driver="mysql" charset="utf8" folder="sql">sql/uninstall.sql</file>
  </sql>
</uninstall>
    

Элемент <files> задает список файлов, которые должны быть скопированы при установке расширения в соответствующую директорию во фронтенде. Для каждого файла добавляется вложенный элемент <filename>, для каждой папки - <folder>, причем содержимое папки уже не описывается. Пример для типичного компонента MVC:

<files folder="site">   <folder>models</folder>   <folder>views</folder>
  <folder>controllers</folder>
  <filename>mycomponent.php</filename>   <filename>router.php</filename>
</files>
    

Языковые файлы описываются внутри элемента <languages>. В установочном пакете эти файлы должны находиться в папке /language/<код языка>. Для каждого из них создается вложенный элемент <language> с атрибутом tag, содержащим код языка в формате <ln-LN>:

<languages folder="site">
         <language tag="ru-RU">language/ru-RU/ru-RU.com_mycomponent.ini</language>
</languages>
    

Медиа-файлы - изображения, файлы Javascript и CSS, флэш - описываются внутри элемента <media>. Атрибут destination задает название папки, в которую будут скопированы перечисленные файлы. Эта папка должна находиться внутри папки /media в корне сайта. Если она не существует, то будет создана при установке расширения.

<media destination="com_mycomponent">
  <folder>css</folder>
  <folder>images</folder>
  <folder>js</folder>
  <filename>pic1.jpg</filename>
</media>
    

Файлы-манифесты компонентов могут включать элемент <administration>. Он содержит такие же элементы <languages> и <files>, как и описанные ранее, а также элементы для описания меню компонента в панели управления: <menu> и <submenu>.

Элемент <menu>, вложенный непосредственно в <administration>, описывает пункт в меню "Компоненты", ссылающийся на главную страницу бэкенда компонента. Атрибутом может быть img - относительный путь к пиктограмме пункта меню (по умолчанию будет присвоено значение "class:component").

Элемент <submenu> может содержать несколько вложенных элементов <menu>, описывающих подпункты этого пункта меню. У таких вложенных тегов <menu> может быть несколько атрибутов, среди которых в первую очередь отметим img и link - ссылка, переход по которой произойдет при щелчке на данном пункте меню. Если ссылка задана, то итоговый URL будет сформирован как index.php?<ссылка>. Если же атрибут link не задан, то установщик проверит наличие следующих атрибутов этого же тега: act, task, controller, view, layout, sub и добавит к строке "index.php?option=com_<имя компонента>&" соответствующие пары "имя-значение", разделенные амперсандом. Например, следующие элементы описывают пункт меню с одной и той же ссылкой index.php?option=com_mycomponent&task=edit:

<menu task="edit">COM_MYCOMPONENT_EDIT</menu>
<menu link="option=com_mycomponent&task=edit">COM_MYCOMPONENT_EDIT</menu>
    

Текст пункта меню задается внутри тега <menu> и обязательно должен быть ключом, значение которого должно быть переведено в языковом файле, обычно - /administrator/languages/<код языка>/<код языка>.com_<имя компонента>.sys.ini.

Элемент <config> описывает настройки расширения. Обратите внимание, что для компонентов этот элемент должен находиться не в файле-манифесте, а в отдельном файле config.xml в корневой директории бэкенда компонента. Для модулей <config> располагается в файле-манифесте и вложен в тег <extension>.

В <config> может быть вложен элемент <fields>. Его атрибут addfieldpath позволяет задать папку, в которой находится файл, определяющий собственный тип поля.

В <fields> или непосредственно в <config> вложен элемент <fieldset>, соответствующий HTML-элементу <fieldset>. Каждый <fieldset> - это группа элементов формы редактирования свойств расширения, например: "Основные настройки", "Расширенные настройки" и т.д. Атрибут name задает имя этого элемента, label - отображаемый текст.

Вложенные в <fieldset> элементы <field> задают поля формы. Каждый <field> соответствует одной настройке расширения. Допустимые атрибуты:

name - имя
type - тип
default - значение по умолчанию
label - текст, который будет выводиться рядом с соответствующим элементом управления на форме
description - описание, которое будет выводиться во всплывающей подсказке.

Некоторые стандартные типы полей:

calendar - текстовое поле, рядом с которым выводится пиктограмма для вывода календаря;
category - выпадающий список категорий;
editors - выпадающий список доступных WYSIWYG-редакторов;
filelist - выпадающий список файлов из заданной директории;
folderlist - выпадающий список папок из заданной директории;
imagelist - выпадающий список файлов изображений из заданной директории;
languages - выпадающий список установленных языковых файлов фронтенда или бэкенда;
list - выпадающий список каких-либо строк;
password - поле для ввода пароля;
radio - переключатель;
spacer - разделитель;
sql - выпадающий список элементов, полученных в результате выполнения заданного SQL-запроса;
text - текстовое поле;
textarea - многострочное текстовое поле;
timezones - список часовых поясов.

Для списков и переключателей в тег <field> должны быть вложены несколько элементов <option>, задающих значения, из которых пользователь может выбрать.

Например, так описывается выпадающий список для выбора порядка сортировки - по возрастанию или по убыванию:

<field name="entries_order" type="list" 
default="DESC" 
label="COM_MYCOMPONENT_ENTRIES_ORDER" description="COM_MYCOMPONENT_ENTRIES_ORDER_DESC">
  <option value="DESC">COM_MYCOMPONENT_ENTRIES_ORDER_DESC</option>
  <option value="ASC">COM_MYCOMPONENT_ENTRIES_ORDER_ASC</option>
</field>
    

Для таких элементов, как filelist, folderlist, imagelist, вложенные элементы <option> не нужны, т.к. список значений определяется исходя из атрибутов этих тегов. Например, выпадающий список для выбора одного из доступных WYSIWYG-редакторов описывается так:

<field name="editors" type="editors" label="COM_MYCOMPONENT_EDITOR" />
    

Для создания собственного типа поля необходимо создать файл <имя типа>.php и в нем описать класс, производный от одного из классов подпакета Form: JFormFieldList, JFormFieldMedia и др. (полный список классов см. в документации). В классе должен быть перегружен метод родительского класса, отвечающий за вывод поля формы. Простой пример приведен в документации Joomla.

Практика

В таблицах #__extensions и #__modules, в которые мы добавляли записи о наших расширениях, есть поле params, позволяющий хранить значения параметров. Например, для модуля mod_myquestions в этом поле хранится значение наподобие {"random":"0","items":"3","maxlen":"100","author":"1","date":"1"}. Нетрудно заметить, что данная строка представляет собой совокупность пар "ключ - значение". Таким образом, заданные значения настроек расширений сохраняются в базе данных. Наша задача - предоставить администратору сайта интерфейс для изменения этих значений.

Кроме того, мы создадим установочные пакеты для модуля и для компонента, представляющие собой ZIP-архивы определенной структуры.

Манифест для компонента

Настройки компонента

Зададим два параметра компонента myquestions - адреса электронной почты администратора сайта и эксперта.

Создайте файл /administrator/components/com_myquestions/config.xml:

  <?xml version="1.0" encoding="utf-8"?> 
<config>
   <fieldset name="component" label="COM_MYQUESTIONS_FIELDSETCONFIG_LABEL"
      description="COM_MYQUESTIONS_FIELDSETCONFIG_LABEL_DESC">
   <field name="email_admin" type="text" label="COM_MYQUESTIONS_FIELD_EMAILADMIN_LABEL"
      description="COM_MYQUESTIONS_FIELD_EMAILADMIN_LABEL_DESC" default="admin@mysite.ru"/>
   <field name="email_expert" type="text" label="COM_MYQUESTIONS_FIELD_EMAILEXPERT_LABEL"
      description="COM_MYQUESTIONS_FIELD_EMAILEXPERT_LABEL_DESC" default="expert@mysite.ru"/>
  </fieldset>
</config>
            

Добавьте в файл /administrator/language/ru-RU/ru-RU.com_myquestions.ini код:

COM_MYQUESTIONS_CONFIGURATION="Настройки системы &laquo;вопрос &ndash; ответ&raquo;"
COM_MYQUESTIONS_FIELDSETCONFIG_LABEL="Настройки системы"
COM_MYQUESTIONS_FIELDSETCONFIG_LABEL_DESC="Настройки системы"
COM_MYQUESTIONS_FIELD_EMAILADMIN_LABEL="E-mail администратора"
COM_MYQUESTIONS_FIELD_EMAILADMIN_LABEL_DESC="На этот адрес 
будут приходить уведомления о новых вопросах, и с этого адреса будут отправляться 
уведомления экспертам и пользователям"
COM_MYQUESTIONS_FIELD_EMAILEXPERT_LABEL="E-mail эксперта"
COM_MYQUESTIONS_FIELD_EMAILEXPERT_LABEL_DESC="На этот адрес будут 
приходить уведомления о новых вопросах, отправленные модератором"
            

Для отображения в панели инструментов кнопки "Настройки" используется метод JToolBarHelper::preferences(). Измените функцию TOOLBAR_myquestions::_DEFAULT() в файле /administrator/components/com_myquestions/toolbar.myquestions.html.php следующим образом:

function _DEFAULT()
  {
    JToolBarHelper::title(JText::_('COM_MYQUESTIONS_TOOLBAR_TITLE'), 'generic.png');
    JToolBarHelper::editList('reply','COM_MYQUESTIONS_REPLY');
    JToolBarHelper::deleteList(JText::_('COM_MYQUESTIONS_TOOLBAR_REMOVE_QUESTIONS_CONFIRMATION'));
    JToolBarHelper::preferences('com_myquestions');
  }
            

Теперь на панели инструментов над списком вопросов появилась кнопка "Настройки", при нажатии на которую выводится окно, в котором можно задавать значения настроек компонента ( рис. 8.2).

Кнопка "Настройки" в панели инструментов

увеличить изображение
Рис. 8.2. Кнопка "Настройки" в панели инструментов

Внесем изменения в код компонента, чтобы использовать значения настроек. Измените код функции QuestionController::send() в файле /administrator/components/com_myquestions/controller.php следующим образом:

$mailer =& JFactory::getMailer();
  $params = JComponentHelper::getParams($option);
  $mailer->setSender($params->get('email_admin','admin@mysite.ru'));
  if ($task == 'sendToExpert')
  {
    $mailer->addRecipient($params->get('email_expert','expert@mysite.ru'));
    $mailer->setSubject(JText::_('COM_MYQUESTIONS_NEW_QUESTION'));
    $mailer->setBody(JText::sprintf('COM_MYQUESTIONS_EMAIL_EXPERT_BODY',$q));
  }
            

С помощью метода JComponentHelper::getParams() мы получаем объект JParameter, а затем используем его метод get() для получения параметров, задавая значения по умолчанию.

Изменим также код фронтенда. Откройте файл /components/com_myquestions/controller.php и измените функцию QuestionController::addQuestion() следующим образом:

…
    $mailer =& JFactory::getMailer();
    $option = JRequest::getVar('option','com_myquestions');
    $params = JComponentHelper::getParams($option);
    $mailer->setSender($params->get('email_admin','admin@mysite.ru'));
    $mailer->addRecipient($params->get('email_admin','admin@mysite.ru'));
…
            

Задайте с помощью кнопки "Настройки" собственные значения адресов электронной почты администратора сайта и эксперта. Добавьте на сайт вопрос, отправьте уведомление о нем эксперту, об ответе - автору вопроса и убедитесь, что в папке <путь к Денверу>/tmp/!sendmail появилось три письма с заданными вами значениями адресов электронной почты в соответствующих полях.

Кирилл Гусаров
Кирилл Гусаров

В разделе "Первые папки и файлы. Добавление пунктов меню"

предлагается создать две файла:

- myquestions.php;

- admin.myquestions.php

с соответствуюшими адресами:

/components/com_myquestions/myquestions.php;

- /administrator/components/com_myquestions/admin.myquestions.php;

Так вот, при создании файла "admin.myquestions.php" В админке выдает ошибку - "Компонент не найден", а при переименовании его на  "myquestions.php" в последующем шаге, в админке не выводятся кнопки редактирования. 
Проверил кодировку, проверил правильность пути к файлам, пересохранил указанный код. Скажите что я делаю не так или в чем может быть причина?