Scriptify.ru

В качестве примера я возьму простейший плагин - кнопку наверх. Теоретически, кнопку наверх сделать очень просто, даже не прибегая к помощи плагинов. Однако здесь я расскажу именно про основные принципы написания плагина для Shop-Script, поняв которые, можно начинать писать и более сложные вещи.

Файловая структура плагина Webasyst Shop-Script 7

Для начала определимся, как будет называться идентификатор нашего плагина. Идентификатор должен состоять из прописных букв английского алфавита. Например, назовем его upbutton. Для того, чтобы плагин был видимым, в файле/wa-config/apps/shop/plugin.php прописываем:

<?php

return array (
  'upbutton' => true,
);

Переходим в /wa-apps/shop/plugins/ и создаем там папку /upbutton/. Рассмотрим ее структуру:

Файловая структура плагина

Файловая структура плагина

Рассмотрим, за что отвечает каждая из папок:

Папка /img/ содержит иконку плагина;

Папка /lib/ содержит весь основной код плагина:

  • подпапка /actions/ содержит экшены - части приложения, отвечающие за генерацию фрагмента HTML-кода. Здесь файл shopUpbuttonPluginSettings.action.php отвечает за генерацию кода настроек в бекенде приложения;

  • /config/plugin.php - содержит конфигурацию плагина.

  • shopUpbutton.plugin.php - содержит основной класс приложения. В нашем случае отвечает за передачу настроек приложения в шаблон и последующего его отображения на странице. Обратите внимание, что название файла должно формироваться по образу [app_id][PLUGIN].plugin.php.

/templates/ содержит smarty шаблоны для фронтенда и бэкенда:

  • Settings.html - шаблон настроек в бекэнде приложения.

  • FrontendUpbutton.html - отвечает за вывод html-кода на страницы сайта.

.htaccess здесь просто запрещает прямой доступ к файлам из сети

Deny from all

Конфигурация плагина

Конфигурация плагина находится в файле /lib/config/plugin.php и содержит массив настроек примерно такого содержания:

<?php

// /lib/config/plugin.php

return array(
    'name' => 'Кнопка наверх',
    'description' => 'Добавляет кнопку на вверх',
    'img' => 'img/buttonup.png',
    'vendor' => '12345',
    'version' => '1.0.1',    
    'shop_settings' => true,
    'frontend' => true,
    'icons' => array(
        16 => 'img/buttonup.png',
    ),
    'handlers' => array(
        'frontend_footer' => 'frontendFooter',
    ),
);

Рассмотрим, за что отвечает каждая настройка:

  • name - название плагина;

  • description - краткое описание;

  • img - картинка плагина;

Соответствие между этими настройками и их отображением в бекэнде будет выглядеть так:

Конфигурация плагина

Конфигурация плагина

  • vendor - идентификатор разработчика. Нужен, если будете продавать свой плагин через партнерку Вебасиста;

  • version - версия плагина;

  • shop_settings - нужна, если плагин имеет свои настройки в бекенде. Иначе в настройках будет такое сообщение:

Конфигурация 'shop_settings' => false

Конфигурация 'shop_settings' => false

  • frontend - необязательный параметр, указывает, предназначен ли плагин для обработки запросов от пользователей фронтенда.

  • icons - Используется вместо параметра img в тех случаях, когда иконки нескольких размеров представлены отдельными файлами

  • handlers - этот параметр необходим для подключения плагина к определенным местам кода (хукам), которые находятся в шаблонах сайта. Например, запись
    'handlers' => array(
        'frontend_footer' => 'frontendFooter',
    ),

означает, что в хуке frontend_footer будет вызываться метод frontendFooter нашего плагина. Для наглядности на рисунке ниже показано это соответствие. Слева - код плагина, справа - код smarty шаблона:

Подключение плагина к хукам

Подключение плагина к хукам

Формирование настроек плагина в бекэнде приложения

Формировать настройки в бекенде можно двумя способами - через файл /lib/config/settings.php либо через экшен /lib/actions/shop[Plugin_id]PluginSettings.action.php. Отличие в том, что второй вариант более гибкий и позволяет сделать настройки, отличные от стандартных. Именно его мы и рассмотрим.

Для начала создаем в папке /lib/actions/ файл shopUpbuttonPluginSettings.action.php с таким содержанием:

<?php
class shopUpbuttonPluginSettingsAction extends waViewAction {    
    public function execute() { 
        // наш код
    }
}

Имя нашего класса обязательно указываем в формате shop[Plugin_id]PluginSettingsAction. Вся логика формирования настроек будет находится в публичном методе execute(), унаследованного от базового класса waViewAction.

В методе execute() нужно получать настройки плагина из базы данных, а также сохранять их и передавать в шаблон. Все настройки плагинов хранятся в таблице под названием wa_app_settings. Ее структура в базе данных будет выглядеть так:

app_id name value
shop.upbutton status 1
shop.upbutton img upbutton.png
shop.upbutton bottom 30
shop.upbutton right 30

app_id содержит имя приложения (shop) и идентификатор плагина (upbutton), name и value соответственно имя и значение настройки.

Для работы с таблицей сначала нужно создать ее модель waAppSettingsModel:

    public function execute() {
        // модель таблицы 
        $app_settings_model = new waAppSettingsModel();
    }   

Для получения данных из таблицы воспользуемся методом модели get(). В том случае, если данных в таблице еще нет (при первичной иницализации приложения), поставим настройки по умолчанию:

    public function execute() { 
        // модель таблицы 
        $app_settings_model = new waAppSettingsModel();
        // получение данных из таблицы
        $upbutton = $app_settings_model->get(array('shop', 'upbutton'));
        // если данных нет, то ставим настройки по умолчанию
        $settings['status'] = !empty($upbutton['status']) ? $upbutton['status'] : '0' ;
        $settings['img']    = !empty($upbutton['img']) ? $upbutton['img'] : '' ;
        $settings['bottom'] = !empty($upbutton['bottom']) ? $upbutton['bottom'] : '10' ;
        $settings['right']  = !empty($upbutton['right']) ? $upbutton['right'] : '10' ;      
    }   

После того, как мы получили массив настроек, нам нужно передать их в шаблон Settings.html. Это делается при помощи метода assign(), где в качестве первого аргумента указываем имя переменной, а в качестве второго имя массива, которое мы получили выше:

    public function execute() { 
        // модель таблицы 
        $app_settings_model = new waAppSettingsModel();
        // получение данных из таблицы
        $upbutton = $app_settings_model->get(array('shop', 'upbutton'));
        // если данных нет, то ставим настройки по умолчанию
        $settings['status'] = !empty($upbutton['status']) ? $upbutton['status'] : '0' ;
        $settings['img']    = !empty($upbutton['img']) ? $upbutton['img'] : '' ;
        $settings['bottom'] = !empty($upbutton['bottom']) ? $upbutton['bottom'] : '10' ;
        $settings['right']  = !empty($upbutton['right']) ? $upbutton['right'] : '10' ;
        // передаем значения в шаблон
        $this->view->assign('settings', $settings);     
    }   

Теперь, когда мы описали логику формирования настроек, создадим сам шаблон. Он будет находится в папке /templates/actions/settings/ под именем Settings.html. Шаблон представляет собой форму, где в качестве атрибута action указываем "?module=plugins&id=upbutton&action=save". Обязательно указываем параметр {$wa->csrf()} для защиты от межсайтовых атак. В шаблоне доступны все настройки, которые мы получили выше, в переменной $settings.

<h1>Кнопка наверх</h1>
<div class="fields form upbutton">
    <form action="?module=plugins&id=upbutton&action=save" method="post" id="plugins-settings-form">
        <!--защита от межсайтовых атак-->
        {$wa->csrf()}

        <div class="field">
            <div class="name">Статус</div>
            <div class="value">
                <select name="shop_upbutton[status]">
                    <option {if $settings.status==1} selected="" {/if} value="1">Включен</option>
                    <option {if $settings.status==0} selected="" {/if} value="0">Выключен</option>
                </select>
            </div>
        </div>
        <div class="field">
            <div class="name">Изображение</div>
            <div class="value">
                <input type="text" name="shop_upbutton[img]" value="{$settings.img}" />
            </div>
        </div>

        <div class="field">
            <div class="name">Отступ снизу</div>
            <div class="value">
                <input type="text" name="shop_upbutton[bottom]" value="{$settings.bottom}" />
            </div>
        </div>

        <div class="field">
            <div class="name">Отступ справа</div>
            <div class="value">
                <input type="text" name="shop_upbutton[right]" value="{$settings.right}" />
            </div>
        </div>

        <div class="field">
            <div class="value submit">
                <input type="submit" class="button green" value="Сохранить">
                <span id="plugins-settings-form-status" style="display:none">
                <i style="vertical-align:middle" class="icon16 yes"></i> [`Saved`]
            </span>
            </div>
        </div>
    </form>
