Slyweb
На разработку сайта! Скидки 50%!

Создание дополнительного элемента формы к статье Joomla

jQuery и CSS

В этой статье будет рассказано о созаднии плагина, котрый объясняет возможности Joomla 2.5 создавать дополнительные поля формы к статьям. Для этого придётся создать отдельный плагин и утановить патч изменяющий компонент "Менеджер статей".

Функции создаваемого плагина:

  • Добавление дополнительного поля к статье в бакэнде сайта;
  • Добавление дополнительного поля к статье в фронтэнде сайта;
  • Сохранение данных вновь создаваемого поля в базе данных;
  • Вывод полей с использованием собственной разметки на страницах сайта (до вывода текста статьи);

Пример

Для примера у нас будут данные браться "структура", "температура", "вкус":

При этом данные будут доступны как в бакэнде так и во фронтэнде сайта.

Админ раздел

При этом данные будут доступны как в бакэнде так и во фронтэнде сайта.

Сайт

При этом данные будут доступны как в бакэнде так и во фронтэнде сайта.

Framework

В Joomla менеджер статей как бакэнде так и во фронтэнде сайта является обычным компонентом, при обработке формы происходят следующие действия:

  • Загрузка структуры формы в XML
  • Загрузка данных из базы
  • Вставка данных в поля формы
  • Отображение формы в HTML разметке

При сохранении фреймовик Joomla выполняет следующие действия:

  • Перехватывае отправляемые даннные
  • Загружает описание полей формы
  • Осуществляет валидацию полей формы и данных
  • При ошибки валидации сохраняет данные во временное состояние
  • Либо добавляет данные в базу

Фреймовик Joomla для каждого из указанных этапов предусматривает соотвтсвующие хуки:

onContentPrepareForm()

выполняется, когда происходит загрузка описания форм;

onContentPrepareData()

выполняется, когда происходит загрузка статьи из базы данных с заполнением полей формы;

onContentAfterSave()

выполняется, когда происходит сохраннеие данных в базу, этот хук будет использоваться для сохранения дополнительных данных в плагине в талицу #__user_profiles (автор);

onContentAfterDelete()

запускается когда происходит удаление статьи, этот хук будет использоваться для удаление дополнительных данных;

onContentPrepare()

запускается когда происходит отображение статьи (во фронтэнде(автор)), данный хук используется для отображение дополнительных данных;

База данных

Контент дополнительных полей статьи должен сохранятся в базу данных. Для этого можно использовать дополнительные таблица базы данных. В Joomla 2.5 можно расширять профиль пользователя дополнительными полями. Они сохраняются в таблицу " #__user_profiles". Данный плагин будет использовать таблицу #__user_profiles и столбцы "user_id" как "article_id".

При этом данные будут доступны как в бакэнде так и во фронтэнде сайта.

Структура нашего плагина:

  • Код
  • Чистый код
  • Копировать в буфер
  1.── plugins/content/rating
  2. ├── language
  3. │ └── en-GB
  4.     ├── en-GB.plg_content_rating.ini     [language file]
  5.     └── en-GB.plg_content_rating.sys.ini [language file]
  6. ├── rating
  7. │ ├── rating.css [CSS for the rendered rating table]
  8. │ └── rating.xml [Form description]
  9. ├── rating.php [Plugin hooks]
10. └── rating.xml [Manifest]

        

Установочный файл

  • Код
  • Чистый код
  • Копировать в буфер
  1.<?xml version="1.0" encoding="utf-8"?>
  2. <extension version="2.5" type="plugin" group="content" method="upgrade">
  3.     <name>plg_content_rating</name>
  4.     <author>Joomla! Project</author>
  5.     <creationDate>June 2012</creationDate>
  6.     <copyright>(C) 2005 - 2012 Open Source Matters. All rights reserved.</copyright>
  7.     <license>GNU General Public License version 2 or later; see LICENSE.txt</license>
  8.     <authorEmail>admin@joomla.org</authorEmail>
  9.     <authorUrl>www.joomla.org</authorUrl>
10.     <version>2.5.0</version>
11.     <description>PLG_CONTENT_RATING_XML_DESCRIPTION</description>
12.
13.     <files>
14.         <folder>language</folder>
15.         <folder>rating</folder>
16.         <filename plugin="rating">rating.php</filename>
17.         <filename>index.html</filename>
18.     </files>
19.
20.     <config>
21.         <fields name="params">
22.            <fieldset name="basic">
23.             <field
24.                 name="ratingclass_sfx"
25.                 type="text"
26.                 label="PLG_CONTENT_RATING_ITEM_FIELD_RATING_CLASS_LABEL"
27.                 description="PLG_CONTENT_RATING_ITEM_FIELD_RATING_CLASS_DESC"
28.             />
29.            </fieldset>
30.         </fields>
31.     </config>
32. </extension>

        

Языковой файл

  • Код
  • Чистый код
  • Копировать в буфер
  1.; Joomla! Project
  2.; Copyright (C) 2005 - 2012 Open Source Matters. All rights reserved.
  3.; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
  4.
  5.PLG_CONTENT_RATING="Content - Rating"
  6.PLG_CONTENT_RATING_XML_DESCRIPTION="[plg_content_rating] Example plugin on how to add custom fields (texture/temperature/taste) to articles (com_content). Adds ratings to an article, and display them as a table before the article content."
  7.PLG_CONTENT_RATING_SLIDER_LABEL="Rating Options"
  8.PLG_CONTENT_RATING_FIELD_TEXTURE_LABEL="Texture"
  9.PLG_CONTENT_RATING_FIELD_TEXTURE_DESC="What does the sample feel like"
10.PLG_CONTENT_RATING_FIELD_TEMPERATURE_LABEL="Temperature"
11.PLG_CONTENT_RATING_FIELD_TEMPERATURE_DESC="What is the temperature of the sample"
12.PLG_CONTENT_RATING_FIELD_TASTE_LABEL="Taste"
13.PLG_CONTENT_RATING_FIELD_TASTE_DESC="How does the sample taste"
14.PLG_CONTENT_RATING_ITEM_FIELD_RATING_CLASS_LABEL="Rating Class"
15.PLG_CONTENT_RATING_ITEM_FIELD_RATING_CLASS_DESC="Optional CSS class to add to the rating. This allows CSS styling specific to the page."

        

CSS

  • Код
  • Чистый код
  • Копировать в буфер
  1.div.rating {
  2.    display: block;
  3.    float: left;
  4.    padding-right: 10px;
  5.}
  6.div.rating table tr td {
  7.    margin: 1px !important;
  8.    padding: 2px !important;
  9.}
10.div.rating table tr.row0 {
11.    background-color:#efefef;
12.}
13.div.rating table tr.row1 {
14.    background-color:#ffffff;
15.}

        

Дополнительные поля формы

  • Код
  • Чистый код
  • Копировать в буфер
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <form>
  3.     <fields name="rating">
  4.         <fieldset name="rating" label="PLG_CONTENT_RATING_SLIDER_LABEL">
  5.            <field
  6.             name="texture"
  7.             type="text"
  8.             id="texture"
  9.             description="PLG_CONTENT_RATING_FIELD_TEXTURE_DESC"
10.             label="PLG_CONTENT_RATING_FIELD_TEXTURE_LABEL"
11.             message="PLG_CONTENT_RATING_FIELD_TEXTURE_MESSAGE"
12.             size="30"
13.            />
14.            <field
15.             name="temperature"
16.             type="text"
17.             id="temperature"
18.             description="PLG_CONTENT_RATING_FIELD_TEMPERATURE_DESC"
19.             label="PLG_CONTENT_RATING_FIELD_TEMPERATURE_LABEL"
20.             message="PLG_CONTENT_RATING_FIELD_TEMPERATURE_MESSAGE"
21.             size="30"
22.            />
23.            <field
24.             name="taste"
25.             type="text"
26.             id="taste"
27.             description="PLG_CONTENT_RATING_FIELD_TASTE_DESC"
28.             label="PLG_CONTENT_RATING_FIELD_TASTE_LABEL"
29.             message="PLG_CONTENT_RATING_FIELD_TASTE_MESSAGE"
30.             size="30"
31.            />
32.         </fieldset>
33.     </fields>
34. </form>

        

Хуки плагина

Главный файл плагина 'rating.php' содержит следующие хуки выполняемые фреймовиком:

Все хуки будет содержаться следующие объекты:

  • $context
  • $data – параметр, содержащий данные полей формы
  • $article (JTableContent) содержит статью

__construct

Конструктор загружает языковой файл:

  • Код
  • Чистый код
  • Копировать в буфер
  1. public function __construct(& $subject, $config)
  2. {
  3.     parent::__construct($subject, $config);
  4.     $this->loadLanguage();
  5. }

        

onContentPrepareForm

onContentPrepareForm добавляет дополнительные поля в формы статей. Загружает фрагмент формы из "rating/rating.xml"

  • Код
  • Чистый код
  • Копировать в буфер
  1.public public function onContentPrepareForm($form, $data)
  2. {
  3.     if (!($form instanceof JForm))
  4.     {
  5.         $this->_subject->setError('JERROR_NOT_A_FORM');
  6.         return false;
  7.     }
  8.
  9.     // Add the extra fields to the form.
10.     JForm::addFormPath(dirname(__FILE__) . '/rating');
11.     $form->loadFile('rating', false);
12.     return true;
13. }

        

onContentPrepareData

onContentPrepareData собирает данные после загрузки статьи (из #__content). Так же он объединяет данные дополнительных полей из таблицы #__user_profiles.

  • Код
  • Чистый код
  • Копировать в буфер
  1. public function onContentPrepareData($context, $data)
  2. {
  3.     if (is_object($data))
  4.     {
  5.         $articleId = isset($data->id) ? $data->id : 0;
  6.         if ($articleId > 0)
  7.         {
  8.            // Load the data from the database.
  9.            $db = JFactory::getDbo();
10.            $query = $db->getQuery(true);
11.            $query->select('profile_key, profile_value');
12.            $query->from('#__user_profiles');
13.            $query->where('user_id = ' . $db->Quote($articleId));
14.            $query->where('profile_key LIKE ' . $db->Quote('rating.%'));
15.            $query->order('ordering');
16.            $db->setQuery($query);
17.            $results = $db->loadRowList();
18.
19.            // Check for a database error.
20.         if ($db->getErrorNum())
21.            {
22.             $this->_subject->setError($db->getErrorMsg());
23.             return false;
24.            }
25.
26.            // Merge the data.
27.            $data->rating = array();
28.
29.            foreach ($results as $v)
30.            {
31.             $k = str_replace('rating.', '', $v[0]);
32.             $data->rating[$k] = json_decode($v[1], true);
33.             if ($data->rating[$k] === null)
34.             {
35.                 $data->rating[$k] = $v[1];
36.             }
37.            }
38.         } else {
39.            // load the form
40.            JForm::addFormPath(dirname(__FILE__) . '/rating');
41.            $form = new JForm('com_content.article');
42.            $form->loadFile('rating', false);
43.
44.            // Merge the default values
45.            $data->rating = array();
46.            foreach ($form->getFieldset('rating') as $field) {
47.             $data->rating[] = array($field->fieldname, $field->value);
48.            }
49.         }
50.     }
51.
52.     return true;
53. }

        

onContentAfterSave

onContentAfterSave сохраняет данные дополнительных полей в базу данных.

  • Код
  • Чистый код
  • Копировать в буфер
  1. public function onContentAfterSave($context, &$article, $isNew)
  2. {
  3.     $articleId = $article->id;
  4.     if ($articleId && isset($article->rating) && (count($article->rating)))
  5.     {
  6.         try
  7.         {
  8.            $db = JFactory::getDbo();
  9.
10.            $query = $db->getQuery(true);
11.            $query->delete('#__user_profiles');
12.            $query->where('user_id = ' . $db->Quote($articleId));
13.            $query->where('profile_key LIKE ' . $db->Quote('rating.%'));
14.            $db->setQuery($query);
15.         if (!$db->query()) {
16.             throw new Exception($db->getErrorMsg());
17.            }
18.
19.            $query->clear();
20.            $query->insert('#__user_profiles');
21.            $order = 1;
22.            foreach ($article->rating as $k => $v)
23.            {
24.             $query->values($articleId.', '.$db->quote('rating.'.$k).', '.$db->quote(json_encode($v)).', '.$order++);
25.            }
26.            $db->setQuery($query);
27.
28.         if (!$db->query()) {
29.             throw new Exception($db->getErrorMsg());
30.            }
31.         }
32.         catch (JException $e)
33.         {
34.            $this->_subject->setError($e->getMessage());
35.         return false;
36.         }
37.     }
38.
39.     return true;
40. }

        

onContentAfterDelete

onContentAfterDelete выполняется при удалении статьи, удаляет данные из дополнительных полей.

  • Код
  • Чистый код
  • Копировать в буфер
  1.public function onContentAfterDelete($context, $article)
  2. {
  3.     $articleId = $article->id;
  4.     if ($articleId)
  5.     {
  6.         try
  7.         {
  8.            $db = JFactory::getDbo();
  9.
10.            $query = $db->getQuery(true);
11.            $query->delete();
12.            $query->from('#__user_profiles');
13.            $query->where('user_id = ' . $db->Quote($articleId));
14.            $query->where('profile_key LIKE ' . $db->Quote('rating.%'));
15.            $db->setQuery($query);
16.
17.         if (!$db->query())
18.            {
19.             throw new Exception($db->getErrorMsg());
20.            }
21.         }
22.         catch (JException $e)
23.         {
24.            $this->_subject->setError($e->getMessage());
25.         return false;
26.         }
27.     }
28.
29.     return true;
30. }

        

onContentPrepare

onContentPrepare при подготовке вывода статьи, переменна $params содержит параметры статьи, $this->params - параметры плагина. Эта функция выводит дополнительные поля в начале статьи на сайте.

  • Код
  • Чистый код
  • Копировать в буфер
  1. public function onContentPrepare($context, &$article, &$params, $page = 0)
  2. {
  3.     if (!isset($article->rating) || !count($article->rating))
  4.         return;
  5.
  6.     // add extra css for table
  7.     $doc = JFactory::getDocument();
  8.     $doc->addStyleSheet(JURI::base(true).'/plugins/content/rating/rating/rating.css');
  9.
10.     // construct a result table on the fly
11.     jimport('joomla.html.grid');
12.     $table = new JGrid();
13.
14.     // Create columns
15.     $table->addColumn('attr')
16.         ->addColumn('value');
17.
18.     // populate
19.     $rownr = 0;
20.     foreach ($article->rating as $attr => $value) {
21.         $table->addRow(array('class' => 'row'.($rownr % 2)));
22.         $table->setRowCell('attr', $attr);
23.         $table->setRowCell('value', $value);
24.         $rownr++;
25.     }
26.
27.     // wrap table in a classed <div>
28.     $suffix = $this->params->get('ratingclass_sfx', 'rating');
29.     $html = '<div class="'.$suffix.'">'.(string)$table.'</div>';
30.
31.     $article->text = $html.$article->text;
32. }

        
Данный плагин поддерживается Joomla 2.5.x при установке патча для компонента менеджера статей Joomla. Патч для Joomla.

Александр Ермаков