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

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

jQuery и CSS

В предыдущей статье ("Создание дополнительного элемента формы к статье Joomla 2.x") я рассказывал о создании дополнительных полей в Joomla 2.5, в этой статье этот же вопрос будет расcмотрен в Joomla 3.x!

Функции создаваемого плагина аналогичны функциям плагина в предыдущей статье:

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

Пример

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

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

Админ раздел

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

Сайт

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

Framework

Опять же как впредыдущей статье все изменения основаны на Joomla Фреймовике, а именно на его событиях (подробное описание каждого можно найти в предыдущей статье "Создание дополнительного элемента формы к статье Joomla 2.x").

  • onContentPrepareForm()
  • onContentPrepareData()
  • onContentAfterSave()
  • onContentAfterDelete()
  • onContentPrepare()

База данных

Наш плагин будет использовать таблицу #__user_profiles и столбец "user_id" как "article_id".

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

Структура нашего плагина остаётся такой же как для Joomla 2.5:

  • Код
  • Чистый код
  • Копировать в буфер
  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]

        

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

Установчный файл можно оставить таким же как и для Joomla 2.5, замените версию на 3.x

  • Код
  • Чистый код
  • Копировать в буфер
  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>

        

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

Языковой файл можно оставить таким же как и для Joomla 2.5

  • Код
  • Чистый код
  • Копировать в буфер
  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

CSS файл можно оставить таким же как и для Joomla 2.5

  • Код
  • Чистый код
  • Копировать в буфер
  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.}

        

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

Элементы формы остаются такими же как и в Joomla 2.5

  • Код
  • Чистый код
  • Копировать в буфер
  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' содержит все хуки что и для Joomla 2.5, за исключение хука "onContentPrepareData", который я решил полностью удалить из его отказа работать в Joomla 3.0.x, хотя в 3.1.1 он работает так как описано в документации:

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

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

__construct

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

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

        

onContentPrepareForm

onContentPrepareForm в Joomla 3.x отличается от того жу хука в Joomla 2.x:

  • Код
  • Чистый код
  • Копировать в буфер
  1.    /**
  2.     * @param    JForm    $form    The form to be altered.
  3.     * @param    array    $data    The associated data for the form.
  4.     *
  5.     * @return    boolean
  6.     * @since    2.5
  7.     */
  8.    function onContentPrepareForm($form, $data)
  9.    {
10.    
11.        if (is_object($data))
12.        {
13.            $articleId = isset($data->id) ? $data->id : 0;
14.            if (!isset($data->rating) and $articleId > 0)
15.            {
16.                // Load the profile data from the database.
17.                $db = JFactory::getDbo();
18.                $query = $db->getQuery(true);
19.                $query->select('profile_key, profile_value');
20.                $query->from('#__user_profiles');
21.                $query->where('user_id = ' . $db->Quote($articleId));
22.                $query->where('profile_key LIKE ' . $db->Quote('rating.%'));
23.                $query->order('ordering');
24.                $db->setQuery($query);
25.                $results = $db->loadRowList();
26.
27.                // Check for a database error.
28.                if ($db->getErrorNum())
29.                {
30.                    $this->_subject->setError($db->getErrorMsg());
31.                    return false;
32.                }
33.
34.                // Merge the profile data.
35.                $data->rating = array();
36.
37.                foreach ($results as $v)
38.                {
39.                    $k = str_replace('rating.', '', $v[0]);
40.                    $data->rating[$k] = json_decode($v[1], true);
41.                    if ($data->rating[$k] === null)
42.                    {
43.                        $data->rating[$k] = $v[1];
44.                    }
45.                }
46.            }
47.        }
48.        
49.        if (!($form instanceof JForm))
50.        {
51.            $this->_subject->setError('JERROR_NOT_A_FORM');
52.            return false;
53.        }
54.
55.        // Add the extra fields to the form.
56.        // need a seperate directory for the installer not to consider the XML a package when "discovering"
57.        JForm::addFormPath(dirname(__FILE__) . '/rating');
58.        $form->loadFile('rating', false);
59.
60.        return true;
61.    }

        

onContentPrepareData

onContentPrepareData удалена и перенесена полностью в функцию "onContentPrepareForm".

