Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%

<<< Как сделать шаблон для Moguta.CMS || Конкурс на 5000 рублей «Все об интернет-магазине» >>>

Moguta.CMS – разработка плагина скидок

10.05.2013
Moguta.CMS – разработка плагина скидок

Здравствуйте, уважаемые читатели блога LifeExample, в этой статье я научу вас самостоятельно делать расширения Moguta.CMS, на примере создания плагина скидок.

Изначально в основу проекта Могута, была заложена идея создания легкой админки. Панель администрирования не должна была стать похожей на сотни однотипных, навороченных разным функционалом продуктов. И это получилось! Периодически мне на email приходят положительные отзывы о продукте, именно с точки зрения понятности админки и легкости управления магазином.

Посмотрите следующий ролик и оцените панель администрирования Moguta.CMS. Выскажите свое мнение в комментариях к данной статье.

В ходе разработки CMS большое внимание уделялось системе плагинов, позволяющих нарастить функционал для каждого магазина индивидуально.

Согласитесь, ведь не всем может понадобиться вести ленту новостей на своем сайте или иметь возможность общаться с пользователями через их личные кабинеты, так зачем это включать в базовый набор функций системы?

Предлагаю в данной статье вместе разработать, полезный многим, плагин скидок для товаров интернет-магазина.

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

Задачи плагина скидок:

  1. Добавить в панель инструментов интерфейс для редактирования скидки;
  2. При выводе стоимости товаров в публичной части показывать рядом с новой ценой зачеркнутую старую цену;

Подготовка

На самом деле, на официальном сайте могуты есть статья "Создание плагина для Moguta.CMS", в которой довольно четко описаны основные требования к плагинам. Рекомендую изучить ее прежде чем двигаться дальше.

Прочитали? Хорошо, тогда вы должны были усвоить несколько основных моментов:

  1. Все плагины располагаются в папке mg-plugins;
  2. Каждый плагин хранится в именованной папке и обязательно содержит файл index.php, в котором первым комментарием задана служебная информация;
  3. Названия папок плагинов должны быть в нижнем регистре;
  4. Плагин необходимо активировать в разделе "Плагины" панели администрирования;
  5. Не все плагины имеют свою страницу настроек;
  6. После активации некоторых плагинов появляется возможность работать с его шорткодами;

Если вы ранее создавали плагины для wordpress или читали статью моего блога "Пишем плагин WordPress", то вы заметите много сходств с процессом разработки плагина для Moguta.CMS.

Начало

Перейдем к практике. Создадим в папке mg-plugins/ новый каталог: discount-panel, в него добавим следующий файл index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<?php
/*
  Plugin Name: Панель скидок
  Description: Устанавливает скидку/наценку  на определенную группу товаров.
  Author: Avdeev Mark
  Version: 1.0
 */


new DiscountPanel;

