Version: current

      1 <?php
      2
      3 /**
      4  * Страница расширенного поиска по каталогу товаров
      5  *
      6  * @package Catalog
      7  * @author menedem, dvp
      8  */
      9 class ProductSearchPage extends Page {
     10
     11     //static $icon = 'cms/images/treeicons/element'; //!!!!
     12     static $can_be_root = true;
     13     static $allowed_children = 'none';
     14
     15     static $defaults = array(
     16         'DevEditType' => 'Fixed',
     17     );
     18
     19     // поля Product для поиска (Поле => Таблица)
     20     protected static $search_fields = array('Title' => 'SiteTree', 'Content' => 'SiteTree', 'Description' => 'Product', 'Vendor' => 'Product', 'SKU' => 'Product');
     21
     22     /**
     23      * Задаем поля для поиска $search_fields
     24      *
     25      * @param array формат: ('Field' => 'Table')
     26      *
     27      */
     28     static function set_product_search_fields($fields) {
     29         self::$search_fields = $fields;
     30     }
     31
     32     /**
     33      * Поля Product для поиска
     34      *
     35      * @return array $value
     36      */
     37     static function get_product_search_fields() {
     38         return self::$search_fields;
     39     }
     40
     41     // флаг - показывать полную форму поиска (с выбором раздела, производителя и фильтра по цене)
     42     protected static $show_full_search_form = false;
     43
     44     /**
     45      * Задаем флаг $show_full_search_form
     46      *
     47      * @param bool $value
     48      *
     49      */
     50     static function set_show_full_search_form($value=true) {
     51         self::$show_full_search_form = $value;
     52     }
     53
     54     /**
     55      * Флаг $show_full_search_form
     56      *
     57      * @return bool $value
     58      */
     59     static function get_show_full_search_form() {
     60         return self::$show_full_search_form;
     61     }
     62
     63     /**
     64      * Возвращает список категорий для селекта в форме поиска
     65      *
     66      * @return array()
     67      */
     68     function getCategoryMap() {
     69         if ($start = DataObject::get('StartCatalog')) {
     70             // Сначала ищем есть ли StartCatalog
     71             $categories = DataObject::get('Catalog', '"SiteTree"."ShowInSearch"=1 AND "SiteTree"."ParentID" IN ('.join(',', $start->Column('ID')).')', 'Title');
     72         }
     73
     74         if (!$categories) {
     75             // если нет - ищем рубрики в корне
     76             $categories = DataObject::get('Catalog', '"SiteTree"."ShowInSearch"=1 AND "SiteTree"."ParentID"=0', 'Title'); //  AND ClassName='Catalog'
     77         }
     78
     79         if (!$categories) {
     80             // если и их нет - все корневые рубрики где бы они не находились
     81             $categories = DataObject::get(
     82                 'Catalog',
     83                 '"SiteTree"."ShowInSearch"=1 AND "ST_Parent"."ClassName"!=\'Catalog\'',
     84                 'Title',
     85                 'LEFT JOIN "SiteTree" AS ST_Parent ON "SiteTree"."ParentID"="ST_Parent"."ID"'
     86             );
     87         }
     88
     89         $this->extend('updateCategoryMap', $categories);
     90         return ($categories) ? $categories->toDropdownMap() : array();
     91     }
     92
     93     /**
     94      * Возвращает список из ID рубрики и всех ее подрубрик
     95      *
     96      * @param Catalog $parent
     97      *
     98      * @return array
     99      */
    100     function getSubCategoryID($parent) {
    101         $res = array($parent->ID);
    102
    103         $subcats = $parent->Subcats;
    104         if ($subcats) {
    105             foreach($subcats as $item) {
    106                 //Кладем основную категорию в список
    107                 $res = array_merge($res, $this->getSubCategoryID($item));
    108             }
    109         }
    110         return $res;
    111     }
    112
    113     /**
    114      * Возвращает производителей товаров для выпадающего списка
    115      *
    116      * @return array
    117      */
    118     function getVendorMap() {
    119         $vendors = DB::Query("SELECT DISTINCT Vendor FROM Product ORDER BY Vendor")->column('Vendor');
    120         $this->extend('updateVendorMap', $vendors);
    121         return ($vendors) ? array_combine($vendors, $vendors) : false;
    122     }
    123
    124     function canCreate() {
    125         if (!Director::isDev()) return false;
    126         return (DataObject::get_one('ProductSearchPage')) ? false : parent::canCreate();
    127     }
    128
    129     function canDelete() {
    130         return (Director::isDev()) ? parent::canDelete() : false;
    131     }
    132
    133 }
    134
    135 class ProductSearchPage_Controller extends Page_Controller {
    136     static $allowed_actions = array('ProductSearchForm');
    137
    138     function Form() {
    139         return $this->ProductSearchForm();
    140     }
    141
    142     /**
    143      * Возвращает форму поиска товара в каталоге
    144      * Форму можно изменить с помощью расширений определив метод updateProductSearchForm(&$from)
    145      *
    146      * @return Form
    147      */
    148     function ProductSearchForm() {
    149         $fields = new FieldSet();
    150         $fields->push(new TextField('Search', _t('ProductSearchForm.Search', 'Search text')));
    151         if (ProductSearchPage::get_show_full_search_form()) {
    152             $fields->push(new NumericField('PriceMin', _t('ProductSearchForm.PriceMin', 'Price from')));
    153             $fields->push(new NumericField('PriceMax', _t('ProductSearchForm.PriceMax', 'Price to')));
    154
    155             $categories = $this->getCategoryMap();
    156             if ($categories && count($categories) > 1) {
    157                 $fields->insertBefore(new DropdownField('Category', _t('ProductSearchForm.Category', 'Category'), $categories, '', null, _t('ProductSearchForm.AllCategory', 'All categories')), 'PriceMin');
    158             }
    159
    160             $vendors = $this->getVendorMap();
    161             if ($vendors && count($vendors) > 1) {
    162                 $fields->insertBefore(new DropdownField('Vendor', _t('ProductSearchForm.Vendor', 'Vendor'), $vendors, '', null, _t('ProductSearchForm.AllVendor', 'All vendors')), 'PriceMin');
    163             }
    164         }
    165
    166         $form = new Form(
    167             $this,
    168             'ProductSearchForm',
    169             $fields,
    170             new FieldSet(
    171                 new FormAction('searchproduct',  _t('ProductSearchForm.SearchButton', 'Search'))
    172             ),
    173             new RequiredFields('Search')
    174         );
    175         $form->setFormMethod('GET');
    176         $form->disableSecurityToken();
    177         $form->setTemplate('ProductSearchForm');
    178
    179         $this->extend('updateProductSearchForm', $form);
    180         if ($this->getRequest()) {
    181             $form->loadDataFrom($this->getRequest()->requestVars());
    182         }
    183
    184         return $form;
    185     }
    186
    187     /**
    188      * Выполняет поиск товаров в каталоге
    189      * Фильтр можно изменить с помощью расширений определив метод updateProductSearchFilter(&$filter)
    190      *
    191      * @param array $data - массив с заполнеными полями формы
    192      * @param Form $form - форма поиска
    193      *
    194      * @return string - страницу с результатами поиска
    195      */
    196     function searchproduct($data, $form) {
    197         $res = array('SearchActive' => true, 'Results' => false);
    198
    199         $search = Convert::raw2sql(preg_replace('/([%_])/', '\\\$1', $data['Search']));
    200         $filter = array();
    201         foreach(ProductSearchPage::get_product_search_fields() as $field=>$table) {
    202             $filter[] = "\"{$table}\".\"{$field}\" LIKE '%$search%'";
    203         }
    204         $filter = '(' . implode(' OR ', $filter) . ')';
    205
    206         if (isset($data['Category']) && $category = (int) $data['Category']) {
    207             $current = DataObject::get_by_id('Catalog', $category);
    208             if (!$current) die('Неправильная категория'); //!!! надо выводить более гуманную ошибку
    209
    210             $filter .= " AND \"SiteTree\".\"ParentID\" IN (" . implode(",", $this->getSubCategoryID($current)) . ")";
    211         }
    212
    213         if (isset($data['Vendor']) && $vendor = Convert::raw2sql($data['Vendor'])) {
    214             $filter .= " AND Vendor = '$vendor'";
    215         }
    216
    217         if (isset($data['PriceMin']) && $priceMin = (int) $data['PriceMin']) {
    218             $filter .= " AND Price >= '$priceMin'";
    219         }
    220
    221         if (isset($data['PriceMax']) && $priceMax = (int) $data['PriceMax']) {
    222             $filter .= " AND Price <= '$priceMax'";
    223         }
    224
    225         $offset = (int) $this->getRequest()->requestVar('start');
    226         $pageSize = ($this->SiteConfig()->ProductPerPage > 0) ? $this->SiteConfig()->ProductPerPage : 20;
    227         $filter .= ' AND "ShowInSearch"=1';
    228
    229         $this->extend('updateProductSearchFilter', $filter, $search, $res);
    230         $res['SearchResults'] = DataObject::get('Product', $filter, 'Price', '', "$offset,$pageSize");
    231         $templates = array('ProductSearchPage','Page');
    232         if (Director::is_ajax()) array_unshift($templates, 'ProductSearchPage_ajax');
    233
    234         return $this->renderwith($templates, $res);
    235     }
    236 }

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -