Создание компонента для Joomla

Часть 15 - добавляем состояние записи

Joomla

Часть 15 - добавляем состояние записи

В Joomla для состояния записи используются следующие значения:

  • опубликовано – 1
  • не опубликовано – 0
  • в архиве – 2
  • в корзине – -2

В этой части мы добавим только первые два. В следующей части (когда будем рассматривать добавление фильтров) ещё два, потому что без фильтров невозможно работать с записями, состояние которых отлично от «опубликовано» и «не опубликовано».

Для добавления состояния записи (сообщения) нам необходимо внести изменения, которые коснутся практически всего компонента.

Изменяем SQL файлы

Для поддержки состояния сообщения необходимо изменить структуру таблицы #__helloworld и добавить поле state.

Вносим изменения в файл admin/sql/install.mysql.utf8.sql:

DROP TABLE IF EXISTS `#__helloworld`;CREATE TABLE `#__helloworld` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `asset_id` INT(10) NOT NULL DEFAULT '0',
 `greeting` varchar(25) NOT NULL,
 `state` tinyint(1) NOT NULL DEFAULT '0',
 `catid` int(11) NOT NULL DEFAULT '0',
 `ordering` INT(11) NOT NULL DEFAULT '0',
 `params` TEXT NOT NULL DEFAULT '',
 PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
 
INSERT INTO `#__helloworld` (`greeting`) VALUES
 ('Hello World!'),
 ('Good bye World!');

Не забудьте создать файл admin/sql/updates/mysql/0.0.15.sql для изменения структуры таблицы во время установки новой версии компонента:

ALTER TABLE `#__helloworld` ADD `state` tinyint(1) NOT NULL DEFAULT '0' AFTER `greeting`;

Добавляем действие core.edit.state

В правах доступа мы не учитывали состояние сообщения для уровня записи, поэтому добавим действие core.edit.state в раздел 'message' в файл admin/access.xml:

<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_HELLOWORLD_ACCESS_EDITSTATE_COMPONENT_DESC" />

Изменяем модель списка сообщений

Открываем файл admin/models/helloworlds.php и вносим два изменения.

Первое, в конструкторе добавим поле state в список валидных полей для сортировки:

/**
 * Конструктор.
 *
 * @param   array  $config  Массив с конфигурационными параметрами.
 */
public function __construct($config = array())
{
    // Добавляем валидные поля для фильтров и сортировки.
    if (empty($config['filter_fields']))
    {
        $config['filter_fields'] = array(
            'id', 'id',
            'greeting', 'greeting',
            'state', 'state',
            'ordering', 'ordering',
        );
    }
 
    parent::__construct($config);
}

Второе, добавляем поле state в запрос select:

// Выбераем поля.
$query->select('id, greeting, state, ordering');

Изменяем представление списка сообщений

В представление списка сообщений admin/views/helloworlds/view.html.php нам необходимо добавить две кнопки в панель инструментов. Вносим изменения в метод addToolBar():

/**
 * Устанавливает панель инструментов.
 *
 * @return void
 */