onContentAfterSave

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

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

        

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 - параметры плагина. Эта функция выводит дополнительные поля в начале статьи на сайте. Функция отличается от её аналога для плагина в Joomla 2.5.

  • Код
  • Чистый код
  • Копировать в буфер
  1.    public function onContentPrepare($context, &$article, &$params, $page = 0)
  2.    {
  3.
  4.    
  5.                // Load the profile data from the database.
  6.                $db = JFactory::getDbo();
  7.                $query = $db->getQuery(true);
  8.                $query->select('profile_key, profile_value');
  9.                $query->from('#__user_profiles');
10.                $query->where('user_id = ' . $db->Quote($article->id));
11.                $query->where('profile_key LIKE ' . $db->Quote('rating.%'));
12.                $query->order('ordering');
13.                $db->setQuery($query);
14.                $results = $db->loadRowList();
15.
16.                // Check for a database error.
17.                if ($db->getErrorNum())
18.                {
19.                    $this->_subject->setError($db->getErrorMsg());
20.                    return false;
21.                }
22.                $article->rating = $results;
23.            
24.        if (!isset($article->rating) || !count($article->rating))
25.            return;
26.
27.            
28.
29.    
30.        // add extra css for table
31.        $doc = JFactory::getDocument();
32.        $doc->addStyleSheet(JURI::base(true).'/plugins/content/rating/rating/rating.css');
33.        
34.        // construct a result table on the fly    
35.        jimport('joomla.html.grid');
36.        $table = new JGrid();
37.
38.        // Create columns
39.        $table->addColumn('attr')
40.            ->addColumn('value');    
41.
42.        // populate
43.        $rownr = 0;
44.        
45.        
46.        
47.            foreach ($article->rating as $attr => $value) {
48.            
49.                $table->addRow(array('class' => 'row'.($rownr % 2)));
50.                $table->setRowCell('attr', $value[0]);
51.                $table->setRowCell('value', $value[1]);
52.                $rownr++;
53.            }
54.        
55.
56.        // wrap table in a classed <div>
57.        $suffix = $this->params->get('ratingclass_sfx', 'rating');
58.        $html = '<div class="'.$suffix.'">'.(string)$table.'</div>';
59.
60.        $article->text = $html.$article->text;
61.    }

        

Вместо патча, используемого в Joomla 2.5, необходимо венсти несколько изменений в файл edit.php, добавить вкладку:

  • Код
  • Чистый код
  • Копировать в буфер
  1.<?php if ($this->canDo->get('core.admin')) : ?>
  2.    <li><a href="#rating" data-toggle="tab"><?php echo JText::_('PLG_CONTENT_RATING_SLIDER_LABEL');?></a></li>
  3.<?php endif ?>

        

и добавить дополнительне поля из файла "rating/rating.xml" вставив их после вкладки "Права доступа к материалу":

  • Код
  • Чистый код
  • Копировать в буфер
  1.    <?php if ($this->canDo->get('core.admin')) : ?>
  2.        <div class="tab-pane" id="rating">
  3.            <?php foreach ($this->form->getFieldset('rating') as $field) : ?>
  4.                <div class="control-group">
  5.                    <?php echo $field->label; ?>
  6.                    <div class="controls">
  7.                        <?php echo $field->input; ?>
  8.                    </div>
  9.                </div>
10.            <?php endforeach; ?>
11.        </div>
12.    <?php endif; ?>
13.<!-- End Tabs -->

        

для Joomla 3.1.x послдений код нужно заменить несколько другим вариантом:

  • Код
  • Чистый код
  • Копировать в буфер
  1. <?php if ($this->canDo->get('core.admin')) : ?>
  2.    <?php echo JHtml::_('bootstrap.addTab', 'myTab', 'rating', JText::_('PLG_CONTENT_RATING_SLIDER_LABEL', true)); ?>
  3.        <div class="tab-pane" id="rating">
  4.            <?php foreach ($this->form->getFieldset('rating') as $field) : ?>
  5.                <div class="control-group">
  6.                    <?php echo $field->label; ?>
  7.                    <div class="controls">
  8.                        <?php echo $field->input; ?>
  9.                    </div>
10.                </div>
11.            <?php endforeach; ?>
12.        </div>
13.    <?php echo JHtml::_('bootstrap.endTab'); ?>
14.    <?php endif; ?>

        

Незабывайте что файл, в котрый мы только что внесли изменения перезаписывается при обновлении Joomla! Для того, чтобы это не прроизошло, нужно скопировать файл "edit.php" в администраторский раздел по адресу "\administrator\templates\isis\html\com_content\article\", в моём случае для шаблона "isis", для того чтобы узнать шаблон зайдите в менеджер шаблонов:

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

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