Разработка расширений
- Обзор
- Правила именований
- Базовый класс расширения
- Активация и обновления
- Отключение
- Настройка
- Вызов из вне расширения
- Разные расширения, другие хуки
- Библиотека хуков расширений
Обзор
С приходом ExpressionEngine 1.4 появилась возможность переписывать и изменять внутреннюю работы программы. В ExpressionEngine это то что известно как 'хуки'; маленькие фрагменты кода в более чем 100 местах которые позваляют вызвать сторонние скрипты. Расширения могут изменить целую страницу панели управления, добавить/удалить функциональность, и изменить внешний вид отдельных элементов страницы. Расширения позволяют сторонних разработчиков изменять аспекты ExpressionEngine без хуков в стандартных скриптах. Вы можете считать, что расширение как плагины, но в отличие от плагина, расширение не используется для ваших шаблонов, вместо этого оно позваляет изменить саму систему.
Расширение представляет собой отдельный скрипт который находится в /system/extensions/ директории и включается в Менеджере расширений в панели управления. Расширение может иметь свои собственные настройки и собственные базы данных таблицы, в случае необходимости, но не является необходимой. Если настройки доступны для расширения, языковой файл не требуется, но в отличие от модуля нет панели управления для расширений.
Правила именований
Расширения имеют аналогичные именования как в ExpressionEngine плагинах, так что разработчики поймут смысл быстро. Существует только один файл, необходимый для расширения и внутри этого файла должен быть PHP класс. Название класса используется в имени файла расширения, имя файла должно быть в нижнем регистре. Имя класса содержит префикс 'ext.' и стандартную php приставку '.php'. Итак, если у нас есть вызов класса 'Example_extension', то имя файла расширения будет 'ext.example_extension.php'.
Внутри расширения
Внутри файла расширения должен быть класс, который будет вызываться ExpressionEngine когда потребуется это расширение. Конструктор для класса требует один параметр, который будет получать настройки для расширения и установить класс переменной.
class Example_extension { var $settings = array(); // ------------------------------- // Constructor - Extensions use this for settings // ------------------------------- function Example_extension($settings='') { $this->settings = $settings; } // END } // END CLASS
Кроме переменной $settings, есть ещё пять других переменных которые у вас должны быть. Эти переменные вывода мета-информации о Ваших расширений к менеджеру расширений, чтобы его можно описать ваши расширения, предоставить документацию, а также обновить параметры (если таковые имеются).
class Example_extension { var $settings = array(); var $name = 'Example Extension'; var $version = '1.0.0'; var $description = 'Our example extension'; var $settings_exist = 'n'; var $docs_url = '';//'http://expressionengine.com'; // ------------------------------- // Constructor - Extensions use this for settings // ------------------------------- function Example_extension($settings='') { $this->settings = $settings; } // END } // END CLASS
Если ваше расширение имеет языковой файл, то $name и $description переменные должны быть указаны в конструкторе для вызова языкового файла и переменных используя Языковой ($LANG) класс. Если расширение может быть использовано и на международном уровне, не английскими пользователями это является рекомендуемым действием.
Активация и обновления
Существуют два метода требуется для вашего класса расширения, которые контролируют активацию и обновление вашего расширения. Наиболее важной является функция активации расширения в ExpressionEngine. Чтобы включить расширение, вы просто выполняете запрос в базу данных с разной информацией, как хуки расширения и имя метода в вашего расширения класса для вызова этого хука.
// -------------------------------- // Activate Extension // -------------------------------- function activate_extension() { global $DB; $DB->query($DB->insert_string('exp_extensions', array( 'extension_id' => '', 'class' => "Example_extension", 'method' => "rewrite_admin_home", 'hook' => "admin_home_page_start", 'settings' => "", 'priority' => 10, 'version' => $this->version, 'enabled' => "y" ) ) ); } // END
Здесь короткий список того что означают поля в таблице базы данных:
- extension_id - первичный id для строки в таблице
- class - имя вашего класса расширения
- method -метод вызова для данного расширения хуком
- hook - имя хука расширения в вашей программе
- settings - сериализованный массив параметров, как правило, пустой по умолчанию
- priority - у расширения может быть много хуков, по этому им нужен приоритет. 1 => первый, 10 => последний.
- version - версия для расширения, когда активируется, используется для обновления
- enabled - если ваше расширение активировано
Обновлять расширения очень легко в ExpressionEngine. Пользователь просто загружает новую версию расширения и ExpressionEngine автоматически обновит расширение в следующий раз, когда оно будет вызвано. Все что требуется, это специальная Функция под называнием update_extension(). Программа автоматически сравнивает версии расширений информации в базе данных в отношении версии расширения файла, а Если расширение файла новой версии он вызывает эту функцию.
// -------------------------------- // Update Extension // -------------------------------- function update_extension($current='') { global $DB; if ($current == '' OR $current == $this->version) { return FALSE; } if ($current < '1.0.1') { // Update to next version 1.0.1 } if ($current < '1.0.2') { // Update to next version 1.0.2 } $DB->query("UPDATE exp_extensions SET version = '".$DB->escape_str($this->version)."' WHERE class = 'Example_extension'"); } // END
Отключение
Когда расширение включается впервый раз, то вызывается функция activate_extension() и расширение делает запись в базу данных. Если расширение включается впервые, то запускается фукнкция activate_extension(). Когда расширение отключают, то расширение не удаляет вызовы из базы данных.
Это создает проблему для разработчиков, которые, разрабатывая расширение, часто тестируют код, проверяя все хуки расширения в функции activate_extension (). То, что мы сделали это позволило создание из disable_extension () в классе расширения. Если эта функция существует в классе, она будет вызываться, когда ваше расширение отключают. Это позволит вам выяснить основные данные вашего расширения и начать новые каждый раз.
// -------------------------------- // Отключение расширения // -------------------------------- function disable_extension() { global $DB; $DB->query("DELETE FROM exp_extensions WHERE class = 'Example_extension'"); } // END
Настройки
Общие настройки форм и обработки
Если вы хотите сделать вашему расширения возможность иметь настройки, то это делается очень легко. Первое, вы должны убедиться что в $settings_exist переменной класса указано 'y'. Второе, вам нужен языковой файл вашего расширения, имя языкового файла имеет имя расширения в нижнем регистре букв, начинается с профикса 'lang.' и оканчивается на '.php'. Созданный языковой файл переносится на директорию /system/language/. И наконец, вам нужен метод в ваш класс расширения, для вызова settings(). Эта функция возвращает массив в специальную форму которая поможет Extensions Manager автоматический создать форму ваших настроек.
// -------------------------------- // Настройки // -------------------------------- function settings() { $settings = array(); $settings['butter'] = "Quite Tasty"; $settings['buttery'] = array('r', array('yes' => "yes", 'no' => "no"), 'no'); // Complex: // [variable_name] => array(type, values, default value) // variable_name => short name for setting and used as the key for language file variable // type: t - textarea, r - radio buttons, s - select, ms - multiselect, f - function calls // values: can be array (r, s, ms), string (t), function name (f) // default: name of array member, string, nothing // // Simple: // [variable_name] => 'Butter' // Text input, with 'Butter' as the default. return $settings; } // END
Для примера была создана форма настроек с текстовым полем и переменной с именем 'butter' и по умолчанию указано значение "Not Tasty" и поле радио кнопки с именем переменнойf 'buttery' с возможными значениями "Yes" или "No" и стандартно "No".
Заметка о массиве второго поля, ключи используются как значения для для этого элемента, а значения будут текстом. Если вы хотите, значения ваших переменных должны быть как языковые переменные вашего расширения языкового файла и Extensions Manager сам автоматический вернёт их для вас.
Создание и обработка формы настроек
Если ваши настройки требуют специальную формукоторую не создать на специальном месте как выше, то ExpressionEngine позваляет вам создать свою форму настроек и функцию обработки в рамках вашего расширения. Сначало, вам нужно иметь метод в вашем классе расширениия, функция называется settings_form(). Эта функция создаёт форму и выводит в Панель управления. Работает эта функция как и любая другая страница созданная для ExpressionEngine панели управления, для создания используйте Display class и свой метод.
function settings_form($current) { global $DSP, $LANG, $IN; $DSP->crumbline = TRUE; $DSP->title = $LANG->line('extension_settings'); $DSP->crumb = $DSP->anchor(BASE.AMP.'C=admin'.AMP.'area=utilities', $LANG->line('utilities')). $DSP->crumb_item($DSP->anchor(BASE.AMP.'C=admin'.AMP.'M=utilities'.AMP.'P=extensions_manager', $LANG->line('extensions_manager'))); $DSP->crumb .= $DSP->crumb_item($this->name); $DSP->right_crumb($LANG->line('disable_extension'), BASE.AMP.'C=admin'.AMP.'M=utilities'.AMP.'P=toggle_extension_confirm'.AMP.'which=disable'.AMP.'name='.$IN->GBL('name')); $DSP->body = $DSP->form_open( array( 'action' => 'C=admin'.AMP.'M=utilities'.AMP.'P=save_extension_settings', 'name' => 'settings_example', 'id' => 'settings_example' ), array('name' => get_class($this)) ); $DSP->body .= $DSP->table('tableBorder', '0', '', '100%'); $DSP->body .= $DSP->tr(); $DSP->body .= $DSP->td('tableHeadingAlt', '', '2'); $DSP->body .= $this->name; $DSP->body .= $DSP->td_c(); $DSP->body .= $DSP->tr_c(); $DSP->body .= $DSP->tr(); $DSP->body .= $DSP->td('tableCellOne', '45%'); $DSP->body .= $DSP->qdiv('defaultBold', $LANG->line('log_table')); $DSP->body .= $DSP->td_c(); $DSP->body .= $DSP->td('tableCellOne'); $DSP->body .= $DSP->input_text('log_table', ( ! isset($current['log_table'])) ? '' : $current['log_table']); $DSP->body .= $DSP->td_c(); $DSP->body .= $DSP->tr_c(); $DSP->body .= $DSP->table_c(); $DSP->body .= $DSP->qdiv('itemWrapperTop', $DSP->input_submit()); $DSP->body .= $DSP->form_c(); }
Наконец, вам необходимо будет иметь метод в классе вашего расширения вызывающий save_settings (). Эта функция будет вызываться, когда ваш settings_form() представляется в форме метода. Используйте его для обработки данных отправки и ввода его в exp_extensions таблицы базы данных. Помните, что данные записаные в базу данных сериализованный массив, поэтому заполните их соответствующим образом.
Вызов расширения
Ниже приводится пример ExpressionEngine хук асширения, который доступен для использования:
// -------------------------------------------- // 'publish_form_start' hook. // - Allows complete rewrite of Publish page. // $edata = $EXT->call_extension('publish_form_start', $which, $submission_error, $entry_id); if ($EXT->end_script === TRUE) return; // // -------------------------------------------
Первый параметр $EXT->call_extension это имя хука, которое позваляет расширению класса знать какое расширение вызывать. Остальные три параметра являются переменными взяты из той функции, которую хук вкладывается внутри. Они предоставляют информацию и данные для начала вызова этого хука, который позваляет выполнять действия или манипулировать данными. Когда расширение вызывается, ExpressionEngine загружает файл расширения, экземпляр класса расширения, и затем вызовы метода подходящие для хука расширения как указано в расширении когда оно будет активировано (смотрите выше об активации).
Когда этот метод вызывается в классе расширения те три другие параметры будут направлены в метод автоматически. Вот что метод может выглядеть следующим образом:
function replace_entry_form($which, $submission_error, $entry_id) { global $DSP, $DB, $IN, $EXT; $EXT->end_script = TRUE; $DSP->body = 'New Entry Form Here'; }
Три параметра для хука расширения отображаются прямо на трех параметров вызываемого метода, и поэтому в ваших расширениях легко можете использовать эти параметры и делать то, что он должен делать. На ExpressionEngine.com Библиотека хуков расширений содержит записи всех хуков расширений и доступных параметров для вас, а также советы как использовать хуки расширений.
Несколько расширений, другие хуки
Когда вызывается хук расширения, ExpressionEngine проверяет базу данных и смотрит, есть ли расширения доступные для хука Если есть расширения, то они обрабатываются в порядке начиная с меньшего номера приоритета вызывающего расширение. Из-за преоритета, расширения могут помешать друг другу, по этому мы предоставили две переменные для помощи с этим.
$EXT->last_call
Здесь будут популярны хуки начинающие использовать несколько расширения и некоторые ждут от вас возвращение данных в хук расширения. Из-за этого, есть переменная доступа из класса Расширения ($EXT) что будет содержать полеченные данные любых расширений для этого хука Скажем, есть хук для форматирования текста и вызывается расширение перед вами. Это расширение будет возвращать форматированый текст, но ваше расширение вызывается с оригинальным текстом информации начала отправки. В таком случае данные возвращаются и доступны другим расширениям в переменной, в ней содержится уже отформатированый текст: $EXT->last_call. Эта переменная вернёт все последние возвращения для этого хука. Если не было расширения раньше, то значение переменной будет FALSE.
$EXT->end_script
Многие хуки расширения существуют специально для контроля страницы или скрипта в панели управления. Они предназначены для просмотра появления формы, или изменение хода работы скрипта для обработки данных формы. В тех случаях, когда вы хотите, чтобы ваше расширение было последним, и вызывов хуков больше небыло. $EXT->end_script существует исключение для этой цели. Если вы укажите значение TRUE, то как только ваше расширение завершит работу, исключение завершит хук.