</div>

Теперь наши настройки будут доступны в бэкенде:

Настройки плагина Shop-Script в бекэнде

Настройки плагина Shop-Script в бекэнде

Все настройки будут сохраняться в таблице wa_app_settings через эту форму.

Основной код приложения

Итак, мы написали код, отвечающий за настройки плагина в бэкенде. Теперь нам надо написать код, который будет получать эти настройки из базы данных, передавать их в шаблон и затем выводить html-код на сам сайт. Он будет находиться в файле /lib/shopUpbutton.plugin.php. Основной класс приложения будет содержать метод frontendFooter(), необходимый для формирования html кода:

<?php

class shopUpbuttonPlugin extends shopPlugin {   

    // отвечает за формирование html кода
    public function frontendFooter() {
        // наш код
    }
}

Рассмотрим по порядку логику формирования html кода приложения. Наш плагин должен иметь возможность включения/выключения. За эту функцию отвечает настройка status. Чтобы получить эту настройку, воспользуемся методом $this->getSettings(). Теперь наш код будет выполняться только тогда, когда status равняется единице:

    public function frontendFooter() {
        // если значение настройки status равняется единице
        if($this->getSettings('status')) {
            // наш код
        }
    }

Для того, чтобы передать данные в шаблон, нужно сначала получить экземпляр шаблонизатора при помощи метода wa()->getView(). Затем при помощи $view->assign() присваиваем переменной $settings все настройки плагина, которые получим из базы данных.

    public function frontendFooter() {
        // если значение настройки status равняется единице
        if($this->getSettings('status')) {
            // получаем класс шаблонизатора, необходимого для формирования страниц
            $view = wa()->getView();
            // присваиваем переменной $settings настройки плагина
            $view->assign('settings', $this->getSettings());
        }
    }

После того, как получили настройки, указываем путь к шаблону. Это делается при помощи метода wa()->getAppPath(). Затем при помощи метода $view->fetch() сохраняем в переменной html-код и выводим его на странице.

    public function frontendFooter() {
        // если значение настройки status равняется единице
        if($this->getSettings('status')) {
            // получаем класс шаблонизатора, необходимого для формирования страниц
            $view = wa()->getView();
            // присваиваем переменной $settings настройки плагина
            $view->assign('settings', $this->getSettings());
            // указываем путь к шаблону
            $template_path = wa()->getAppPath('plugins/upbutton/templates/FrontendUpbutton.html', 'shop');
            // получаем итоговый html код
            $html = $view->fetch($template_path);
            // выводим код на странице
            return $html;
        }
    }

Шаблон FrontendUpbutton.html, который будет применятся для вывода на страницы, для наглядности максимально упростим. Здесь переменные $settings.right и $settings.bottom отвечают за позиционирование страницы относительно правого и нижнего края. В переменной {$settings.img} содержится имя картинки, которую загрузили раннее в папку img.

Примечание: Весь код, заключенный между {literal}, не интерпретируется Smarty, а выводится как есть.

<div id="upbutton" style="right:{$settings.right}px; bottom:{$settings.bottom}px; position: fixed;">
    <img src="/wa-apps/shop/plugins/upbutton/img/{$settings.img}"/>
</div>

{literal}
<script>
$(function() {
    var upbutton = $('#upbutton') ;
    if(upbutton.length) {
        $(window).scroll(function() {
            if($(this).scrollTop() > 0) {
                upbutton.fadeIn() ;
            } else {
                upbutton.fadeOut() ;
            }
        }) ;
        upbutton.click(function() {
            $('body,html').animate({scrollTop: 0}, 400) ;
            return false ;
        }) ;
    }
}) ;
</script>
{/literal}

Итоги

На данном простом примере я показал основы написания плагина для Shop-Script. Но все это - лишь верхушка айсберга. Здесь не описаны такие нюансы, как например работа с моделями, и т. д. Если хочется узнать больше, то на сайте разработчиков можно получить больше информации по разработке плагинов.

Содержание статьи