1 <?php
2
3 4 5 6 7 8
9 class Catalog extends Page {
10
11 static $icon = array('cms/images/treeicons/folder', 'folder');
12 static $allowed_children = array('Product', '*Catalog', 'SpecialCatalog');
13 static $default_child = 'Product';
14
15 static $default_sort = 'Title ASC';
16
17 static $db = array(
18 'Description' => 'Text',
19 'OwnFilter' => 'Boolean',
20 'OwnParams' => 'Boolean',
21
22 'StandartView' => 'Varchar',
23 'ImportID' => 'Varchar',
24
25 'GroupTitle' => 'Varchar(255)',
26 );
27
28 static $defaults = array(
29 'AutoChild' => 0,
30 'OwnFilter' => false,
31 'OwnParams' => false,
32 );
33
34 static $has_one = array(
35 'Photo' => 'Image',
36 'CatalogVAT' => 'VAT',
37 );
38
39 static $has_many = array(
40 'Params' => 'ProductParam',
41 'CatalogFilters' => 'CatalogFilter'
42 );
43
44
45 static $many_many = array(
46 'EnabledParams' => 'ProductParam',
47 'EnabledCatalogFilters' => 'CatalogFilter'
48 );
49
50 static $indexes = array(
51 'ImportID' => true,
52 );
53
54 static $subpage_children = 'Product';
55
56 57 58 59 60
61 static function get_sort_options() {
62 $productClass = self::$subpage_children;
63 return array_keys($productClass::get_sort_options());
64 }
65
66 67 68
69 private static $view_options = array('tile');
70
71 72 73 74 75 76
77 static function set_view_options(array $data) {
78 self::$view_options = $data;
79 }
80
81 82 83 84 85
86 static function get_view_options() {
87 return self::$view_options;
88 }
89
90 91 92 93 94 95 96
97 static function view_options_dropdown_map($addDefault = false) {
98 $map = array();
99 if ($addDefault) {
100 $map[''] = _t('Catalog.ViewOption_default', 'Default');
101 }
102 foreach (self::get_view_options() as $key) {
103 $map[$key] = _t('Catalog.ViewOption_'.$key, ucfirst($key));
104 }
105 return $map;
106 }
107
108 109 110
111 private static $user_can_change_view = false;
112
113 114 115 116 117
118 static function allow_user_change_view($val = true) {
119 self::$user_can_change_view = $val;
120 }
121
122 123 124 125
126 static $pagesize_options = array();
127
128 129 130 131 132
133 static function set_pagesize_options($list) {
134 self::$pagesize_options = $list;
135 }
136
137 138 139 140 141
142 static function get_pagesize_options() {
143 return self::$pagesize_options;
144 }
145
146 147 148 149 150 151 152
153 static function pagesize_dropdown_map($addDefault = false) {
154 $map = array();
155 if ($addDefault) {
156 $map[''] = _t('Catalog.PageSize_default', 'Default');
157 }
158 foreach (self::get_pagesize_options() as $key) {
159 $map[$key] = _t('Catalog.PageSize_'. $key, ucfirst($key));
160 }
161 return $map;
162 }
163
164 165 166
167 private static $user_can_change_pagesize = false;
168
169 170 171 172 173
174 static function allow_user_change_pagesize($val = true) {
175 self::$user_can_change_pagesize = $val;
176 }
177
178 179 180
181 static $use_additional_params = true;
182
183 184 185 186 187
188 static function disable_additional_params() {
189 self::$use_additional_params = false;
190 }
191
192 193 194
195 static $use_additional_filters = true;
196
197 198 199 200 201
202 static function disable_additional_filters() {
203 self::$use_additional_filters = false;
204 }
205
206 207 208
209 static $reduce_filters = false;
210
211 212 213 214 215
216 static function enable_reduce_filters() {
217 self::$reduce_filters = true;
218 }
219
220 221 222
223 static $use_variations = false;
224
225 226 227 228 229
230 static function enable_variations() {
231 self::$use_variations = true;
232 }
233
234 235 236 237
238 static $hide_allow_purchase_products = false;
239
240 241 242 243 244
245 static function hide_allow_purchase_products($val) {
246 self::$hide_allow_purchase_products = $val;
247 }
248
249 250 251
252 static $filter_calc_suitable_products_mode = false;
253
254 255 256 257 258 259 260 261 262
263 static function set_filter_calc_suitable_products_mode($val) {
264 if (in_array($val, array(false, 'one_filter', 'all_filters'))) {
265 self::$filter_calc_suitable_products_mode = $val;
266 }
267 }
268
269 270 271 272 273
274 static function CatalogSearch($text, $neededCount) {
275 $text = Convert::raw2sql(trim(preg_replace('/([%_])/', '\\\$1', $text)));
276 $where = "Title LIKE '%$text%'";
277 $rs = DataObject::get('Catalog', $where, 'Title', '', $neededCount);
278 return $rs;
279 }
280
281
282
283 static $cache = false;
284
285 286 287
288 static function get_cache() {
289 if (!self::$cache) {
290 self::$cache = SS_Cache::factory('catalog');
291 }
292 return self::$cache;
293 }
294
295 296 297 298 299
300 static function get_cached_data($key) {
301 if (!$key) return false;
302 return unserialize(self::get_cache()->load($key));
303 }
304
305 306 307 308 309 310
311 static function set_cached_data($key, $data) {
312 if (!$key) return false;
313 return self::get_cache()->save(serialize($data), $key);
314 }
315
316 317 318
319 static function clean_cache() {
320 return self::get_cache()->clean();
321 }
322
323
324 325 326
327 static $possibleFields = array('Title', 'Description', 'Content', 'URLSegment', 'MenuTitle', 'MetaTitle', 'MetaDescription', 'MetaKeywords', 'Sort');
328
329 330 331 332 333
334 static function addPossibleFields($fields) {
335 if ($fields)
336 foreach($fields as $field)
337 self::$possibleFields[] = $field;
338 }
339
340 341 342 343
344 static function import_find($importID) {
345 return DataObject::get_one('Catalog', "ImportID = '" . Convert::raw2sql($importID) . "'");
346 }
347
348 349 350 351 352 353 354
355 function importUpdate($importLog, $data) {
356 if (!$this->importValidate($importLog, $data)) {
357 return false;
358 }
359
360 $rs = $this->extend('onBeforeImport', $importLog, $data);
361 if ($rs && max($rs) == false) return false;
362
363 if (isset($data['id'])) {
364 $this->ImportID = $data['id'];
365 }
366
367 foreach(self::$possibleFields as $field) {
368 if (isset($data[$field]))
369 $this->{$field} = $data[$field];
370 }
371
372 if (isset($data['Photo'])) {
373 $this->PhotoID = ($data['Photo']) ? $data['Photo']->ID : 0;
374 }
375
376 if (isset($data['ParentID']) && !$this->ParentID) {
377 $this->ParentID = $data['ParentID'];
378 }
379 if (isset($data['Publish'])) {
380 if ($data['Publish']) {
381 $this->doPublish();
382 } else {
383 $this->doUnpublish();
384 }
385 } else {
386
387 if ($this->isPublished()) {
388 $this->doPublish();
389 } else {
390 $this->write();
391 }
392 }
393 if (isset($data['Unpublish']) && $data['Unpublish']) {
394 $this->doUnpublish();
395 }
396 $this->extend('onAfterImport', $importLog, $data);
397 return true;
398 }
399
400 401 402 403 404
405 function importValidate($importLog, $data) {
406 if ((!$this->Title) && (!isset($data['Title']) || trim($data['Title']) == '')) {
407 $importLog->addLog("Раздел каталога с id='{$data['id']}' не имеет названия!", 'error');
408 return false;
409 }
410 if (isset($data['Title']) && trim($data['Title']) == '') {
411 $importLog->addLog("Раздел каталога с id='{$data['id']}' не имеет названия!", 'error');
412 return false;
413 }
414 if ((!$this->Title) && (!isset($data['Title']) || trim($data['Title']) == '')) {
415 $importLog->addLog("Раздел каталога с id='{$data['id']}' не имеет названия!", 'error');
416 return false;
417 }
418 if (isset($data['Sort']) && $data['Sort'] != (int)$data['Sort']) {
419 $importLog->addLog("Параметр Sort раздела каталога {$data['Title']} не является целым числом!", 'warning');
420 $data['Sort'] = 0;
421 }
422 $rs = $this->extend('importValidate', $importLog, $data);
423 if ($rs && max($rs) == false) return false;
424 return true;
425 }
426
427 428 429
430 function importClearAll($importLog) {
431 $oldMode = Versioned::get_reading_mode();
432
433 Versioned::reading_stage('Stage');
434 $catalogs = DataObject::get('Catalog', "ClassName <> 'SpecialCatalog' AND ClassName <> 'StartCatalog'");
435 if ($catalogs)
436 foreach($catalogs as $catalog) {
437 $catalog->doUnpublish();
438 $catalog->delete();
439 }
440 unset($catalogs);
441
442 Versioned::reading_stage('Live');
443 $catalogs = DataObject::get('Catalog', "ClassName <> 'SpecialCatalog' AND ClassName <> 'StartCatalog'");
444 if ($catalogs)
445 foreach($catalogs as $catalog) {
446 $catalog->doUnpublish();
447 $catalog->delete();
448 }
449
450 Versioned::set_reading_mode($oldMode);
451 }
452
453
454 455 456 457 458 459 460 461
462 static function get_unique_values($filter, $productsSQL) {
463
464 $stage = (Versioned::current_stage() == 'Live' ? '_Live' : '');
465 if ($table = self::productFieldTable($filter->FilterField)) {
466 $data = DB::Query("SELECT DISTINCT {$filter->FilterField} as Value FROM \"{$table}{$stage}\" WHERE \"{$table}{$stage}\".ID IN (SELECT \"SiteTree{$stage}\".ID FROM \"SiteTree{$stage}\" JOIN \"Product{$stage}\" ON \"SiteTree{$stage}\".\"ID\" = \"Product{$stage}\".\"ID\" WHERE {$productsSQL}) ORDER BY {$filter->FilterField}");
467 } else {
468 $sort = 'ORDER BY Value';
469
470 $productParam = DataObject::get_one('ProductParam', "TechTitle = '{$filter->FilterField}'");
471
472 if ($productParam && $productParam->Type == 'number') {
473 $sort = 'ORDER BY (Value+0)';
474 }
475 $data = DB::Query("SELECT DISTINCT Value FROM ProductParamValue WHERE TechTitle = '{$filter->FilterField}' AND ProductID IN (SELECT \"SiteTree{$stage}\".ID FROM \"SiteTree{$stage}\" JOIN \"Product{$stage}\" ON \"SiteTree{$stage}\".\"ID\" = \"Product{$stage}\".\"ID\" WHERE {$productsSQL}) {$sort}");
476 }
477
478 $rs = array();
479 if ($data->numRecords()) {
480 foreach($data as $entry) {
481 if ($entry['Value']) {
482 $rs[$entry['Value']] = $entry['Value'];
483 }
484 }
485 }
486 return $rs;
487 }
488
489 490 491 492 493 494 495 496
497 static function get_min_max_values($filter, $productsSQL) {
498 $stage = (Versioned::current_stage() == 'Live' ? '_Live' : '');
499 if ($table = self::productFieldTable($filter->FilterField)) {
500 $data = DB::Query("SELECT MIN({$filter->FilterField}) as MinVal, MAX({$filter->FilterField}) as MaxVal FROM \"{$table}{$stage}\" WHERE \"{$table}{$stage}\".ID IN (SELECT \"SiteTree{$stage}\".ID FROM \"SiteTree{$stage}\" JOIN \"Product{$stage}\" ON \"SiteTree{$stage}\".\"ID\" = \"Product{$stage}\".\"ID\" WHERE {$productsSQL})");
501 } else {
502
503 $data = DB::Query("SELECT MIN(Value+0) as MinVal, MAX(Value+0) as MaxVal FROM ProductParamValue WHERE TechTitle = '{$filter->FilterField}' AND ProductID IN (SELECT \"SiteTree{$stage}\".ID FROM \"SiteTree{$stage}\" JOIN \"Product{$stage}\" ON \"SiteTree{$stage}\".\"ID\" = \"Product{$stage}\".\"ID\" WHERE {$productsSQL})");
504 }
505 return $data;
506 }
507
508 function getCMSFields() {
509 SiteTree::disableCMSFieldsExtensions();
510 $fields = parent::getCMSFields();
511 SiteTree::enableCMSFieldsExtensions();
512
513 $fields->addFieldToTab('Root.Content.Main', new ImageField('Photo', $this->fieldLabel('Photo')), 'Content');
514 $fields->addFieldToTab('Root.Content.Main', new TextField('ImportID', $this->fieldLabel('ImportID')), 'Content');
515 $fields->addFieldToTab('Root.Content.Main', new TextareaField('Description', $this->fieldLabel('Description')), 'Content');
516
517 if (count(self::get_view_options()) > 1)
518 $fields->addFieldToTab('Root.Content.Main', new DropdownField("StandartView", $this->fieldLabel('StandartView'), self::view_options_dropdown_map(true)), 'Description');
519
520 if ($allVATs = DataObject::get('VAT')) {
521 $fields->addFieldToTab('Root.Content.Main', new DropdownField("CatalogVATID", $this->fieldLabel('CatalogVAT'), $allVATs->map('ID', 'Title', _t('VAT.SelectVAT'))));
522 }
523
524 $fields->addFieldToTab('Root.Content', new Tab('FullContent', _t('Catalog.tab_FullContent', 'Content')), 'Metadata');
525 $fields->addFieldToTab('Root.Content.FullContent', $fields->dataFieldByName('Content'));
526 if ($allVATs = DataObject::get('VAT')) {
527 $fields->addFieldToTab('Root.Content.Main', new DropdownField("CatalogVATID", $this->fieldLabel('CatalogVAT'), $allVATs->map('ID', 'Title', _t('VAT.SelectVAT'))), 'Description');
528 }
529
530
531 Requirements::css('catalog/css/ProductAdmin.css');
532
533
534
535 $fields->addFieldToTab('Root.Content', new Tab('tabSubPages', _t('Catalog.tab_Products', 'Products')), 'Metadata');
536
537 $class = $this->class;
538
539 $sp = new SubpageListField('Subpages', $this, $class::$subpage_children);
540 $sp->Dragable = true;
541 $url = '<a href=\"admin/show/$ID\">$value</a>';
542
543 $sp->setFieldFormatting(array_combine(array_keys(singleton($class::$subpage_children)->summaryFields()), array_fill(0, count(singleton($class::$subpage_children)->summaryFields()), $url)));
544 $fields->addFieldToTab('Root.Content.tabSubPages', $sp);
545
546 if (Catalog::$use_additional_params) {
547
548 $tab = $fields->findOrMakeTab('Root.Content.Params', _t('Catalog.ProductParams', 'Product Params'));
549 $tab->push(new LiteralField('CatalogParams', '<h4>'.$this->fieldLabel('Params').'</h4>'));
550 $ctf = new ComplexTableField(
551 $this,
552 'Params',
553 'ProductParam'
554 );
555 $ctf->setRelationAutoSetting(true);
556 $tab->push($ctf);
557
558 $tab->push(new CheckboxField('OwnParams', $this->fieldLabel('OwnParams')));
559 if (!$this->OwnParams) {
560 $tab->push(new LiteralField('OwnParamsOnly', '<p>'._t('Catalog.OwnParamsOnly').'</p>'));
561 } else {
562
563 if (($params = $this->getAllCatalogParams()) && $params->Count()) {
564 $ctf = new ManyManyDataObjectManager(
565 $this,
566 'EnabledParams',
567 'ProductParam',
568 array('Title'=>'Title', 'TechTitle'=>'TechTitle', 'LocalType'=>'Type'),
569 null,
570 "ProductParam.ID IN (".implode(',', $params->map('ID', 'ID')).")"
571 );
572 $ctf->setPermissions(array());
573 $ctf->setPluralTitle($this->fieldLabel('EnabledParams'));
574
575 $tab->push($ctf);
576 }
577 }
578 }
579
580 if (Catalog::$use_additional_filters) {
581
582 $tab = $fields->findOrMakeTab('Root.Content.Filters', _t('Catalog.CatalogFilters', 'Catalog Filters'));
583
584 $tab->push(new LiteralField('CatalogFilters', '<h4>'.$this->fieldLabel('CatalogFilters').'</h4>'));
585 $ctf = new ComplexTableField(
586 $this,
587 'CatalogFilters',
588 'CatalogFilter'
589 );
590 $ctf->setRelationAutoSetting(true);
591 $tab->push($ctf);
592
593 $tab->push(new CheckboxField('OwnFilter', $this->fieldLabel('OwnFilter')));
594 if (!$this->OwnFilter) {
595 $tab->push(new LiteralField('OwnParamsOnly', '<p>'._t('Catalog.OwnFilterOnly').'</p>'));
596 } else {
597
598 if (($filters = $this->getAllCatalogFilters()) && $filters->Count()) {
599 $ctf = new ManyManyDataObjectManager(
600 $this,
601 'EnabledCatalogFilters',
602 'CatalogFilter',
603 array('Title'=>'Title', 'LocalFilterField'=>'FilterField', 'LocalType'=>'Type'),
604 null,
605 "CatalogFilter.ID IN (".implode(',', $filters->map('ID', 'ID')).")"
606 );
607
608 $ctf->setPermissions(array());
609 $ctf->setPluralTitle($this->fieldLabel('EnabledCatalogFilters'));
610 $tab->push($ctf);
611 }
612 }
613 }
614
615 $this->extend('updateCMSFields', $fields);
616 return $fields;
617 }
618
619 function onAfterWrite() {
620 parent::onAfterWrite();
621 }
622
623 function onAfterDelete() {
624 if ($this->IsDeletedFromStage && !$this->ExistsOnLive) {
625 if ($this->EnabledParams()) {
626 $this->EnabledParams()->removeAll();
627 }
628 if ($this->EnabledCatalogFilters()) {
629 $this->EnabledCatalogFilters()->removeAll();
630 }
631 if ($this->Params()) {
632 foreach ($this->Params() as $obj) {
633 $obj->delete();
634 }
635 }
636 if ($this->CatalogFilters()) {
637 foreach ($this->CatalogFilters() as $obj) {
638 $obj->delete();
639 }
640 }
641 }
642 parent::onAfterDelete();
643 }
644
645 function getVAT(){
646 if ($this->CatalogVATID && ($vat = $this->CatalogVAT())) {
647 return $vat;
648 }
649 if ($this->ParentID && ($parent = $this->Parent()) && is_a($parent, 'Catalog')) {
650 return $this->Parent()->getVAT();
651 }
652 return SiteConfig::current_site_config()->DefaultVAT();
653 }
654
655 656 657 658 659
660 public function AllowChangeView() {
661 return self::$user_can_change_view && (count(self::$view_options) > 1);
662 }
663
664 665 666 667 668
669 public function AllowChangePageSize() {
670 return self::$user_can_change_pagesize && (count(self::$pagesize_options) > 1);
671 }
672
673 674 675 676 677
678 public function Subcats() {
679 return DataObject::get("Catalog", "ParentID = {$this->ID} AND ShowInMenus=1", "Sort");
680 }
681
682 683 684 685 686
687 public function CountItems() {
688 $count = 0;
689 if ($items = DataObject::get("Product", "ParentID = {$this->ID}")) {
690 $count += $items->Count();
691 }
692 return $count;
693 }
694
695 696 697 698 699
700 public function defaultSort() {
701 return ($this->SiteConfig->CatalogDefaultSort)? $this->SiteConfig->CatalogDefaultSort : 'title';
702 }
703
704 705 706 707 708
709 public function defaultView() {
710 if ($this->StandartView)
711 return $this->StandartView;
712
713 return ($this->SiteConfig->CatalogDefaultView) ? $this->SiteConfig->CatalogDefaultView : 'tile';
714 }
715
716 717 718 719 720
721 public function defaultPageSize() {
722 return ($this->SiteConfig->ProductPerPage)? $this->SiteConfig->ProductPerPage : 30;
723 }
724
725 726 727 728 729
730 public function catalogFilterFields() {
731 $filters = false;
732 if ($this->OwnFilter) {
733 $filters = $this->EnabledCatalogFilters();
734 return $filters;
735 }
736 if ($this->ParentID && $this->Parent() && is_a($this->Parent(), 'Catalog')) {
737 $filters = $this->Parent()->catalogFilterFields();
738 }
739
740 if (!$filters && ($rootFilters = DataObject::get('CatalogFilter', "ParentCatalogID = 0 AND ShowDefault = 1"))) {
741 $filters = $rootFilters;
742 }
743 return $filters;
744 }
745
746
747 function getAllCatalogFilters() {
748 $filters = $this->CatalogFilters();
749 if ($this->getAncestors( )) {
750 foreach($this->getAncestors( ) as $ancestor) {
751 if (is_a($ancestor, 'Catalog') && $ancestor->CatalogFilters()) {
752 $filters->merge($ancestor->CatalogFilters());
753 }
754 }
755 }
756
757 if ($rootFilters = DataObject::get('CatalogFilter', "ParentCatalogID = 0")) {
758 $filters->merge($rootFilters);
759 }
760 return $filters;
761 }
762
763 764 765 766 767
768 public function catalogParams() {
769 $params = false;
770 if ($this->OwnParams) {
771 return $this->EnabledParams();
772 }
773 if ($this->ParentID && $this->Parent() && is_a($this->Parent(), 'Catalog')) {
774 $params = $this->Parent()->catalogParams();
775 }
776
777 if ((!$params || !$params->Count()) && ($rootParams = DataObject::get('ProductParam', "ParentCatalogID = 0 AND ShowDefault = 1"))) {
778 $params = $rootParams;
779 }
780 return $params;
781 }
782
783
784 function getAllCatalogParams() {
785 $params = $this->Params();
786 if ($this->getAncestors( )) {
787 foreach($this->getAncestors( ) as $ancestor) {
788 if (is_a($ancestor, 'Catalog') && $ancestor->Params()) {
789 $params->merge($ancestor->Params());
790 }
791 }
792 }
793 if ($rootParam = DataObject::get('ProductParam', "ParentCatalogID = 0 AND ShowDefault = 1")) {
794 $params->merge($rootParam);
795 }
796 return $params;
797
798 }
799
800
801 function getVariationCatalogParams() {
802 if ($params = $this->catalogParams()) {
803 $variationParams = new DataObjectSet();
804 foreach($params as $param) {
805 if ($param->ParamForVariation) {
806 $variationParams->push($param);
807 }
808 }
809 return $variationParams;
810 }
811 return false;
812 }
813
814
815 function getNonVariationCatalogParams() {
816 if ($params = $this->catalogParams()) {
817 $nonVariationParams = new DataObjectSet();
818 foreach($params as $param) {
819 if (!$param->ParamForVariation) {
820 $nonVariationParams->push($param);
821 }
822 }
823 return $nonVariationParams;
824 }
825 return false;
826 }
827
828 829 830 831 832 833
834 static function productFieldTable($field) {
835 if (!singleton(self::$subpage_children)->hasField($field)) {
836 return false;
837 }
838 $classes = array_reverse(ClassInfo::ancestry(singleton(self::$subpage_children)));
839 foreach($classes as $class) {
840 $fields = Object::uninherited_static($class, 'db');
841 if (isset($fields[$field])) {
842 return $class;
843 }
844 }
845 return false;
846 }
847
848 849 850 851 852 853 854 855 856
857 public function filteredProducts($order=null, $filters=null, $limit=null) {
858 $orderby = false;
859 if (!is_null($order)) {
860 $orderby = Product::sort_options_orderby($order);
861 }
862 if (!$orderby) {
863 $orderby = Product::sort_options_orderby($this->defaultSort());
864 }
865
866 $query = $this->getProductsListQuery($orderby, $limit);
867 if ($filters) {
868
869 $query = $this->updateQueryByProductParamFilters($filters, $query);
870 }
871 $this->extend('updateFilteredProductsQuery', $query, $filters);
872 $results = DataObject::buildDataObjectSet($query->execute());
873 if($results) $results->parseQueryLimit($query);
874 return $results;
875 }
876
877 function getProductsListQuery($orderby=null, $limit=null) {
878 $where = $this->getProductsListWhere();
879 $query = singleton('SiteTree')->extendedSQL(implode(' AND ', $where), $orderby, $limit);
880 return $query;
881 }
882
883 884 885 886 887 888
889 function getProductsListWhere($forceShowProductsFromSubCategories=false) {
890 $sc = SiteConfig::current_site_config();
891 $where = array();
892
893 $productClasses = array();
894 if($subclasses = ClassInfo::subclassesFor(self::$subpage_children)) {
895 foreach ($subclasses as $subclass)
896 $productClasses[] = $subclass;
897 } else {
898 $productClasses[] = self::$subpage_children;
899 }
900 $where[] = "(ClassName IN ('".implode("','", $productClasses)."'))";
901
902 $categoryIDs = array($this->ID);
903
904 if ($sc->ShowProductsFromSubCategories || $forceShowProductsFromSubCategories) {
905 $categoryIDs = $this->getDescendantIDList();
906 $categoryIDs[] = $this->ID;
907 }
908 $where[] = "(ParentID IN (".implode(',', $categoryIDs) ."))";
909
910
911 if (self::$hide_allow_purchase_products) {
912 $where[] = "(AllowPurchase = 1)";
913 }
914 return $where;
915 }
916
917
918 function updateQueryByProductParamFilters($filters, $query) {
919 920 921 922 923
924
925 $stage = (Versioned::current_stage() == 'Live' ? '_Live' : '');
926 $query->renameTable('SiteTree', 'SiteTree'. $stage);
927 $paramsWhere = array();
928
929 foreach($filters as $key=>$value) {
930 $filter = DataObject::get_one('CatalogFilter', "FilterField = '".Convert::raw2sql($key)."'");
931 if ($filter && $value) {
932 switch ($filter->Type) {
933 case 'bool':
934 case 'boolgroup':
935 case 'list':
936 $value = Convert::raw2sql($value);
937 if (self::productFieldTable($filter->FilterField)) {
938 $query->where[] = "{$filter->FilterField} = '{$value}'";
939 } else {
940
941 $paramsWhere[] = "SELECT DISTINCT ProductID FROM ProductParamValue WHERE TechTitle = '{$filter->FilterField}' AND Value = '{$value}'";
942 }
943 break;
944 case 'slider':
945
946 if (self::productFieldTable($filter->FilterField)) {
947 $sliderWhere = array();
948 if (isset($value['min'])) {
949 $sliderWhere[] = "{$filter->FilterField} >= ".((int)$value['min']);
950 }
951 if (isset($value['max'])) {
952 $sliderWhere[] = "{$filter->FilterField} <= ".((int)$value['max']);
953 }
954 if (count($sliderWhere)) {
955 $query->where[] = "(". implode(' AND ', $sliderWhere).")";
956 }
957 } else {
958 $sliderWhere = array();
959 if (isset($value['min'])) {
960 $sliderWhere[] = "(CONVERT(Value, SIGNED) >= ".((int)$value['min']) . ")";
961 }
962 if (isset($value['max'])) {
963 $sliderWhere[] = "(CONVERT(Value, SIGNED) <= ".((int)$value['max']) . ")";
964 }
965 if (count($sliderWhere)) {
966 $paramsWhere[] = "SELECT DISTINCT ProductID FROM ProductParamValue WHERE TechTitle = '{$filter->FilterField}' AND (". implode(' AND ', $sliderWhere).")";
967 }
968 }
969 break;
970 case 'multiselect':
971 if (is_array($value) && count($value)) {
972 foreach($value as $key=>$val) {
973 $value[$key] = Convert::raw2sql($val);
974 }
975 if (self::productFieldTable($filter->FilterField)) {
976 $query->where[] = "{$filter->FilterField} in('" . implode("','", $value)."')";
977 } else {
978
979 $paramsWhere[] = "SELECT DISTINCT ProductID FROM ProductParamValue WHERE TechTitle = '{$filter->FilterField}' AND Value in ('" . implode("','", $value) . "')";
980 }
981 break;
982 }
983 case 'text':
984 $value = Convert::raw2sql($value);
985 $condition = "LIKE '%{$value}%'";
986
987 if (self::productFieldTable($filter->FilterField)) {
988 if (self::productFieldTable($filter->FilterField) == 'Int') {
989 $condition = " = '$value'";
990 }
991 $query->where[] = "{$filter->FilterField} $condition";
992 } else {
993 $param = DataObject::get_one('ProductParam', "TechTitle = '{$filter->FilterField}'");
994 if ($param && $param->Type == 'number') {
995 $condition = " = '$value'";
996 }
997
998 $paramsWhere[] = "SELECT DISTINCT ProductID FROM ProductParamValue WHERE TechTitle = '{$filter->FilterField}' AND Value $condition";
999 }
1000 break;
1001 }
1002 }
1003 }
1004
1005
1006 if (count($paramsWhere)) {
1007 $fullWhere = false;
1008 foreach($paramsWhere as $where) {
1009 if (!$fullWhere) {
1010 $fullWhere = $where;
1011 } else {
1012 $fullWhere .= " AND ProductID IN ({$where}";
1013 }
1014 }
1015 $fullWhere .= str_repeat(")", count($paramsWhere)-1);
1016 $query->where[] = "SiteTree{$stage}.ID IN ({$fullWhere})";
1017 }
1018
1019 return $query;
1020 }
1021
1022 1023 1024 1025 1026
1027 function () {
1028 $where = $this->getProductsListWhere();
1029 $stage = (Versioned::current_stage() == 'Live' ? '_Live' : '');
1030 return "SELECT \"SiteTree{$stage}\".ID FROM \"SiteTree{$stage}\" JOIN \"Product{$stage}\" ON \"SiteTree{$stage}\".\"ID\" = \"Product{$stage}\".\"ID\" WHERE " . implode(' AND ', $where);
1031 }
1032
1033
1034 }
1035
1036 class Catalog_Controller extends Page_Controller {
1037
1038
1039 public $CurrentSort;
1040 public $CurrentView;
1041 public $CurrentPageSize;
1042
1043 public $FilterActive = null;
1044
1045 public $UseShowMore = false;
1046 public $UseChangeView = false;
1047
1048 1049 1050 1051 1052 1053 1054 1055
1056 function setupCatalogtVar($name, $newVal = null) {
1057 $currName = 'Current' . $name;
1058 $cookieName = 'Catalog' . $name;
1059 $checkName = 'AllowChange' . $name;
1060 $defName = 'default' . $name;
1061 $valuesName = 'get_' . strtolower($name) . '_options';
1062
1063 $changed = false;
1064 $default = $this->$defName();
1065 $possibleValues = Catalog::$valuesName();
1066
1067
1068 $this->$currName = $default;
1069
1070
1071 if ($this->hasMethod($checkName) && !$this->$checkName()) {
1072 return false;
1073 }
1074
1075
1076 $cookieVal = Cookie::get($cookieName);
1077 if (isset($cookieVal) && in_array($cookieVal, $possibleValues)) {
1078 $this->$currName = $cookieVal;
1079 }
1080
1081
1082 if (!$cookieVal && $member = Member::currentUser()) {
1083 if ($member->hasMethod('getCatalogOption')) {
1084 $cookieVal = $member->getCatalogOption($cookieName);
1085 if ($cookieVal && in_array($cookieVal, $possibleValues)) {
1086 $this->$currName = $cookieVal;
1087 Cookie::set($cookieName, $cookieVal);
1088 }
1089 }
1090 }
1091
1092
1093 if (isset($newVal)) {
1094 $member = Member::currentUser();
1095 if ($newVal === '' || $newVal == 'default') {
1096 $changed = ($default != $this->$currName);
1097 $this->$currName = $default;
1098
1099 Cookie::set($cookieName, '');
1100 if ($member && $member->hasMethod('setCatalogOption')) {
1101 $member->setCatalogOption($cookieName, '');
1102 }
1103 return $changed;
1104 }
1105 if (in_array($newVal, $possibleValues)) {
1106 $changed = ($newVal != $this->$currName);
1107 $this->$currName = $newVal;
1108
1109 Cookie::set($cookieName, $newVal);
1110 if ($member && $member->hasMethod('setCatalogOption')) {
1111 $member->setCatalogOption($cookieName, $newVal);
1112 }
1113
1114 $this->data()->SeoIsAlternative = true;
1115 }
1116 }
1117
1118
1119 1120 1121 1122 1123
1124 return $changed;
1125 }
1126
1127 function isEmptyContent() {
1128 return parent::isEmptyContent() && $this->CountItems() == 0;
1129 }
1130
1131 1132 1133 1134 1135 1136 1137 1138
1139 function setupFilterClasses($field, $filter) {
1140 if ($filter->Important) {
1141 $field->addExtraClass('form_fieldContent__important important');
1142 $field->addExtraClass('form_fieldContent__active active');
1143 }
1144 else {
1145 $field->addExtraClass('not_important');
1146 $filterData = $this->cleanParams();
1147 if (isset($filterData[$filter->FilterField]) && ($filterData[$filter->FilterField] !== '')) {
1148 $field->addExtraClass('form_fieldContent__active active');
1149 }
1150 }
1151 return $field;
1152 }
1153
1154 1155 1156 1157 1158 1159 1160
1161 function getTextFilter($filter) {
1162 return $this->setupFilterClasses(new TextField($filter->FilterField, $filter->Title), $filter);
1163 }
1164
1165 1166 1167 1168 1169 1170 1171
1172 function getBoolFilter($filter) {
1173 return $this->setupFilterClasses(new CheckboxField($filter->FilterField, $filter->Title), $filter);
1174 }
1175
1176 1177 1178 1179 1180 1181 1182
1183 function getMultiSelectFilter($filter, $productsSQL) {
1184 $rs = Catalog::get_unique_values($filter, $productsSQL);
1185 if (count($rs) > 0) {
1186 $f = new CheckboxSetField($filter->FilterField, $filter->Title, $rs);
1187 if (trim($filter->DefaultValue)) {
1188 $f->setValue($filter->DefaultValue);
1189 }
1190 return $this->setupFilterClasses($f, $filter);
1191 }
1192 return false;
1193 }
1194
1195 1196 1197 1198 1199 1200 1201
1202 function getListFilter($filter, $productsSQL) {
1203 $rs = Catalog::get_unique_values($filter, $productsSQL);
1204 if (count($rs) > 0) {
1205 $f = (trim($filter->DefaultValue)) ? new DropdownField($filter->FilterField, $filter->Title, $rs, $filter->DefaultValue) : new DropdownField($filter->FilterField, $filter->Title, $rs, '', null, 'Не важно');
1206 return $this->setupFilterClasses($f, $filter);
1207 }
1208 return false;
1209 }
1210
1211 1212 1213 1214 1215 1216 1217
1218 function getSliderFilter($filter, $productsSQL) {
1219 $data = Catalog::get_min_max_values($filter, $productsSQL);
1220 $data = $data->First();
1221 if (isset($data['MinVal']) && isset($data['MaxVal']) && ($data['MinVal'] < $data['MaxVal'])) {
1222 $min_max_data = array('min' => floor($data['MinVal']), 'max' => ceil($data['MaxVal']));
1223 $f = new RangeField($filter->FilterField, $filter->Title);
1224 $f->setValue($min_max_data);
1225 $f->setMinMaxValue($min_max_data);
1226 if (trim($filter->Unit)) {
1227 $f->addExtraAttribute('Unit', trim($filter->Unit));
1228 $f->setUnit(trim($filter->Unit));
1229 }
1230 return $this->setupFilterClasses($f, $filter);
1231 }
1232 return false;
1233 }
1234
1235 1236 1237 1238 1239 1240 1241
1242 function getGroupFilter($key, $filters, &$paramFields) {
1243 if (!$filters->Count()) {
1244 return false;
1245 }
1246 $groupFields = new FieldSet();
1247 $t = Convert::rus2lat($key);
1248
1249 $label = new LabelField($t . '_label', $key);
1250 $label->addExtraClass('elem_label');
1251 $groupFields->push($label);
1252
1253 $filterData = $this->cleanParams();
1254
1255 $minSort = false;
1256 $important = 0;
1257 $active = '';
1258 $groupFields->push(new LiteralField('group_wrapper', '<div class="group_wrapper">'));
1259
1260 foreach($filters as $filter) {
1261 if ($minSort === false) {
1262 $minSort = $filter->Sort;
1263 } else {
1264 if ($filter->Sort && (($filter->Sort < $minSort) || (!$minSort))) {
1265 $minSort = $filter->Sort;
1266 }
1267 }
1268 if ($filter->Important) {
1269 $important = 1;
1270 }
1271 $paramTitle = $filter->Title;
1272
1273 if (isset($filterData[$filter->FilterField])) {
1274 $active = 'active';
1275 }
1276 $groupFields->push(new CheckboxField($filter->FilterField, $paramTitle));
1277 }
1278 $groupFields->push(new LiteralField('end_group_wrapper', '</div>'));
1279
1280 $groupFields->push(new LiteralField('end_wrapper', '</div>'));
1281
1282 $extraClass = 'not_important';
1283 if ($important) {
1284 $active = 'active';
1285 $extraClass = 'important';
1286 }
1287 $extraClass = "{$extraClass} {$active}";
1288 $groupFields->insertFirst(new LiteralField('wrapper', '<div id="'.$t.'" class="field '.$extraClass.'">'));
1289
1290 foreach($groupFields as $groupField) {
1291 $paramFields[$important][$minSort][] = $groupField;
1292 }
1293 }
1294
1295 1296 1297 1298 1299 1300 1301
1302 function cleanParams($values = false, $keepPage=false) {
1303 if (!$values)
1304 $values = $this->getRequest()->requestVars();
1305
1306 unset($values['url']);
1307 if (!$keepPage)
1308 unset($values['start']);
1309
1310 unset($values['sort']);
1311 unset($values['view']);
1312 unset($values['pagesize']);
1313 unset($values['action_filter']);
1314 unset($values['action_filterclear']);
1315 unset($values['show_more']);
1316 return $values;
1317 }
1318
1319 1320 1321 1322 1323 1324 1325
1326 function linkWithParams($params = array()) {
1327 if (!$params)
1328 $params = $this->cleanParams(false, true);
1329 if (!$params)
1330 return $this->Link();
1331
1332 $action = ($this->IsFilterActive()) ? 'filter' : '';
1333 return $this->Link($action) . '?' . http_build_query($params);
1334 }
1335
1336 1337 1338
1339 function Sorts($default = false) {
1340 $values = $this->cleanParams();
1341 $items = new DataObjectSet();
1342 foreach (Product::sort_options_dropdown_map($default) as $id => $title) {
1343 $htmlID = ($id) ? $id : 'default';
1344 $values['sort'] = $htmlID;
1345 $items->push(new ArrayData(array(
1346 'ID' => $htmlID,
1347 'Title' => $title,
1348 'Link' => $this->linkWithParams($values),
1349 'isCurrent' => ($id == $this->CurrentSort),
1350 'LinkOrCurrent' => ($id == $this->CurrentSort) ? 'current' : 'link',
1351 )));
1352
1353 }
1354 return $items;
1355 }
1356
1357 1358 1359
1360 function Views($default = false) {
1361 if (!$this->AllowChangeView()) return false;
1362
1363 $values = $this->cleanParams(false, true);
1364 $items = new DataObjectSet();
1365 foreach (Catalog::view_options_dropdown_map($default) as $id => $title) {
1366 $htmlID = ($id) ? $id : 'default';
1367 $values['view'] = $htmlID;
1368 $items->push(new ArrayData(array(
1369 'ID' => $htmlID,
1370 'Title' => $title,
1371 'Link' => $this->linkWithParams($values),
1372 'isCurrent' => ($id == $this->CurrentView),
1373 'LinkOrCurrent' => ($id == $this->CurrentView) ? 'current' : 'link',
1374 )));
1375 }
1376 return $items;
1377 }
1378
1379 1380 1381
1382 function PageSizes($default = false) {
1383 if (!$this->AllowChangePageSize()) return false;
1384
1385 $values = $this->cleanParams();
1386 $items = new DataObjectSet();
1387 foreach (Catalog::pagesize_dropdown_map($default) as $id => $title) {
1388 $htmlID = ($id) ? $id : 'default';
1389 $values['pagesize'] = $htmlID;
1390 $items->push(new ArrayData(array(
1391 'ID' => $htmlID,
1392 'Title' => $title,
1393 'Link' => $this->linkWithParams($values),
1394 'isCurrent' => ($id == $this->CurrentPageSize),
1395 'LinkOrCurrent' => ($id == $this->CurrentPageSize) ? 'current' : 'link',
1396 )));
1397 }
1398 return $items;
1399 }
1400
1401 1402 1403 1404 1405
1406 function FilteredProductsCountLink() {
1407 return $this->Link('filtered_products_count');
1408 }
1409
1410 1411 1412 1413 1414
1415 function Filters() {
1416 if ($this->TotalProductsCount(false) == 0) {
1417 return false;
1418 }
1419
1420 $fields = new FieldSet();
1421 $paramFields = array();
1422 $paramFields[0] = array();
1423 $paramFields[1] = array();
1424
1425 $productsSQL = $this->getProductsListWhere();
1426 $sliderProductsSQL = implode(' AND ', $productsSQL);
1427
1428 $query = new SQLQuery();
1429 $query->where = $productsSQL;
1430
1431 $filters = $this->catalogFilterFields();
1432 if ($filters && $filters->Count()) {
1433 $groupFilters = new DataObjectSet();
1434
1435
1436
1437 foreach($filters as $filter) {
1438
1439
1440
1441 if (Catalog::$reduce_filters && ($filterData = $this->setFiltersDefaultValue($this->cleanParams()))) {
1442 $query->where = $productsSQL;
1443 unset($filterData[$filter->TechTitle]);
1444 $this->updateQueryByProductParamFilters($filterData, $query);
1445 }
1446 $filteredProductSQL = implode(' AND ', $query->where);
1447
1448 if ($filter->Type == 'text') {
1449 $filterField = $this->getTextFilter($filter);
1450 }
1451 elseif ($filter->Type == 'bool') {
1452 $filterField = $this->getBoolFilter($filter);
1453 }
1454 elseif ($filter->Type == 'slider') {
1455 $filterField = $this->getSliderFilter($filter, $sliderProductsSQL);
1456 }
1457 elseif ($filter->Type == 'list') {
1458 $filterField = $this->getListFilter($filter, $filteredProductSQL);
1459 }
1460 elseif ($filter->Type == 'multiselect') {
1461 $filterField = $this->getMultiSelectFilter($filter, $filteredProductSQL);
1462 }
1463 elseif ($filter->Type == 'boolgroup') {
1464 $filterField = false;
1465 $groupFilters->push($filter);
1466 }
1467
1468 if ($filterField) {
1469 if (!isset($paramFields[$filter->Important][$filter->Sort])) {
1470 $paramFields[$filter->Important][$filter->Sort] = array();
1471 }
1472 $paramFields[$filter->Important][$filter->Sort][] = $filterField;
1473 }
1474 }
1475
1476
1477 if ($groupFilters) {
1478
1479 $allGroupFilters = $groupFilters->groupBy('GroupTitle');
1480 foreach($allGroupFilters as $key=>$groupFilters) {
1481 $this->getGroupFilter($key, $groupFilters, $paramFields);
1482 }
1483 }
1484
1485
1486 foreach($paramFields[1] as $sort=>$importantParamFields) {
1487 if ($sort > 0) {
1488 foreach($importantParamFields as $paramField) {
1489 $fields->push($paramField);
1490 }
1491 }
1492 }
1493
1494 if (isset($paramFields[1][0])) {
1495 foreach($paramFields[1][0] as $paramField) {
1496 $fields->push($paramField);
1497 }
1498 }
1499
1500
1501 foreach($paramFields[0] as $sort=>$notImportantparamFields) {
1502 if ($sort > 0) {
1503 foreach($notImportantparamFields as $paramField) {
1504 $fields->push($paramField);
1505 }
1506 }
1507 }
1508
1509 if (isset($paramFields[0][0])) {
1510 foreach($paramFields[0][0] as $paramField) {
1511 $fields->push($paramField);
1512 }
1513 }
1514 }
1515
1516 if (Catalog::$filter_calc_suitable_products_mode) {
1517 $this->calculateSuitableProducts($fields, $filters);
1518 }
1519
1520 $this->extend("updateFilterFields", $fields);
1521 if ($fields->Count() == 0) {
1522 return false;
1523 }
1524
1525 $fields->First()->addExtraClass('first');
1526 $actions = new FieldSet(
1527 $fa1 = new FormAction('filter', _t('Catalog.FILTER_SELECT','Выбрать')),
1528 $fa2 = new FormAction('filterclear', _t('Catalog.FILTER_CLEAR','Очистить'))
1529 );
1530 $fa1->addExtraClass('button__filters');
1531 $fa2->addExtraClass('button__filters button__second');
1532
1533 $form = new Form($this, 'Filters', $fields, $actions);
1534 $form->disableSecurityToken();
1535 $form->setFormMethod('GET');
1536 $form->getValidator()->setJavascriptValidationHandler('none');
1537 $form->addExtraClass('filters');
1538 $form->setTemplate('CatalogFilterForm');
1539
1540 $this->extend('updateFilterForm', $form);
1541
1542 if ($form->Fields()->Count() == 0)
1543 return false;
1544
1545 if ($this->getRequest()) {
1546 $form->loadDataFrom($this->getRequest()->requestVars());
1547 }
1548 return $form;
1549 }
1550
1551 function calculateSuitableProducts($fields, $filters) {
1552 foreach($fields as $field) {
1553 if ($field->is_a('DropdownField') || $field->is_a('CheckboxField')) {
1554 $name = $field->Name();
1555
1556 $map = array();
1557 $useAllFilters = true;
1558 if (Catalog::$filter_calc_suitable_products_mode == 'one_filter') {
1559 $key = "FilterData_{$this->ID}_{$name}";
1560 $map = Catalog::get_cached_data($key);
1561 $useAllFilters = false;
1562 }
1563
1564 $productsSQL = $this->getProductsListWhere();
1565 $productsSQL = implode(' AND ', $productsSQL);
1566 if (!is_array($map) || !count($map)) {
1567 $filter = $filters->find('FilterField', $name);
1568 $values = Catalog::get_unique_values($filter, $productsSQL);
1569 $map = array();
1570 foreach($values as $value) {
1571 $filterData = array();
1572 $where = array();
1573 if ($value) {
1574 $where[] = "{$name} = '{$value}'";
1575 $count = $this->TotalProductsCount($useAllFilters, $where);
1576 $map[$value] = $count;
1577 }
1578 }
1579 Catalog::set_cached_data($key, $map);
1580 }
1581
1582 if ($field->is_a('DropdownField')) {
1583 foreach ($map as $v => $c) {
1584 $map[$v] = "$v ($c)";
1585 }
1586 $field->setSource($map);
1587 } else if ($field->is_a('CheckboxField')) {
1588 $field->setTitle($field->Title(). " ({$map[1]})");
1589 }
1590 }
1591 }
1592 }
1593
1594 1595 1596 1597 1598 1599 1600
1601 function setFiltersDefaultValue($filterData) {
1602 if ($this->catalogFilterFields() && $this->catalogFilterFields()->Count()) {
1603 foreach($this->catalogFilterFields() as $filter) {
1604 if ($filter->Type == 'list' && trim($filter->DefaultValue)) {
1605 if (!isset($filterData[$filter->FilterField]) && $filter->DefaultValue) {
1606 $filterData[$filter->FilterField] = $filter->DefaultValue;
1607 }
1608 }
1609 }
1610 }
1611 return $filterData;
1612 }
1613
1614 1615 1616 1617 1618
1619 function IsFilterActive() {
1620 if ($this->FilterActive) {
1621 return true;
1622 }
1623 $data = $this->cleanParams();
1624 if (!count($data)) return false;
1625
1626 $filters = $this->Filters();
1627 if (!$filters) {
1628 return false;
1629 }
1630 $filterFields = $filters->Fields();
1631 foreach ($data as $k => $v) {
1632 if ($filterFields->fieldByName($k)) {
1633 if ($v !== '') return true;
1634 }
1635 }
1636 return false;
1637 }
1638
1639 1640 1641 1642 1643 1644 1645
1646 function TotalProductsCount($withFilters=true, $additionalFilters=false) {
1647 $query = new SQLQuery();
1648 $query->where = $this->getProductsListWhere();
1649 if ($withFilters) {
1650 $filterData = $this->setFiltersDefaultValue($this->cleanParams());
1651 $this->updateQueryByProductParamFilters($filterData, $query);
1652 }
1653 if ($additionalFilters && is_array($additionalFilters) && count($additionalFilters)) {
1654 foreach($additionalFilters as $withFilter) {
1655 $query->where[] = $withFilter;
1656 }
1657 }
1658
1659 $stage = (Versioned::current_stage() == 'Live' ? '_Live' : '');
1660 $filteredProductSQL = implode(' AND ', $query->where);
1661
1662
1663
1664
1665
1666
1667 if(in_array("ShopsAdmin", get_declared_classes())){
1668 $shopID = $this->cleanParams()['shopaddress'];
1669 $sql = "SELECT count(*) FROM \"SiteTree{$stage}\" JOIN \"Product{$stage}\" ON \"SiteTree{$stage}\".\"ID\" = \"Product{$stage}\".\"ID\" LEFT JOIN \"Product_Shops\" ON \"Product_Shops\".\"ProductID\" = \"SiteTree{$stage}\".\"ID\" WHERE {$filteredProductSQL}";
1670 if($shopID){
1671 $sql .= " AND ShopsItemID = {$shopID}";
1672 }
1673 }else{
1674 $sql = "SELECT count(*) FROM \"SiteTree{$stage}\" JOIN \"Product{$stage}\" ON \"SiteTree{$stage}\".\"ID\" = \"Product{$stage}\".\"ID\" WHERE {$filteredProductSQL}";
1675 }
1676
1677
1678
1679 return DB::Query($sql)->value();
1680 }
1681
1682 1683 1684 1685 1686
1687 function TotalProductsCountTitle() {
1688 return Convert::number2name($this->TotalProductsCount(), _t('Product.Title_1'), _t('Product.Title_2_4'), _t('Product.Title_5_9'));
1689 }
1690
1691 function init() {
1692 parent::init();
1693
1694 $this->setupCatalogtVar('Sort');
1695 $this->setupCatalogtVar('View');
1696 $this->setupCatalogtVar('PageSize');
1697 $this->data()->SeoCanonicalLink = $this->Link();
1698 }
1699
1700
1701
1702 function index() {
1703 $request = $this->getRequest();
1704 $start = intval($request->getVar('start'));
1705
1706
1707 if ($this->setupCatalogtVar('View', $request->requestVar('view'))) {
1708 if (Director::is_ajax()) $this->UseChangeView = true;
1709 }
1710
1711
1712 if ($this->setupCatalogtVar('Sort', $request->requestVar('sort'))) {
1713 if (Director::is_ajax()) $this->UseChangeView = true;
1714 $start = 0;
1715 }
1716
1717
1718 if ($this->setupCatalogtVar('PageSize', $request->requestVar('pagesize'))) {
1719 if (Director::is_ajax()) $this->UseChangeView = true;
1720 $start = 0;
1721 }
1722
1723
1724 if ($request->requestVar('show_more')) {
1725 if (Director::is_ajax()) $this->UseShowMore = true;
1726 $_SERVER['REQUEST_URI'] = str_replace('&show_more=1', '', $_SERVER['REQUEST_URI']);
1727 }
1728
1729
1730 $limit = '';
1731 if ($this->CurrentPageSize == 'all') {
1732 $this->data()->SeoIsAlternative = true;
1733 } else {
1734 $limit = "$start,{$this->CurrentPageSize}";
1735 }
1736
1737
1738 if ($this->IsFilterActive()) {
1739 $this->data()->SeoIsAlternative = true;
1740 }
1741
1742 $filterData = $this->setFiltersDefaultValue($this->cleanParams());
1743
1744 $this->Products = $this->filteredProducts($this->CurrentSort, $filterData, $limit);
1745 if ($this->hasMethod('setSEOVars')) {
1746 $this->setSEOVars($this->Products);
1747 }
1748
1749
1750 if (Director::is_ajax()) {
1751 $this->getResponse()->addHeader('X-Set-Url', $this->linkWithParams());
1752 }
1753
1754 $action = (Director::is_ajax()) ? 'ajax' : 'index';
1755 return parent::defaultAction($action);
1756 }
1757
1758 1759 1760 1761 1762
1763 function filtered_products_count() {
1764 $totalProductsCount = $this->TotalProductsCount();
1765 $rs = array(
1766 'ProductCount' => $totalProductsCount,
1767 'ProductCountTitle' => Convert::number2name($totalProductsCount, _t('Product.Title_1'), _t('Product.Title_2_4'), _t('Product.Title_5_9')),
1768 );
1769 return json_encode($rs);
1770 }
1771
1772 1773 1774 1775 1776 1777 1778 1779
1780 function filterclear($data, $form) {
1781
1782 if (!Director::is_ajax())
1783 return $this->redirect($this->Link());
1784
1785 if ($form) {
1786 $this->FilterActive = true;
1787 }
1788 return $this->index();
1789 }
1790
1791 1792 1793
1794 function filter($data, $form=null) {
1795 if ($form) {
1796 if (!Director::is_ajax()) {
1797 return $this->redirect($this->linkWithParams());
1798 }
1799 $this->FilterActive = true;
1800 }
1801 return $this->index();
1802 }
1803 }
1804
[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.
-