class DiscountPanel{
  private static $arrayProducts = array(); // массив продуктов с новыми ценами, выводимый на генерируемую странице.
  public function __construct(){
    mgActivateThisPlugin(__FILE__, array(__CLASS__, 'createDateBase'));  
    mgAddAction(__FILE__, array(__CLASS__, 'pageSettingsPlugin'));
   
    if(!URL::isSection('mg-admin')){
      mgAddShortcode('old-price', array(__CLASS__, 'oldPrice'));      
      mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1);
      mgAddAction('models_product_getproduct' , array(__CLASS__, 'discountToProduct'), 1);
      mgAddAction('models_catalog_getlistproductbykeyword' , array(__CLASS__, 'discountToSearch'), 1);
      mgAddAction('smalcart_getcartdata' , array(__CLASS__, 'discountToSmalCart'), 1);      
    }    
  }
 
 
  /**
   * Создает таблицу для скидок в БД при активации плагина
   */

  static function createDateBase(){
  DB::query("
     CREATE TABLE IF NOT EXISTS `"
.PREFIX."discount` (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Порядковый номер скидки',
      `cat_id` int(11) NOT NULL COMMENT 'Категория на которую растпространяется скидка',
      `prod_ids` text CHARACTER SET utf8 NOT NULL COMMENT 'Номера товаров попадающих под скидку, если пусто - значит все.',
      `persent` int(11) NOT NULL DEFAULT '0' COMMENT 'Процент скидки',
      `date_start` date NOT NULL COMMENT 'Дата начала скидки',
      `date_end` date NOT NULL COMMENT 'Дата завершения скидки',
      `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Действие скидки',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;"
);  
   
    DB::query(" INSERT INTO  `".PREFIX."discount` (
          `id` ,
          `cat_id` ,
          `prod_ids` ,
          `persent` ,
          `date_start` ,
          `date_end` ,
          `enabled`
        )
        VALUES (
         1 ,  '0',  '',  '10',  now(),  now(),  '1'
        );
     "

    );
  }
 
  /**
   * Выводит страницу настроек плагина в админке
   */

  static function pageSettingsPlugin(){
   
    if(isset($_POST['discount']) && is_numeric($_POST['discount'])){
      $discount = $_POST['discount'];
      DB::query("
        UPDATE `"
.PREFIX."discount`
        SET `persent` = "
.DB::quote($discount)."
        WHERE id=1
      "
);
      echo "<br/> Установлена новая скидка на все товары: ".$discount."%";
    } else{    
        $discount = self::getDiscount();
    };
   
    echo '
      <div class="discount-block" style="margin: 50px;">  
        <form methot="post" action="">
          Скидка на все товары: <input type="text" name="discount" value="'
.$discount.'"/> %.
          <br/>    
          <input type="hidden" name="pluginTitle" value="'
.$_POST['pluginTitle'].'"/>
          <input type="submit" value="Применить"/>
        </form>
      </div>'
;
  }
 
  /**
   * Получает текущую скидку на все товары
   */

  static function getDiscount(){  
    $discount = 0;
    $res = DB::query(" SELECT `persent` FROM `".PREFIX."discount` WHERE `id`= 1");
      if($row = DB::fetchAssoc($res)){
        $discount = $row['persent'];        
      }  
    return $discount;  
  }
 

  /**
   * Применяет скидку к ценам выводимым для продуктов в каталоге
   */

  static function discountToCatalog($arg){    
 
     foreach ($arg['result']['catalogItems']  as &$item) {
       // сохраняем старую цену продукта для последующего вывода шорткодом
       self::$arrayProducts[$item['id']]['oldPrice'] = $item['price'];
       $item['price'] = self::applyDiscount($item['price']);
       // сохраняем новую цену для продукта для последующего вывода шорткодом
       self::$arrayProducts[$item['id']]['newPrice'] = $item['price'];
     }          
   
     return $arg['result'];
  }  
 
  /**
   * Применяет скидку к ценам для продуктов в карточке товара
   */

  static function discountToProduct($arg){
     self::$arrayProducts[$arg['result']['id']]['oldPrice'] = $arg['result']['price'];
     $arg['result']['price']=self::applyDiscount($arg['result']['price']);
     self::$arrayProducts[$item['id']]['oldPrice'] = $arg['result']['price'];
     
     return $arg['result'];
  }  
 
 
  /**
   * Применяет скидку к ценам для продуктов в карточке товара
   */

  static function discountToSearch($arg){
     foreach ($arg['result']['catalogItems']  as &$item) {
       self::$arrayProducts[$item['id']]['oldPrice'] = $item['price'];
       $item['price'] = self::applyDiscount($item['price']);
       self::$arrayProducts[$item['id']]['newPrice'] = $item['price'];
     }
     return $arg['result'];    
  }  
 
   /**
   * Применяет скидку к ценам для продуктов в маленькой корзине
   */

  static function discountToSmalCart($arg){
     if(isset($arg['result']['dataCart'])){
       $arg['result']['cart_price'] = 0;
       foreach ($arg['result']['dataCart']  as &$item) {
         $item['price'] = self::applyDiscount($item['price']);
         $item['priceInCart'] = $item['price']." ".MG::getSetting('currency');
         $arg['result']['cart_price'] += $item['price'] * $item['countInCart'];      
       }    
     }
     
     $arg['result']['cart_price_wc'] = $arg['result']['cart_price']." ".MG::getSetting('currency');      
     return $arg['result'];
  }  
 
 
   /**
   * Применяет скидку к ценам продуктов
   */

  static function applyDiscount($price){  
    $price = $price - self::getDiscount()*$price/100;    
    return $price;
  }
 
 
  /**
   * Обработчик шотркода вида [old-price id="7"]1060[/old-price].
   * Выводит новую цену товара, зачеркивая старую.
   */

  static function oldPrice($arg){
    $id = $arg['id'];
    $newPrice = $arg['content'];
    $oldPrice = isset(self::$arrayProducts[$id]['oldPrice'])?self::$arrayProducts[$id]['oldPrice']:'undefined';
    return "<span style='text-decoration:line-through; color: orange;'>".$oldPrice.' '.MG::getSetting('currency')."</span> <br/> <span>".$newPrice."</span>";
  }
   
}

Всё, плагин готов, его можно активировать и использовать! После активации у вас появится отдельная страница настроек скидок.

панель скидок в админке

Пишите свои комментарии в конце статьи, подписывайтесь на продолжение, в котором мы усовершенствуем плагин скидок, всего доброго дорогие друзья!

Шучу! 🙂

Конечно же, я объясню по порядку, что происходит в этом коде, и как оно работает.

Вникаем в код

Во-первых, мы создали отдельный класс DiscountPanel отвечающий за логику работы скидок, и самым интересным кодом в этом классе является код в теле конструктора:

1
2
3
4
5
6
7
8
9
10
11
12
public function __construct(){
    mgActivateThisPlugin(__FILE__, array(__CLASS__, 'createDateBase'));  
    mgAddAction(__FILE__, array(__CLASS__, 'pageSettingsPlugin'));
   
    if(!URL::isSection('mg-admin')){
      mgAddShortcode('old-price', array(__CLASS__, 'oldPrice'));      
      mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1);
      mgAddAction('models_product_getproduct' , array(__CLASS__, 'discountToProduct'), 1);
      mgAddAction('models_catalog_getlistproductbykeyword' , array(__CLASS__, 'discountToSearch'), 1);
      mgAddAction('smalcart_getcartdata' , array(__CLASS__, 'discountToSmalCart'), 1);      
    }    
  }

Для новичков в программировании он может быть несколько пугающим, но на самом деле является шаблонным для плагинов Moguta.CMS и поэтому достаточно один раз вникнуть в его суть.

В коде происходит привязка методов класса к разного рода событиям системы.

Например, строка:

1
mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1);

означает, что когда системой будет инициализировано событие ‘models_catalog_getlist’, то должен выполниться статический метод данного класса ‘discountToCatalog’, внеся свои коррективы в работу метода getList() в классе Models_Catalog.

Как видите, в коде используется несколько функций системы для задания привязок:

  • mgActivateThisPlugin — определяет метод класса, который будет происходить всякий раз при активации плагина.
  • mgAddShortcode – определяет обработчик для шорткода [old-price]
  • mgAddAction – позволяет привязать свой метод к определенному событию системы, подробнее о событиях читайте в статье "Система работы плагинов в Moguta.CMS"

В коде мы видим особое применение функции mgAddAction, в которую мы передаем директиву __FILE__:

1
mgAddAction(__FILE__, array(__CLASS__, 'pageSettingsPlugin'));

Такое применение привязывает метод данного класса ‘pageSettingsPlugin’, который будет отвечать за генерацию контента на странице настроек плагина в панели администрирования.

Еще один важный момент. Поскольку данный плагин немного специфичен и его методы действуют на все выводы цен, не только в публичной части, но и в админке, то нужно задать условие позволяющее применять скидку только для публичной части:

1
  if(!URL::isSection('mg-admin')){}

Методом URL::isSection мы вычислим, что работа ведется в административном разделе и предотвратим обработку вывода цен для продукта данным плагином.

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

  • createDateBase() — создает таблицу для скидок в БД при активации плагина;
  • pageSettingsPlugin() — выводит страницу настроек плагина в админке;
  • getDiscount() — получает текущую скидку на все товары;
  • discountToCatalog($arg) — применяет скидку к ценам выводимым для продуктов в каталоге;
  • discountToProduct($arg) — применяет скидку к ценам для продуктов в карточке товара;
  • discountToSearch($arg) — применяет скидку к ценам для продуктов в результате поискаа;
  • discountToSmalCart($arg) — применяет скидку к ценам для продуктов в маленькой корзине;
  • applyDiscount($price) — применяет скидку к ценам продуктов;
  • oldPrice($arg) — обработчик шотркода вида [old-price id=»7″]1060[/old-price]. Выводит новую цену товара, зачеркивая старую.

Немного о событиях

Заострим внимание на методах discountToCatalog($arg), discountToProduct($arg), discountToSearch($arg), discountToSmalCart($arg).

Всех их объединяет наверняка непонятный вам массив $arg.

На примере метода discountToCatalog(), параметр $arg – это массив аргументов передающийся при генерации движком события ‘models_catalog_getlist’, к которому привязан метод плагина:

1
mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1);

В данном случае в $arg[‘args’] попадут все переменные, которые были переданы в getList() в классе Models_Catalog, а в $arg[‘result’] результат работы метода getList().

Это значит, что если мы в методе discountToCatalog() просто вернем $arg[‘result’]:

1
2
3
  static function discountToCatalog($arg){  
     return $arg['result'];
  }

то ничего не изменится. А если в тело функции вставить какой-то код, влияющий на массив $arg[‘result’]:

1
2
3
4
5
6
7
8
9
10
11
12
static function discountToCatalog($arg){    
   
     foreach ($arg['result']['catalogItems']  as &$item) {
       // сохраняем старую цену продукта для последующего вывода шорткодом
       self::$arrayProducts[$item['id']]['oldPrice'] = $item['price'];
       $item['price'] = self::applyDiscount($item['price']);
       // сохраняем новую цену для продукта для последующего вывода шорткодом
       self::$arrayProducts[$item['id']]['newPrice'] = $item['price'];
     }          
   
     return $arg['result'];
  }

То результат будет на лицо:

плагин скидок с зачеркиванием старой цены

Четыре, практически, одинаковых метода нужны потому, что в разных местах сайта товары выводятся разными методами и поэтому генерируют разные события. Для каталога будет генерироваться событие ‘models_catalog_getlist’, для страницы с подробным описанием товара — ‘models_product_getproduct’, для результатов поиска — ‘models_catalog_getlistproductbykeyword’, для маленькой корзины — ‘smalcart_getcartdata’.

Шорткоды

Не менее интересным, в данном классе является метод oldPrice($arg). В отличии от рассмотренных ранее методов, этот привязан функцией:

1
mgAddShortcode('old-price', array(__CLASS__, 'oldPrice'));

которая определила шорткод [old-price], это значит, что всякий раз кода будет использоваться шорткод такого вида [old-price id=»7″]1060[/old-price], то в метод oldPrice($arg) будет попадать arg[‘id’]=7 и arg[‘content’]= 1060. Можно передавать любые аргументы на подобии ‘id’.
К примеру, если указать в шорткоде [old-price id=»7″ paramet =»exclusive»]содержание[/old-price], то $arg будет содержаться элементы:

1
array('id'=>7, 'paramet '=> 'exclusive', 'content'=>'содержание' );

Заключение

В данной статье мы рассмотрели код, несложного плагина скидок для Moguta.CMS. Я надеюсь, мои пояснения помогли вам усвоить основные принципы создания плагина. Напишите в комментариях, хотели бы вы увидеть продолжение материала и еще больше разобраться с разработкой плагинов для Moguta.CMS.

Скачать плагин скидок для Moguta.CMS ( Скачали: 320 чел. ) 

Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.

Нравится

Комментарии

  • Андрей

    Не работает. Выдает следующее:

    Ошибка в SQL запросе: SELECT `persent` FROM `mg_discount` WHERE `id`= 1
    Table ‘u511598273_tin.mg_discount’ doesn’t exist
    /home/u511598273/public_html/mg-plugins/discount-panel/index.php (line 92)
    /home/u511598273/public_html/mg-plugins/discount-panel/index.php (line 73)
    (line )
    /home/u511598273/public_html/mg-core/lib/eventhook.php (line 68)
    /home/u511598273/public_html/mg-core/lib/pm.php (line 207)
    /home/u511598273/public_html/mg-core/lib/mg.php (line 201)
    /home/u511598273/public_html/mg-admin/section/views/plugintemplate.php (line 10)
    /home/u511598273/public_html/mg-core/lib/mg.php (line 712)
    /home/u511598273/public_html/mg-core/lib/mg.php (line 513)
    /home/u511598273/public_html/mg-core/mg-start.php (line 49)
    /home/u511598273/public_html/index.php (line 86)

    • Спасибо, поправил в статье и перезалил архив.

  • tragis

    Плагин очень полезный и перспективный, ждем следующую статью по управлению скидками. Удачи Вам.

  • anlite

    Выдает ошибку
    Fatal error: Call to undefined method MG::getSetting() in Z:\home\localhost\www\mg-plugins\discount-panel\index.php on line 154

    • Видимо вы используете версию 3.0.2. Скачайте и установите обновленную CMS 3.0.3. Или замените в данном плагине все MG::getSetting() на MG::getOption().

  • Для того чтобы вывести зачеркнутую цену нужно:
    вставить шорткоды
    [old-price id=»< ?php echo $item["id"] ?>«]< ?php echo $item["price"] ?>[/old-price]
    этот в catalog.php
    [old-price id=»< ?php echo $data["id"] ?>«]< ?php echo $data["price"] ?>[/old-price]
    этот в product.php

  • webyuk

    Этот плагин применяется ко всем товарам, а можно как то его модифицировать, чтобы он применялся к конкретному товару? Или только к одной категории?

    • Это есть в планах. В следующей части статьи я опишу как это реализовать.

  • Виктор

    возможно ли написание плагина, с включением которого будет появляться поле при редактировании товара, например чтобы старая цена была полем при редактировании товара?

    • Возможно, пишите на мейл, обсудим стоимость.

  • Дмитрий

    Здравствуйте Mark!
    Подскажите пожалуйста — как вывести на продуктах в Каталоге(обычную) зачеркнутую цену… имеющуюся в стандартном функционале шаблона. И ещё сразу как вывести под продуктами в Каталоге сразу и выбор размеров.
    Что бы накидывать в корзину сразу из каталога. Спасибо.

    • В новой версии системы, зачеркивание старой цены реализована базовым функционалом.

  • Алексей

    Скидка НЕ применяется к товара с пометками New и рекомендуемые, которые выводятся отдельным блоком.

  • Женя

    Здравствуйте подскажите пожалуйста поставил плагин он везде работает кроме описания товара discountToProduct… Видимо движок новый и getProduct уже переписан. Подскажите пожалуйста как изменить discountToProduct чтоб он заработал. Большое спасибо

  • Оставить комментарий

    Подписаться на комментарии к этой статье по RSS

    Яндекс.Метрика