protected function addToolBar()
{
    JToolBarHelper::title(JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLDS'), 'helloworld');
 
    if ($this->canDo->get('core.create'))
    {
        JToolBarHelper::addNew('helloworld.add');
    }
 
    if ($this->canDo->get('core.edit'))
    {
        JToolBarHelper::editList('helloworld.edit');
    }
 
    if ($this->canDo->get('core.edit.state'))
    {
        JToolBarHelper::divider();
        JToolbarHelper::publish('helloworlds.publish', 'JTOOLBAR_PUBLISH', true);
        JToolbarHelper::unpublish('helloworlds.unpublish', 'JTOOLBAR_UNPUBLISH', true);
    }
 
    if ($this->canDo->get('core.delete'))
    {
        JToolBarHelper::divider();
        JToolBarHelper::deleteList('', 'helloworlds.delete');
    }
 
    if ($this->canDo->get('core.admin'))
    {
        JToolBarHelper::divider();
        JToolBarHelper::preferences('com_helloworld');
    }
}

Здесь мы добавили вызовы двух методов:

JToolbarHelper::publish(helloworlds.publish', 'JTOOLBAR_PUBLISH', true);
JToolbarHelper::unpublish(helloworlds.unpublish', 'JTOOLBAR_UNPUBLISH', true);

Изменяем шаблоны списка сообщений

Сначала изменим суб-шаблон заголовков списков admin/views/helloworlds/tmpl/default_head.php:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Данные по сортировке.
$listOrder    = $this->escape($this->state->get('list.ordering'));
$listDirn    = $this->escape($this->state->get('list.direction'));
?>
<tr>
    <th width="1%">
        <input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'); ?>" on-click="Joomla.checkAll(this)"
    </th>
    <th>
        <?php echo JHtml::_('grid.sort', 'COM_HELLOWORLD_HELLOWORLD_HEADING_GREETING', 'greeting', $listDirn, $listOrder); ?>
    </th>
    <th width="10%">
        <?php echo JHtml::_('grid.sort', 'JSTATUS', 'state', $listDirn, $listOrder); ?>
    </th>
    <th width="10%">
        <?php echo JHtml::_('grid.sort', 'JGRID_HEADING_ORDERING', 'ordering', $listDirn, $listOrder); ?>
        <?php if ($listOrder == 'ordering') : ?>
            <?php echo JHtml::_('grid.order', $this->items, 'filesave.png', 'helloworlds.saveorder'); ?>
        <?php endif; ?>
    </th>
    <th width="1%">
        <?php echo JHtml::_('grid.sort', 'COM_HELLOWORLD_HELLOWORLD_HEADING_ID', 'id', $listDirn, $listOrder); ?>
    </th>
</tr>

Мы добавили вывод заголовка "Состояние":

<th width="10%">
    <?php echo JHtml::_('grid.sort', 'JSTATUS', 'state', $listDirn, $listOrder); ?>
</th>

Далее изменяем суб-шаблон admin/views/helloworlds/tmpl/default_body.php:

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Данные по сортировке.
$listDirn    = $this->escape($this->state->get('list.direction'));
$listOrder    = $this->escape($this->state->get('list.ordering'));
$saveOrder    = $listOrder == 'ordering';
 
foreach ($this->items as $i => $item) :
    $canEdit = JFactory::getUser()->authorise('core.edit', 'com_helloworld.message.' . $item->id);
    $canChange = JFactory::getUser()->authorise('core.edit.state', 'com_helloworld.message.' . $item->id);
    ?>
    <tr>
        <td>
            <?php echo JHtml::_('grid.id', $i, $item->id); ?>
        </td>
        <td>
            <?php if ($canEdit) : ?>
                <a href="/<?php echo JRoute::_('index.php?option=com_helloworld&task=helloworld.edit&id=' . (int) $item->id); ?>">
                    <?php echo $item->greeting; ?>
                </a>
            <?php else: ?>
                <?php echo $item->greeting; ?>
            <?php endif; ?>
        </td>
        <td>
            <?php echo JHtml::_('jgrid.published', $item->state, $i, 'helloworlds.', $canChange); ?>
        </td>
        <td>
            <?php if ($saveOrder) : ?>
                <?php if ($listDirn == 'asc') : ?>
                    <span><?php echo $this->pagination->orderUpIcon($i, true, 'helloworlds.orderup', 'JLIB_HTML_MOVE_UP', $saveOrder); ?></span>
                    <span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'helloworlds.orderdown', 'JLIB_HTML_MOVE_DOWN', $saveOrder); ?></span>
                <?php elseif ($listDirn == 'desc') : ?>
                    <span><?php echo $this->pagination->orderUpIcon($i, true, 'helloworlds.orderdown', 'JLIB_HTML_MOVE_UP', $saveOrder); ?></span>
                    <span><?php echo $this->pagination->orderDownIcon($i, $this->pagination->total, true, 'helloworlds.orderup', 'JLIB_HTML_MOVE_DOWN', $saveOrder); ?></span>
                <?php endif; ?>
            <?php endif; ?>
            <?php $disabled = $saveOrder ?  '' : 'disabled="disabled"'; ?>
            <input type="text" name="order[]" size="5" value="<?php echo $item->ordering; ?>" <?php echo $disabled; ?> />
        </td>
        <td>
            <?php echo $item->id; ?>
        </td>
    </tr>
<?php endforeach; ?>

Здесь была добавлена кнопка публикации. Обратите внимание, что мы передаем также возможность изменять состояние в переменной $canChange и если оно равно false, то кнопка становится неактивной:

<td>
 <?php echo JHtml::_('jgrid.published', $item->state, $i, 'helloworlds.', $canChange); ?>
</td>

Кроме того, в четвертом параметре мы указываем, какой контроллер необходимо задействовать для исполнения задачи. В нашем случае - helloworlds.

В суб-шаблоне admin/views/helloworlds/tmpl/default_foot.php мы увеличиваем значение colspan:

<tr>
    <td colspan="5"><?php echo $this->pagination->getListFooter(); ?></td>
</tr>

Теперь у нас есть кнопки на панели инструментов и кнопка в списке сообщений.

Добавляем состояние записи - список сообщений

Добавляем метод publish() в класс таблицы

Для того чтобы состояние сообщения могло быть изменено, необходимо добавить в класс таблицы сообщения HelloWorldTableHelloWorld метод publish(). Именно он вызывается в конечном итоге при попытке изменить состояние. Но почему именно он? Потому что в Joomla этот процесс происходит следующим образом:

  • вызывается метод publish() контроллера JControllerAdmin, так как наш контроллер HelloWorldControllerHelloWorlds его расширяет;
  • контроллер JControllerAdmin вызывает метод publish() модели JModelAdmin, так как в нашем контроллере мы установили модель HelloWorldModel в методе getModel(), а она расширяет JModelAdmin;
  • модель JModelAdmin в методе publish() вызывает экземпляр таблицы HelloWorldTableHelloWorld, так как в нашей модели HelloWorldModel мы установили её в методе getTable().

Итак, откройте файл admin/tables/helloworld.php и добавьте следующий код после метода load():

/**
 * Метод для изменения состояния сообщения.
 *
 * @param   mixed    $pks     Необязательный массив первичных ключей.
 * @param   integer  $state   Код состояния.
 * @param   integer  $userId  Id пользователя, который производит операцию.
 *
 * @return  boolean  True если состояние успешно установлено.
 *
 * @throws  RuntimeException
 */
public function publish($pks = null, $state = 1, $userId = 0)
{
    $k = $this->_tbl_key;
 
    // Очищаем входные параметры.
    JArrayHelper::toInteger($pks);
    $state = (int) $state;
 
    // Если первичные ключи не установлены, то проверяем ключ в текущем объекте.
    if (empty($pks))
    {
        if ($this->$k)
        {
            $pks = array($this->$k);
        }
        else
        {
            throw new RuntimeException(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED'), 500);
        }
    }
 
    // Устанавливаем состояние для всех первичных ключей.
    foreach ($pks as $pk)
    {
        // Загружаем сообщение.
        if (!$this->load($pk))
        {
            throw new RuntimeException(JText::_('COM_HELLOWORLD_TABLE_ERROR_RECORD_LOAD'), 500);
        }
 
        $this->state = $state;
 
        // Сохраняем сообщение.
        if (!$this->store())
        {
            throw new RuntimeException(JText::_('COM_HELLOWORLD_TABLE_ERROR_RECORD_STORE'), 500);
        }
    }
 
        return true;
}

Изменяем модель сообщения

Первое, что мы добавим в модель – это проверку на возможность изменять состояние сообщения. Открываем файл admin/models/helloworld.php и добавляем метод canEditState():

/**
 * Метод для проверки, может ли пользователь изменять состояние записи.
 *
 * @param   object  $record  Объект записи.
 *
 * @return  boolean  True, если разрешено  изменять состояние записи.
 */
protected function canEditState($record)
{
    $user = JFactory::getUser();
 
    if (!empty($record->id))
    {
        return $user->authorise('core.edit.state', $this->option . '.message.' . (int) $record->id);
    }
    elseif (!empty($record->catid))
    {
        return $user->authorise('core.edit.state', $this->option . '.category.' . (int) $record->catid);
    }
    else
    {
        return parent::canEditState($record);
    }
}

Далее изменим метод getForm(), добавив проверку на возможность изменять состояние:

/**
 * Метод для получения формы.
 *
 * @param   array    $data      Данные для формы.
 * @param   boolean  $loadData  True, если форма загружает свои данные (по умолчанию), false если нет.
 *
 * @return  mixed  Объект JForm в случае успеха, в противном случае false.
 */
public function getForm($data = array(), $loadData = true)
{
    // Получаем форму.
    $form = $this->loadForm(
        $this->option . '.helloworld', 'helloworld', array('control' => 'jform', 'load_data' => $loadData)
    );
 
    if (empty($form))
    {
        return false;
    }
 
    $id = JFactory::getApplication()->input->get('id', 0);
    $user = JFactory::getUser();
 
    // Изменяем форму исходя из доступов пользователя.
    if ($id != 0 && (!$user->authorise('core.edit.state', $this->option . '.message.' . (int) $id))
        || ($id == 0 && !$user->authorise('core.edit.state', $this->option)))
    {
        // Модифицируем поля.
        $form->setFieldAttribute('state', 'disabled', 'true');
    }
 
    return $form;
}

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

Изменяем файл формы

Откройте файл admin/models/forms/helloworld.xml и добавьте следующий код после поля catid:

<field
    name="state"
    type="list"
    label="JSTATUS"
    description="JFIELD_PUBLISHED_DESC"
    class="inputbox"
    size="1"
    default="1"
>
    <option value="1">JPUBLISHED</option>
    <option value="0">JUNPUBLISHED</option>
</field>

Добавляем состояние записи - редактирование сообщения

Изменяем тип поля

В типе поля нам необходимо учитывать состояние сообщения, чтобы в пункте меню нам не показывались неопубликованные или находящиеся в корзине записи. Открываем admin/models/fields/helloworld.php и в метод getOptions() добавляем условие ->where('h.state > 0'):

<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
// Подключаем тип поля list.
jimport('joomla.form.helper');
JFormHelper::loadFieldClass('list');
 
/**
 * Класс поля формы HelloWorld компонента HelloWorld.
 */
class JFormFieldHelloWorld extends JFormFieldList
{
    /**
     * Тип поля.
     *
     * @var  string
     */
    protected $type = 'HelloWorld';
 
    /**
     * Метод для получения списка опций для поля списка.
     *
     * @return  array  Массив JHtml опций.
     */
    protected function getOptions()
    {
        // Получаем объект базы данных.
        $db = JFactory::getDbo();
 
        // Конструируем SQL запрос.
        $query = $db->getQuery(true);
        $query->select('h.id, h.greeting, h.catid')
            ->from('#__helloworld as h')
            ->select('c.title as category')
            ->leftJoin('#__categories AS c ON c.id = h.catid')
            ->where('h.state > 0');
        $db->setQuery($query);
        $messages = $db->loadObjectList();
 
        // Массив JHtml опций.
        $options = array();
 
        if ($messages)
        {
            foreach ($messages as $message)
            {
                $options[] = JHtml::_('select.option', $message->id,
                    $message->greeting . ($message->catid ? ' (' . $message->category . ')' : '')
                );
            }
        }
        else
        {
            $options[] = JHtml::_('select.option', 0, JText::_('COM_HELLOWORLD_ERROR_MESSAGE_NOT_FOUND'));
        }
 
        $options = array_merge(parent::getOptions(), $options);
 
        return $options;
    }
}

Если мы не можем найти сообщение (например, все они сняты с публикации), то вместо списка выбора мы отображаем всего один пункт "Сообщение не найдено". И даже если мы сохраним такой пункт меню, то в публичной части все равно будет отображена ошибка 404, так как в качестве id записи мы передаем 0, а записей с таким id в базе данных быть не может.

Изменяем модель сообщения в публичной части

Похожее изменение (как и для типа поля) необходимо внести и в модель сообщения публичной части. Открываем файл site/models/helloworld.php и добавляем условие ->where('h.state > 0') в метод getItem():

// Конструируем SQL запрос.
$query = $this->_db->getQuery(true);
$query->select('h.greeting, h.params')
    ->from('#__helloworld as h')
    ->select('c.title as category')
    ->leftJoin('#__categories as c ON c.id = h.catid')
    ->where('h.id = ' . (int) $id)
    ->where('h.state > 0');

Теперь в публичной части не будут отображаться неопубликованные или находящиеся в корзине сообщения.

Добавляем языковые константы

Откройте файл admin/language/en-GB/en-GB.com_helloworld.ini и добавьте:

COM_HELLOWORLD_N_ITEMS_PUBLISHED_1="One message published"
COM_HELLOWORLD_N_ITEMS_UNPUBLISHED_1="One message unpublished"
COM_HELLOWORLD_N_ITEMS_PUBLISHED="%d messages published"
COM_HELLOWORLD_N_ITEMS_UNPUBLISHED="%d messages unpublished"
COM_HELLOWORLD_TABLE_ERROR_RECORD_LOAD="Error loading record from the table."
COM_HELLOWORLD_TABLE_ERROR_RECORD_STORE="Error saving record into the table."

Откройте файл admin/language/ru-RU/ru-RU.com_helloworld.ini и добавьте:

COM_HELLOWORLD_N_ITEMS_PUBLISHED_1="1 сообщение опубликовано"
COM_HELLOWORLD_N_ITEMS_UNPUBLISHED_1="1 сообщение снято с публикации"
COM_HELLOWORLD_N_ITEMS_PUBLISHED_2="%d сообщения опубликовано"
COM_HELLOWORLD_N_ITEMS_UNPUBLISHED_2="%d сообщения снято с публикации"
COM_HELLOWORLD_N_ITEMS_PUBLISHED_MORE="%d сообщений опубликовано"
COM_HELLOWORLD_N_ITEMS_UNPUBLISHED_MORE="%d сообщений снято с публикации"
COM_HELLOWORLD_TABLE_ERROR_RECORD_LOAD="Ошибка при попытке загрузить запись из таблицы."
COM_HELLOWORLD_TABLE_ERROR_RECORD_STORE="Ошибка при попытке сохранить запись в таблице."

Откройте файл site/language/en-GB/en-GB.com_helloworld.ini и добавьте:

COM_HELLOWORLD_ERROR_MESSAGE_NOT_FOUND="Message not found"

Откройте файл site/language/ru-RU/ru-RU.com_helloworld.ini и добавьте:

COM_HELLOWORLD_ERROR_MESSAGE_NOT_FOUND="Сообщение не найдено"

Собираем пакет установки компонента

Не забудьте поменять номер версии в файле helloworld.xml:

<version>0.0.15</version>

helloworld.xml

<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="2.5.0" method="upgrade">
 
    <name>COM_HELLOWORLD</name>
    <!-- Следующие элементы необязательны -->
    <creationDate>Июль 2012</creationDate>
    <author>Вася Пупкин</author>
    <authorEmail>Ваш e-mail</authorEmail>
    <authorUrl>Ваш сайт</authorUrl>
    <copyright>Информация о копирайте</copyright>
    <license>Информация о лицензии</license>
    <!--  Версия записывается в таблицу компонентов -->
    <version>0.0.15</version>
    <!-- Описание необязательно -->
    <description>COM_HELLOWORLD_DESCRIPTION</description>
 
    <!-- Запускается при установке/удалении/обновлении -->
    <scriptfile>script.php</scriptfile>
 
    <!-- Запускается при установке -->
    <install>
        <sql>
            <file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
        </sql>
    </install>
    <!-- Запускается при удалении -->
    <uninstall>
        <sql>
            <file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
        </sql>
    </uninstall>
    <!-- Запускается при обновлении -->
    <update>
        <schemas>
            <schemapath type="mysql">sql/updates/mysql</schemapath>
        </schemas>
    </update>
 
    <!-- Раздел основных файлов сайта -->
    <!-- Обратите внимание на значение аттрибута folder: Этот аттрибут описывает папку нашего пакета-установщика из которой должны копироваться файлы. 
    Поэтому указанные в этом разделе файлы будут скопированы из папки /site/ нашего пакета-установщика в соответствующую папку установки. -->
    <files folder="site">
        <filename>index.html</filename>
        <filename>controller.php</filename>
        <filename>helloworld.php</filename>
        <folder>language</folder>
        <folder>models</folder>
        <folder>views</folder>
    </files>
 
    <media destination="com_helloworld" folder="media">
        <filename>index.html</filename>
        <folder>images</folder>
    </media>
 
    <!-- Администрирование -->
    <administration>
        <!-- Раздел Меню -->
        <menu img="../media/com_helloworld/images/hello-16x16.png">COM_HELLOWORLD_MENU</menu>
        <!-- Раздел основных файлов администрирования  -->
        <!-- Обратите внимание на значение аттрибута folder: Этот аттрибут описывает папку нашего пакета-установщика из которой должны копироваться файлы. 
        Поэтому указанные в этом разделе файлы будут скопированы из папки /admin/ нашего пакета-установщика в соответствующую папку установки. -->
        <files folder="admin">
            <filename>index.html</filename>
            <filename>access.xml</filename>
            <filename>config.xml</filename>
            <filename>controller.php</filename>
            <filename>helloworld.php</filename>
            <folder>controllers</folder>
            <folder>helpers</folder>
            <folder>models</folder>
            <folder>sql</folder>
            <folder>tables</folder>
            <folder>views</folder>
        </files>
        <languages folder="admin">
            <language tag="en-GB">language/en-GB/en-GB.com_helloworld.ini</language>
            <language tag="en-GB">language/en-GB/en-GB.com_helloworld.sys.ini</language>
            <language tag="ru-RU">language/ru-RU/ru-RU.com_helloworld.ini</language>
            <language tag="ru-RU">language/ru-RU/ru-RU.com_helloworld.sys.ini</language>
        </languages>
    </administration>

    
    <!-- Сервер обновлений -->
    <updateservers>
        <!-- Заметка: Не допускаются пробелы или переносы строк между тегам server -->
        <server type="extension" priority="1" name="Сайт обновлений компонента Hello World!">http://вашдомен.ru/update/helloworld-update.xml</server>
    </updateservers>
 
</extension>

Содержимое директории с кодом:

helloworld.xml
script.php
site/index.html
site/helloworld.php
site/controller.php
site/language/index.html
site/language/en-GB/index.html
site/language/en-GB/en-GB.com_helloworld.ini
site/language/ru-RU/index.html
site/language/ru-RU/ru-RU.com_helloworld.ini
site/models/index.html
site/models/helloworld.php
site/views/index.html
site/views/helloworld/index.html
site/views/helloworld/view.html.php
site/views/helloworld/tmpl/index.html
site/views/helloworld/tmpl/default.xml
site/views/helloworld/tmpl/default.php
admin/index.html
admin/access.xml
admin/config.xml
admin/controller.php
admin/helloworld.php
admin/controllers/index.html
admin/controllers/helloworld.php
admin/controllers/helloworlds.php
admin/helpers/index.html
admin/helpers/helloworld.php
admin/language/index.html
admin/language/en-GB/index.html
admin/language/en-GB/en-GB.com_helloworld.ini
admin/language/en-GB/en-GB.com_helloworld.sys.ini
admin/language/ru-RU/index.html
admin/language/ru-RU/ru-RU.com_helloworld.ini
admin/language/ru-RU/ru-RU.com_helloworld.sys.ini
admin/models/index.html
admin/models/helloworld.php
admin/models/helloworlds.php
admin/models/fields/index.html
admin/models/fields/helloworld.php
admin/models/forms/index.html
admin/models/forms/helloworld.js
admin/models/forms/helloworld.xml
admin/models/rules/index.html
admin/models/rules/greeting.php
admin/sql/index.html
admin/sql/install.mysql.utf8.sql
admin/sql/uninstall.mysql.utf8.sql
admin/sql/updates/index.html
admin/sql/updates/mysql/index.html
admin/sql/updates/mysql/0.0.1.sql
admin/sql/updates/mysql/0.0.4.sql
admin/sql/updates/mysql/0.0.9.sql
admin/sql/updates/mysql/0.0.10.sql
admin/sql/updates/mysql/0.0.12.sql
admin/sql/updates/mysql/0.0.14.sql
admin/tables/index.html
admin/tables/helloworld.php
admin/views/index.html
admin/views/helloworld/index.html
admin/views/helloworld/view.html.php
admin/views/helloworld/submitbutton.js
admin/views/helloworld/tmpl/index.html
admin/views/helloworld/tmpl/edit.php
admin/views/helloworlds/index.html
admin/views/helloworlds/view.html.php
admin/views/helloworlds/tmpl/index.html
admin/views/helloworlds/tmpl/default.php
admin/views/helloworlds/tmpl/default_body.php
admin/views/helloworlds/tmpl/default_foot.php
admin/views/helloworlds/tmpl/default_head.php
language/index.html
language/en-GB/index.html
language/en-GB/en-GB.com_helloworld.sys.ini
language/ru-RU/index.html
language/ru-RU/ru-RU.com_helloworld.sys.ini
media/index.html
media/images/index.html
media/images/hello-16x16.png
media/images/hello-48x48.png

Запакуйте директорию в архивный файл (zip, tar, tar.gz, bz2) или скачайте его напрямую c GitHub. Далее установите его, используя менеджер расширений Joomla. Теперь у нас есть возможность изменять состояние записи.

Код для этой части

Скачать com_helloworld часть 15

Актуальный код части 15 на GitHub

Dmitry Rekun
Работаю в банковской сфере, а с веб-разработкой (непосредственно с Joomla) столкнулся в 2007 году. Теперь это моё хобби и время от времени вторая работа. Какое-то время вёл свой блог, но решил попробовать работать в команде. И вот c 2012 года я здесь :)