Catalin_Seo - Version 1.0.0

Version Notes

ajax, seo urls, price slider, multiple selection for the same attribute.

Download this release

Release Info

Developer Catalin
Extension Catalin_Seo
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

Files changed (29) hide show
  1. app/code/community/Catalin/SEO/Block/Catalog/Layer/Filter/Attribute.php +37 -0
  2. app/code/community/Catalin/SEO/Block/Catalog/Layer/Filter/Price.php +60 -0
  3. app/code/community/Catalin/SEO/Block/Catalog/Layer/State.php +46 -0
  4. app/code/community/Catalin/SEO/Block/Catalog/Product/List/Pager.php +40 -0
  5. app/code/community/Catalin/SEO/Block/Catalog/Product/List/Toolbar.php +40 -0
  6. app/code/community/Catalin/SEO/Block/CatalogSearch/Layer/Filter/Attribute.php +30 -0
  7. app/code/community/Catalin/SEO/Controller/Router.php +135 -0
  8. app/code/community/Catalin/SEO/Helper/Data.php +201 -0
  9. app/code/community/Catalin/SEO/Model/Catalog/Layer/Filter/Attribute.php +120 -0
  10. app/code/community/Catalin/SEO/Model/Catalog/Layer/Filter/Category.php +97 -0
  11. app/code/community/Catalin/SEO/Model/Catalog/Layer/Filter/Item.php +116 -0
  12. app/code/community/Catalin/SEO/Model/Catalog/Resource/Layer/Filter/Attribute.php +122 -0
  13. app/code/community/Catalin/SEO/Model/CatalogSearch/Layer/Filter/Attribute.php +30 -0
  14. app/code/community/Catalin/SEO/Model/System/Config/Backend/Seo/Catalog.php +35 -0
  15. app/code/community/Catalin/SEO/controllers/CategoryController.php +94 -0
  16. app/code/community/Catalin/SEO/controllers/ResultController.php +88 -0
  17. app/code/community/Catalin/SEO/etc/adminhtml.xml +22 -0
  18. app/code/community/Catalin/SEO/etc/config.xml +100 -0
  19. app/code/community/Catalin/SEO/etc/system.xml +75 -0
  20. app/design/frontend/default/default/layout/catalin_seo.xml +53 -0
  21. app/design/frontend/default/default/template/catalin_seo/catalog/layer/filter.phtml +26 -0
  22. app/design/frontend/default/default/template/catalin_seo/catalog/layer/price.phtml +48 -0
  23. app/design/frontend/default/default/template/catalin_seo/catalog/layer/view.phtml +35 -0
  24. app/design/frontend/default/default/template/catalin_seo/catalog/product/list.phtml +181 -0
  25. app/etc/modules/Catalin_SEO.xml +12 -0
  26. package.xml +31 -0
  27. skin/frontend/default/default/css/price_slider/style.css +18 -0
  28. skin/frontend/default/default/images/price_slider/bkg_slider.png +0 -0
  29. skin/frontend/default/default/images/price_slider/slider.png +0 -0
app/code/community/Catalin/SEO/Block/Catalog/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Block_Catalog_Layer_Filter_Attribute extends Mage_Catalog_Block_Layer_Filter_Attribute
18
+ {
19
+
20
+ /**
21
+ * Class constructor
22
+ */
23
+ public function __construct()
24
+ {
25
+ parent::__construct();
26
+
27
+ if ($this->helper('catalin_seo')->isEnabled()
28
+ && $this->helper('catalin_seo')->isMultipleChoiceFiltersEnabled()) {
29
+ /**
30
+ * Modify template for multiple filters rendering
31
+ * It has checkboxes instead of classic links
32
+ */
33
+ $this->setTemplate('catalin_seo/catalog/layer/filter.phtml');
34
+ }
35
+ }
36
+
37
+ }
app/code/community/Catalin/SEO/Block/Catalog/Layer/Filter/Price.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Block_Catalog_Layer_Filter_Price extends Mage_Catalog_Block_Layer_Filter_Price
18
+ {
19
+
20
+ /**
21
+ * Class constructor
22
+ *
23
+ * Set correct template depending on module state
24
+ */
25
+ public function __construct()
26
+ {
27
+ parent::__construct();
28
+ if ($this->helper('catalin_seo')->isEnabled()
29
+ && $this->helper('catalin_seo')->isPriceSliderEnabled()) {
30
+ // Modify template to render price filter as slider
31
+ $this->setTemplate('catalin_seo/catalog/layer/price.phtml');
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Get max price for the collection
37
+ *
38
+ * @return int
39
+ */
40
+ public function getMaxPriceInt()
41
+ {
42
+ return $this->_filter->getMaxPriceInt() + 1;
43
+ }
44
+
45
+ /**
46
+ * URL Pattern used in javascript for price filtering
47
+ *
48
+ * @return string
49
+ */
50
+ public function getUrlPattern()
51
+ {
52
+ $item = Mage::getModel('catalog/layer_filter_item')
53
+ ->setFilter($this->_filter)
54
+ ->setValue('__PRICE_VALUE__')
55
+ ->setCount(0);
56
+
57
+ return $item->getUrl();
58
+ }
59
+
60
+ }
app/code/community/Catalin/SEO/Block/Catalog/Layer/State.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Block_Catalog_Layer_State extends Mage_Catalog_Block_Layer_State
18
+ {
19
+
20
+ /**
21
+ * Retrieve Clear Filters URL
22
+ *
23
+ * @return string
24
+ */
25
+ public function getClearUrl()
26
+ {
27
+ if (!$this->helper('catalin_seo')->isEnabled()) {
28
+ return parent::getClearUrl();
29
+ }
30
+
31
+ if ($this->helper('catalin_seo')->isCatalogSearch()) {
32
+ $filterState = array('isLayerAjax' => null);
33
+ foreach ($this->getActiveFilters() as $item) {
34
+ $filterState[$item->getFilter()->getRequestVar()] = $item->getFilter()->getCleanValue();
35
+ }
36
+ $params['_current'] = true;
37
+ $params['_use_rewrite'] = true;
38
+ $params['_query'] = $filterState;
39
+ $params['_escape'] = true;
40
+ return Mage::getUrl('*/*/*', $params);
41
+ }
42
+
43
+ return $this->helper('catalin_seo')->getClearFiltersUrl();
44
+ }
45
+
46
+ }
app/code/community/Catalin/SEO/Block/Catalog/Product/List/Pager.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Block_Catalog_Product_List_Pager extends Mage_Page_Block_Html_Pager
18
+ {
19
+
20
+ /**
21
+ * Return current URL with rewrites and additional parameters
22
+ *
23
+ * @param array $params Query parameters
24
+ * @return string
25
+ */
26
+ public function getPagerUrl($params = array())
27
+ {
28
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
29
+ return parent::getPagerUrl($params);
30
+ }
31
+
32
+ if ($this->helper('catalin_seo')->isCatalogSearch()) {
33
+ $params['isLayerAjax'] = null;
34
+ return parent::getPagerUrl($params);
35
+ }
36
+
37
+ return $this->helper('catalin_seo')->getPagerUrl($params);
38
+ }
39
+
40
+ }
app/code/community/Catalin/SEO/Block/Catalog/Product/List/Toolbar.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Block_Catalog_Product_List_Toolbar extends Mage_Catalog_Block_Product_List_Toolbar
18
+ {
19
+
20
+ /**
21
+ * Return current URL with rewrites and additional parameters
22
+ *
23
+ * @param array $params Query parameters
24
+ * @return string
25
+ */
26
+ public function getPagerUrl($params = array())
27
+ {
28
+ if (!$this->helper('catalin_seo')->isEnabled()) {
29
+ return parent::getPagerUrl($params);
30
+ }
31
+
32
+ if ($this->helper('catalin_seo')->isCatalogSearch()) {
33
+ $params['isLayerAjax'] = null;
34
+ return parent::getPagerUrl($params);
35
+ }
36
+
37
+ return $this->helper('catalin_seo')->getPagerUrl($params);
38
+ }
39
+
40
+ }
app/code/community/Catalin/SEO/Block/CatalogSearch/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Block_CatalogSearch_Layer_Filter_Attribute extends Catalin_SEO_Block_Catalog_Layer_Filter_Attribute
18
+ {
19
+
20
+ /**
21
+ * Set filter model name
22
+ *
23
+ */
24
+ public function __construct()
25
+ {
26
+ parent::__construct();
27
+ $this->_filterModelName = 'catalogsearch/layer_filter_attribute';
28
+ }
29
+
30
+ }
app/code/community/Catalin/SEO/Controller/Router.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Controller_Router extends Mage_Core_Controller_Varien_Router_Standard
18
+ {
19
+
20
+ /**
21
+ * Add catalog router to front controller
22
+ *
23
+ * @param Varien_Event_Observer $observer
24
+ */
25
+ public function initControllerRouters(Varien_Event_Observer $observer)
26
+ {
27
+ $front = $observer->getEvent()->getFront();
28
+ // Collect routes - needed for match()
29
+ $this->collectRoutes('frontend', 'standard');
30
+ $front->addRouter('catalin_catalog', $this);
31
+ }
32
+
33
+ /**
34
+ * Match the request
35
+ *
36
+ * @param Zend_Controller_Request_Http $request
37
+ * @return boolean
38
+ */
39
+ public function match(Zend_Controller_Request_Http $request)
40
+ {
41
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
42
+ return false;
43
+ }
44
+
45
+ $suffix = Mage::getStoreConfig('catalog/seo/category_url_suffix');
46
+ $identifier = trim(str_replace($suffix, '', $request->getPathInfo()), '/');
47
+ $urlSplit = explode(Catalin_SEO_Helper_Data::ROUTING_CATEGORY_SUFFIX, $identifier, 2);
48
+
49
+ //Check if it is a link generated by the SEO module
50
+ if (!isset($urlSplit[1])) {
51
+ return false;
52
+ }
53
+
54
+ $urlRewrite = Mage::getModel('core/url_rewrite');
55
+ $urlRewrite->setStoreId(Mage::app()->getStore()->getId());
56
+ $cat = $urlSplit[0];
57
+
58
+ $catPath = $cat . $suffix;
59
+ $urlRewrite->loadByRequestPath($catPath);
60
+
61
+ // Check if a valid category is found
62
+ if ($urlRewrite->getId()) {
63
+ $modules = $this->getModuleByFrontName('catalog');
64
+
65
+ $found = false;
66
+
67
+ // Find the controller to be executed
68
+ // It takes in account rewrites
69
+ foreach ($modules as $realModule) {
70
+ $request->setRouteName($this->getRouteByFrontName('catalog'));
71
+
72
+ // Check if this place should be secure
73
+ $this->_checkShouldBeSecure($request, '/catalog/category/view');
74
+
75
+ // Find controller class name
76
+ $controllerClassName = $this->_validateControllerClassName($realModule, 'category');
77
+ if (!$controllerClassName) {
78
+ continue;
79
+ }
80
+
81
+ // Instantiate controller class
82
+ $controllerInstance = Mage::getControllerInstance($controllerClassName, $request, $this->getFront()->getResponse());
83
+
84
+ // Check if controller has viewAction() method
85
+ if (!$controllerInstance->hasAction('view')) {
86
+ continue;
87
+ }
88
+ $found = true;
89
+ break;
90
+ }
91
+
92
+ // Check if we found a controller
93
+ if (!$found) {
94
+ return false;
95
+ }
96
+
97
+ // Set the required data on $request object
98
+ $request->setPathInfo($catPath . Catalin_SEO_Helper_Data::ROUTING_CATEGORY_SUFFIX);
99
+ $request->setModuleName('catalog')
100
+ ->setControllerName('category')
101
+ ->setActionName('view')
102
+ ->setParam('id', $urlRewrite->getCategoryId())
103
+ ->setAlias(
104
+ Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, $catPath . Catalin_SEO_Helper_Data::ROUTING_CATEGORY_SUFFIX
105
+ );
106
+
107
+ // Parse url params
108
+ $params = explode('/', trim($urlSplit[1], '/'));
109
+ $layerParams = array();
110
+ $total = count($params);
111
+ for ($i = 0; $i < $total - 1; $i++) {
112
+ if (isset($params[$i + 1])) {
113
+ $layerParams[$params[$i]] = urldecode($params[$i + 1]);
114
+ ++$i;
115
+ }
116
+ }
117
+ // Add post params to parsed ones from url
118
+ // Usefull to easily override params
119
+ $layerParams += $request->getPost();
120
+ // Add params to request
121
+ $request->setParams($layerParams);
122
+
123
+ // Save params in registry - used later to generate links
124
+ Mage::register('layer_params', $layerParams);
125
+
126
+ // dispatch action
127
+ $request->setDispatched(true);
128
+ $controllerInstance->dispatch('view');
129
+
130
+ return true;
131
+ }
132
+ return false;
133
+ }
134
+
135
+ }
app/code/community/Catalin/SEO/Helper/Data.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Helper_Data extends Mage_Core_Helper_Abstract
18
+ {
19
+
20
+ /**
21
+ * Routing suffix
22
+ */
23
+ const ROUTING_CATEGORY_SUFFIX = '/f';
24
+
25
+ /**
26
+ * Delimiter for multiple filters
27
+ */
28
+ const MULTIPLE_FILTERS_DELIMITER = ',';
29
+
30
+ /**
31
+ * Check if module is enabled or not
32
+ *
33
+ * @return boolean
34
+ */
35
+ public function isEnabled()
36
+ {
37
+ return Mage::getStoreConfigFlag('catalin_seo/catalog/enabled');
38
+ }
39
+
40
+ /**
41
+ * Check if ajax is enabled
42
+ *
43
+ * @return boolean
44
+ */
45
+ public function isAjaxEnabled()
46
+ {
47
+ if (!$this->isEnabled()) {
48
+ return false;
49
+ }
50
+ return Mage::getStoreConfigFlag('catalin_seo/catalog/ajax_enabled');
51
+ }
52
+
53
+ /**
54
+ * Check if multipe choice filters is enabled
55
+ *
56
+ * @return boolean
57
+ */
58
+ public function isMultipleChoiceFiltersEnabled()
59
+ {
60
+ if (!$this->isEnabled()) {
61
+ return false;
62
+ }
63
+ return Mage::getStoreConfigFlag('catalin_seo/catalog/multiple_choise_filters');
64
+ }
65
+
66
+ /**
67
+ * Check if price slider is enabled
68
+ *
69
+ * @return boolean
70
+ */
71
+ public function isPriceSliderEnabled()
72
+ {
73
+ if (!$this->isEnabled()) {
74
+ return false;
75
+ }
76
+ return Mage::getStoreConfigFlag('catalin_seo/catalog/price_slider');
77
+ }
78
+
79
+ /**
80
+ * Getter for layered navigation params
81
+ * If $params are provided then it overrides the ones from registry
82
+ *
83
+ * @param array $params
84
+ * @return array|null
85
+ */
86
+ public function getCurrentLayerParams(array $params = null)
87
+ {
88
+ $layerParams = Mage::registry('layer_params');
89
+
90
+ if (!is_array($layerParams)) {
91
+ $layerParams = array();
92
+ }
93
+
94
+ if (!empty($params)) {
95
+ foreach ($params as $key => $value) {
96
+ if ($value === null) {
97
+ unset($layerParams[$key]);
98
+ } else {
99
+ $layerParams[$key] = $value;
100
+ }
101
+ }
102
+ }
103
+
104
+ // Sort by key - small SEO improvement
105
+ ksort($layerParams);
106
+ return $layerParams;
107
+ }
108
+
109
+ /**
110
+ * Method to get url for layered navigation
111
+ *
112
+ * @param array $filters array with new filter values
113
+ * @param integer $escape to autoescape or not
114
+ * @param boolean $noFilters to add filters to the url or not
115
+ * @param array $q array with values to add to query string
116
+ * @return string
117
+ */
118
+ public function getFilterUrl(array $filters, $escape = true, $noFilters = false, array $q = array())
119
+ {
120
+ $query = array(
121
+ 'isLayerAjax' => null, // this needs to be removed because of ajax request
122
+ Mage::getBlockSingleton('page/html_pager')->getPageVarName() => null // exclude current page from urls
123
+ );
124
+ $query = array_merge($query, $q);
125
+
126
+ $suffix = Mage::getStoreConfig('catalog/seo/category_url_suffix');
127
+ $params = array(
128
+ '_current' => true,
129
+ '_use_rewrite' => true,
130
+ '_query' => $query,
131
+ '_nosid' => true,
132
+ );
133
+ // If we should escape or not
134
+ if ($escape) {
135
+ $params['_escape'] = true;
136
+ }
137
+ $url = Mage::getUrl('*/*/*', $params);
138
+ $url = str_replace($suffix, '', $url);
139
+ $urlPath = '';
140
+
141
+ if (!$noFilters) {
142
+ // Add filters
143
+ $layerParams = $this->getCurrentLayerParams($filters);
144
+ foreach ($layerParams as $key => $value) {
145
+ // Encode and replace escaped delimiter with the delimiter itself
146
+ $value = str_replace(urlencode(self::MULTIPLE_FILTERS_DELIMITER), self::MULTIPLE_FILTERS_DELIMITER, urlencode($value));
147
+ $urlPath .= "/{$key}/{$value}";
148
+ }
149
+ }
150
+
151
+ $urlParts = explode('?', $url);
152
+
153
+ // Add the suffix to the url - fixes when comming from non suffixed pages
154
+ if (stripos($urlParts[0], self::ROUTING_CATEGORY_SUFFIX) === false) {
155
+ $urlParts[0] .= self::ROUTING_CATEGORY_SUFFIX;
156
+ }
157
+
158
+ $url = $urlParts[0] . $urlPath . $suffix;
159
+ if (!empty($urlParts[1])) {
160
+ $url .= '?' . $urlParts[1];
161
+ }
162
+
163
+ return $url;
164
+ }
165
+
166
+ /**
167
+ * Get the url to clear all layered navigation filters
168
+ *
169
+ * @return string
170
+ */
171
+ public function getClearFiltersUrl()
172
+ {
173
+ return $this->getFilterUrl(array(), true, true);
174
+ }
175
+
176
+ /**
177
+ * Get url for layered navigation pagination
178
+ *
179
+ * @param array $query
180
+ * @return string
181
+ */
182
+ public function getPagerUrl(array $query)
183
+ {
184
+ return $this->getFilterUrl(array(), true, false, $query);
185
+ }
186
+
187
+ /**
188
+ * Check if we are in the catalog search
189
+ *
190
+ * @return boolean
191
+ */
192
+ public function isCatalogSearch()
193
+ {
194
+ $pathInfo = $this->_getRequest()->getPathInfo();
195
+ if (stripos($pathInfo, '/catalogsearch/result') !== false) {
196
+ return true;
197
+ }
198
+ return false;
199
+ }
200
+
201
+ }
app/code/community/Catalin/SEO/Model/Catalog/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Model_Catalog_Layer_Filter_Attribute extends Mage_Catalog_Model_Layer_Filter_Attribute
18
+ {
19
+
20
+ protected $_values = array();
21
+
22
+ public function getValues()
23
+ {
24
+ return $this->_values;
25
+ }
26
+
27
+ /**
28
+ * Apply attribute filter to layer
29
+ *
30
+ * @param Zend_Controller_Request_Abstract $request
31
+ * @param object $filterBlock
32
+ * @return Enterprise_Search_Model_Catalog_Layer_Filter_Attribute
33
+ */
34
+ public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
35
+ {
36
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
37
+ return parent::apply($request, $filterBlock);
38
+ }
39
+
40
+ $filter = $request->getParam($this->_requestVar);
41
+ if (is_array($filter)) {
42
+ return $this;
43
+ }
44
+
45
+ if (empty($filter)) {
46
+ return $this;
47
+ }
48
+
49
+ $this->_values = explode(Catalin_SEO_Helper_Data::MULTIPLE_FILTERS_DELIMITER, $filter);
50
+
51
+ if (!empty($this->_values)) {
52
+ $this->_getResource()->applyFilterToCollection($this, $this->_values);
53
+ foreach ($this->_values as $filter) {
54
+ $this->getLayer()->getState()->addFilter($this->_createItem($filter, $filter));
55
+ // process all items if multiple choice is enabled
56
+ if (!Mage::helper('catalin_seo')->isMultipleChoiceFiltersEnabled()) {
57
+ $this->_items = array();
58
+ }
59
+ }
60
+ }
61
+
62
+ return $this;
63
+ }
64
+
65
+ /**
66
+ * Get data array for building attribute filter items
67
+ *
68
+ * @return array
69
+ */
70
+ protected function _getItemsData()
71
+ {
72
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
73
+ return parent::_getItemsData();
74
+ }
75
+
76
+ $attribute = $this->getAttributeModel();
77
+ $this->_requestVar = $attribute->getAttributeCode();
78
+
79
+ $key = $this->getLayer()->getStateKey() . '_' . $this->_requestVar;
80
+ $data = $this->getLayer()->getAggregator()->getCacheData($key);
81
+
82
+ if ($data === null) {
83
+ $options = $attribute->getFrontend()->getSelectOptions();
84
+ $optionsCount = $this->_getResource()->getCount($this);
85
+ $data = array();
86
+ foreach ($options as $option) {
87
+ if (is_array($option['value'])) {
88
+ continue;
89
+ }
90
+ if (Mage::helper('core/string')->strlen($option['value'])) {
91
+ // Check filter type
92
+ if ($this->_getIsFilterableAttribute($attribute) == self::OPTIONS_ONLY_WITH_RESULTS) {
93
+ if (!empty($optionsCount[$option['value']])) {
94
+ $data[] = array(
95
+ 'label' => $option['label'],
96
+ 'value' => $option['label'],
97
+ 'count' => $optionsCount[$option['value']],
98
+ );
99
+ }
100
+ } else {
101
+ $data[] = array(
102
+ 'label' => $option['label'],
103
+ 'value' => $option['label'],
104
+ 'count' => isset($optionsCount[$option['value']]) ? $optionsCount[$option['value']] : 0,
105
+ );
106
+ }
107
+ }
108
+ }
109
+
110
+ $tags = array(
111
+ Mage_Eav_Model_Entity_Attribute::CACHE_TAG . ':' . $attribute->getId()
112
+ );
113
+
114
+ $tags = $this->getLayer()->getStateTags($tags);
115
+ $this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
116
+ }
117
+ return $data;
118
+ }
119
+
120
+ }
app/code/community/Catalin/SEO/Model/Catalog/Layer/Filter/Category.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Model_Catalog_Layer_Filter_Category extends Mage_Catalog_Model_Layer_Filter_Category
18
+ {
19
+
20
+ /**
21
+ * Get data array for building category filter items
22
+ *
23
+ * @return array
24
+ */
25
+ protected function _getItemsData()
26
+ {
27
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
28
+ return parent::_getItemsData();
29
+ }
30
+
31
+ $key = $this->getLayer()->getStateKey().'_SUBCATEGORIES';
32
+ $data = $this->getLayer()->getAggregator()->getCacheData($key);
33
+
34
+ if ($data === null) {
35
+ $categoty = $this->getCategory();
36
+ /** @var $categoty Mage_Catalog_Model_Categeory */
37
+ $categories = $categoty->getChildrenCategories();
38
+
39
+ $this->getLayer()->getProductCollection()
40
+ ->addCountToCategories($categories);
41
+
42
+ $data = array();
43
+ foreach ($categories as $category) {
44
+ if ($category->getIsActive() && $category->getProductCount()) {
45
+ $data[] = array(
46
+ 'label' => Mage::helper('core')->htmlEscape($category->getName()),
47
+ 'value' => $category->getUrlKey(),
48
+ 'count' => $category->getProductCount(),
49
+ );
50
+ }
51
+ }
52
+ $tags = $this->getLayer()->getStateTags();
53
+ $this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
54
+ }
55
+ return $data;
56
+ }
57
+
58
+ /**
59
+ * Apply category filter to layer
60
+ *
61
+ * @param Zend_Controller_Request_Abstract $request
62
+ * @param Mage_Core_Block_Abstract $filterBlock
63
+ * @return Mage_Catalog_Model_Layer_Filter_Category
64
+ */
65
+ public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
66
+ {
67
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
68
+ return parent::apply($request, $filterBlock);
69
+ }
70
+
71
+ $filter = $request->getParam($this->getRequestVar());
72
+ if (!$filter) {
73
+ return $this;
74
+ }
75
+
76
+ // Load the category filter by url_key
77
+ $this->_appliedCategory = Mage::getModel('catalog/category')
78
+ ->setStoreId(Mage::app()->getStore()->getId())
79
+ ->loadByAttribute('url_key', $filter);
80
+
81
+ $this->_categoryId = $this->_appliedCategory->getId();
82
+
83
+ Mage::register('current_category_filter', $this->getCategory(), true);
84
+
85
+ if ($this->_isValidCategory($this->_appliedCategory)) {
86
+ $this->getLayer()->getProductCollection()
87
+ ->addCategoryFilter($this->_appliedCategory);
88
+
89
+ $this->getLayer()->getState()->addFilter(
90
+ $this->_createItem($this->_appliedCategory->getName(), $filter)
91
+ );
92
+ }
93
+
94
+ return $this;
95
+ }
96
+
97
+ }
app/code/community/Catalin/SEO/Model/Catalog/Layer/Filter/Item.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Model_Catalog_Layer_Filter_Item extends Mage_Catalog_Model_Layer_Filter_Item
18
+ {
19
+
20
+ protected $_helper;
21
+
22
+ protected function _helper()
23
+ {
24
+ if ($this->_helper === null) {
25
+ $this->_helper = Mage::helper('catalin_seo');
26
+ }
27
+ return $this->_helper;
28
+ }
29
+
30
+ /**
31
+ * Get filter item url
32
+ *
33
+ * @return string
34
+ */
35
+ public function getUrl()
36
+ {
37
+ if (!$this->_helper()->isEnabled()) {
38
+ return parent::getUrl();
39
+ }
40
+
41
+ $values = $this->getFilter()->getValues();
42
+ if (!empty($values)) {
43
+ $tmp = array_merge($values, array($this->getValue()));
44
+ $values = implode(Catalin_SEO_Helper_Data::MULTIPLE_FILTERS_DELIMITER, $tmp);
45
+ } else {
46
+ $values = $this->getValue();
47
+ }
48
+
49
+ if ($this->_helper()->isCatalogSearch()) {
50
+ $query = array(
51
+ 'isLayerAjax' => null,
52
+ $this->getFilter()->getRequestVar() => $values,
53
+ Mage::getBlockSingleton('page/html_pager')->getPageVarName() => null // exclude current page from urls
54
+ );
55
+ return Mage::getUrl('*/*/*', array('_current' => true, '_use_rewrite' => true, '_query' => $query));
56
+ }
57
+
58
+ return $this->_helper()->getFilterUrl(array(
59
+ $this->getFilter()->getRequestVar() => $values
60
+ ), false);
61
+ }
62
+
63
+ /**
64
+ * Get url for remove item from filter
65
+ *
66
+ * @return string
67
+ */
68
+ public function getRemoveUrl()
69
+ {
70
+ if (!$this->_helper()->isEnabled()) {
71
+ return parent::getRemoveUrl();
72
+ }
73
+
74
+ $values = $this->getFilter()->getValues();
75
+ if (!empty($values)) {
76
+ $tmp = array_diff($values, array($this->getValue()));
77
+ if (!empty($tmp)) {
78
+ $values = implode(Catalin_SEO_Helper_Data::MULTIPLE_FILTERS_DELIMITER, $tmp);
79
+ } else {
80
+ $values = null;
81
+ }
82
+ } else {
83
+ $values = null;
84
+ }
85
+ if ($this->_helper()->isCatalogSearch()) {
86
+ $query = array(
87
+ 'isLayerAjax' => null,
88
+ $this->getFilter()->getRequestVar() => $values
89
+ );
90
+ $params['_current'] = true;
91
+ $params['_use_rewrite'] = true;
92
+ $params['_query'] = $query;
93
+ $params['_escape'] = true;
94
+ return Mage::getUrl('*/*/*', $params);
95
+ }
96
+
97
+ return $this->_helper()->getFilterUrl(array(
98
+ $this->getFilter()->getRequestVar() => $values
99
+ ));
100
+ }
101
+
102
+ /**
103
+ * Check if current filter is selected
104
+ *
105
+ * @return boolean
106
+ */
107
+ public function isSelected()
108
+ {
109
+ $values = $this->getFilter()->getValues();
110
+ if (in_array($this->getValue(), $values)) {
111
+ return true;
112
+ }
113
+ return false;
114
+ }
115
+
116
+ }
app/code/community/Catalin/SEO/Model/Catalog/Resource/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Model_Catalog_Resource_Layer_Filter_Attribute extends Mage_Catalog_Model_Resource_Layer_Filter_Attribute
18
+ {
19
+
20
+ /**
21
+ * Apply attribute filter to product collection
22
+ *
23
+ * @param Mage_Catalog_Model_Layer_Filter_Attribute $filter
24
+ * @param int $value
25
+ * @return Mage_Catalog_Model_Resource_Layer_Filter_Attribute
26
+ */
27
+ public function applyFilterToCollection($filter, $value)
28
+ {
29
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
30
+ return parent::applyFilterToCollection($filter, $value);
31
+ }
32
+
33
+ $collection = $filter->getLayer()->getProductCollection();
34
+ $attribute = $filter->getAttributeModel();
35
+ $connection = $this->_getReadAdapter();
36
+ $tableAlias = $attribute->getAttributeCode() . '_idx' . uniqid();
37
+ $conditions = array(
38
+ "{$tableAlias}.entity_id = e.entity_id",
39
+ $connection->quoteInto("{$tableAlias}.attribute_id = ?", $attribute->getAttributeId()),
40
+ $connection->quoteInto("{$tableAlias}.store_id = ?", $collection->getStoreId()),
41
+ );
42
+
43
+ $options = $attribute->getSource()->getAllOptions(false);
44
+ if (!is_array($value)) {
45
+ foreach ($options as $option) {
46
+ if ($option['label'] == $value) {
47
+ $value = $option['value'];
48
+ }
49
+ }
50
+ $conditions[] = $connection->quoteInto("{$tableAlias}.value = ?", $value);
51
+ } else {
52
+ $conditions[] = "{$tableAlias}.value in ( ";
53
+ foreach ($value as $v) {
54
+ foreach ($options as $option) {
55
+ if ($option['label'] == $v) {
56
+ $v = $option['value'];
57
+ }
58
+ }
59
+ $conditions[count($conditions) - 1] .= $connection->quoteInto("?", $v) . ' ,';
60
+ }
61
+ $conditions[count($conditions) - 1] = rtrim($conditions[count($conditions) - 1], ',');
62
+ $conditions[count($conditions) - 1] .= ')';
63
+ }
64
+
65
+ $collection->getSelect()->join(
66
+ array($tableAlias => $this->getMainTable()), implode(' AND ', $conditions), array()
67
+ );
68
+ $collection->getSelect()->distinct();
69
+
70
+ return $this;
71
+ }
72
+
73
+ /**
74
+ * Retrieve array with products counts per attribute option
75
+ *
76
+ * @param Mage_Catalog_Model_Layer_Filter_Attribute $filter
77
+ * @return array
78
+ */
79
+ public function getCount($filter)
80
+ {
81
+ if (!Mage::helper('catalin_seo')->isEnabled()) {
82
+ return parent::getCount($filter);
83
+ }
84
+
85
+ // clone select from collection with filters
86
+ $select = clone $filter->getLayer()->getProductCollection()->getSelect();
87
+ // reset columns, order and limitation conditions
88
+ $select->reset(Zend_Db_Select::COLUMNS);
89
+ $select->reset(Zend_Db_Select::ORDER);
90
+ $select->reset(Zend_Db_Select::LIMIT_COUNT);
91
+ $select->reset(Zend_Db_Select::LIMIT_OFFSET);
92
+
93
+
94
+ $connection = $this->_getReadAdapter();
95
+ $attribute = $filter->getAttributeModel();
96
+ $tableAlias = sprintf('%s_idx', $attribute->getAttributeCode());
97
+ $conditions = array(
98
+ "{$tableAlias}.entity_id = e.entity_id",
99
+ $connection->quoteInto("{$tableAlias}.attribute_id = ?", $attribute->getAttributeId()),
100
+ $connection->quoteInto("{$tableAlias}.store_id = ?", $filter->getStoreId()),
101
+ );
102
+
103
+ // start removing all filters for current attribute - we need correct count
104
+ $parts = $select->getPart(Zend_Db_Select::FROM);
105
+ $from = array();
106
+ foreach ($parts as $key => $part) {
107
+ if (stripos($key, $tableAlias) === false) {
108
+ $from[$key] = $part;
109
+ }
110
+ }
111
+ $select->setPart(Zend_Db_Select::FROM, $from);
112
+ // end of removing
113
+
114
+ $select
115
+ ->join(
116
+ array($tableAlias => $this->getMainTable()), join(' AND ', $conditions), array('value', 'count' => new Zend_Db_Expr("COUNT({$tableAlias}.entity_id)")))
117
+ ->group("{$tableAlias}.value");
118
+
119
+ return $connection->fetchPairs($select);
120
+ }
121
+
122
+ }
app/code/community/Catalin/SEO/Model/CatalogSearch/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Model_CatalogSearch_Layer_Filter_Attribute extends Catalin_SEO_Model_Catalog_Layer_Filter_Attribute
18
+ {
19
+
20
+ /**
21
+ * Set filter model name
22
+ *
23
+ */
24
+ public function __construct()
25
+ {
26
+ parent::__construct();
27
+ $this->_filterModelName = 'catalogsearch/layer_filter_attribute';
28
+ }
29
+
30
+ }
app/code/community/Catalin/SEO/Model/System/Config/Backend/Seo/Catalog.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ class Catalin_SEO_Model_System_Config_Backend_Seo_Catalog extends Mage_Core_Model_Config_Data
18
+ {
19
+
20
+ /**
21
+ * After enabling layered navigation seo cache refresh is required
22
+ *
23
+ * @return Catalin_SEO_Model_System_Config_Backend_Seo_Catalog
24
+ */
25
+ protected function _afterSave()
26
+ {
27
+ if ($this->isValueChanged()) {
28
+ $instance = Mage::app()->getCacheInstance();
29
+ $instance->invalidateType('block_html');
30
+ }
31
+
32
+ return $this;
33
+ }
34
+
35
+ }
app/code/community/Catalin/SEO/controllers/CategoryController.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ require_once 'Mage/Catalog/controllers/CategoryController.php';
18
+
19
+ class Catalin_Seo_CategoryController extends Mage_Catalog_CategoryController
20
+ {
21
+
22
+ public function viewAction()
23
+ {
24
+ if (($category = $this->_initCatagory())) {
25
+ $design = Mage::getSingleton('catalog/design');
26
+ $settings = $design->getDesignSettings($category);
27
+
28
+ // apply custom design
29
+ if ($settings->getCustomDesign()) {
30
+ $design->applyCustomDesign($settings->getCustomDesign());
31
+ }
32
+
33
+ Mage::getSingleton('catalog/session')->setLastViewedCategoryId($category->getId());
34
+
35
+ $update = $this->getLayout()->getUpdate();
36
+ $update->addHandle('default');
37
+
38
+ if (!$category->hasChildren()) {
39
+ $update->addHandle('catalog_category_layered_nochildren');
40
+ }
41
+
42
+ $this->addActionLayoutHandles();
43
+ $update->addHandle($category->getLayoutUpdateHandle());
44
+ $update->addHandle('CATEGORY_' . $category->getId());
45
+ // apply custom ajax layout
46
+ if ($this->getRequest()->isAjax()) {
47
+ $update->addHandle('catalog_category_layered_ajax_layer');
48
+ }
49
+ $this->loadLayoutUpdates();
50
+
51
+ // apply custom layout update once layout is loaded
52
+ if (($layoutUpdates = $settings->getLayoutUpdates())) {
53
+ if (is_array($layoutUpdates)) {
54
+ foreach ($layoutUpdates as $layoutUpdate) {
55
+ $update->addUpdate($layoutUpdate);
56
+ }
57
+ }
58
+ }
59
+
60
+ $this->generateLayoutXml()->generateLayoutBlocks();
61
+ // apply custom layout (page) template once the blocks are generated
62
+ if ($settings->getPageLayout()) {
63
+ $this->getLayout()->helper('page/layout')->applyTemplate($settings->getPageLayout());
64
+ }
65
+
66
+ if (($root = $this->getLayout()->getBlock('root'))) {
67
+ $root->addBodyClass('categorypath-' . $category->getUrlPath())
68
+ ->addBodyClass('category-' . $category->getUrlKey());
69
+ }
70
+
71
+ $this->_initLayoutMessages('catalog/session');
72
+ $this->_initLayoutMessages('checkout/session');
73
+
74
+ // return json formatted response for ajax
75
+ if ($this->getRequest()->isAjax()) {
76
+ $listing = $this->getLayout()->getBlock('product_list')->toHtml();
77
+ $layer = $this->getLayout()->getBlock('catalog.leftnav')->toHtml();
78
+
79
+ $response = array(
80
+ 'listing' => $listing,
81
+ 'layer' => $layer
82
+ );
83
+
84
+ $this->getResponse()->setHeader('Content-Type', 'application/json', true);
85
+ $this->getResponse()->setBody(json_encode($response));
86
+ } else {
87
+ $this->renderLayout();
88
+ }
89
+ } elseif (!$this->getResponse()->isRedirect()) {
90
+ $this->_forward('noRoute');
91
+ }
92
+ }
93
+
94
+ }
app/code/community/Catalin/SEO/controllers/ResultController.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Catalin Ciobanu
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ *
13
+ * @package Catalin_Seo
14
+ * @copyright Copyright (c) 2012 Catalin Ciobanu
15
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
16
+ */
17
+ require_once 'Mage/CatalogSearch/controllers/ResultController.php';
18
+
19
+ class Catalin_Seo_ResultController extends Mage_CatalogSearch_ResultController
20
+ {
21
+
22
+ /**
23
+ * Display search result
24
+ */
25
+ public function indexAction()
26
+ {
27
+ $query = Mage::helper('catalogsearch')->getQuery();
28
+ /* @var $query Mage_CatalogSearch_Model_Query */
29
+
30
+ $query->setStoreId(Mage::app()->getStore()->getId());
31
+
32
+ if ($query->getQueryText() != '') {
33
+ if (Mage::helper('catalogsearch')->isMinQueryLength()) {
34
+ $query->setId(0)
35
+ ->setIsActive(1)
36
+ ->setIsProcessed(1);
37
+ } else {
38
+ if ($query->getId()) {
39
+ $query->setPopularity($query->getPopularity() + 1);
40
+ } else {
41
+ $query->setPopularity(1);
42
+ }
43
+
44
+ if ($query->getRedirect()) {
45
+ $query->save();
46
+ $this->getResponse()->setRedirect($query->getRedirect());
47
+ return;
48
+ } else {
49
+ $query->prepare();
50
+ }
51
+ }
52
+
53
+ Mage::helper('catalogsearch')->checkNotes();
54
+
55
+ $this->loadLayout();
56
+ // apply custom ajax layout
57
+ if ($this->getRequest()->isAjax()) {
58
+ $update = $this->getLayout()->getUpdate();
59
+ $update->addHandle('catalog_category_layered_ajax_layer');
60
+ }
61
+ $this->_initLayoutMessages('catalog/session');
62
+ $this->_initLayoutMessages('checkout/session');
63
+
64
+ // return json formatted response for ajax
65
+ if ($this->getRequest()->isAjax()) {
66
+ $listing = $this->getLayout()->getBlock('search_result_list')->toHtml();
67
+ $layer = $this->getLayout()->getBlock('catalogsearch.leftnav')->toHtml();
68
+
69
+ $response = array(
70
+ 'listing' => $listing,
71
+ 'layer' => $layer
72
+ );
73
+
74
+ $this->getResponse()->setHeader('Content-Type', 'application/json', true);
75
+ $this->getResponse()->setBody(json_encode($response));
76
+ } else {
77
+ $this->renderLayout();
78
+ }
79
+
80
+ if (!Mage::helper('catalogsearch')->isMinQueryLength()) {
81
+ $query->save();
82
+ }
83
+ } else {
84
+ $this->_redirectReferer();
85
+ }
86
+ }
87
+
88
+ }
app/code/community/Catalin/SEO/etc/adminhtml.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <acl>
4
+ <resources>
5
+ <admin>
6
+ <children>
7
+ <system>
8
+ <children>
9
+ <config>
10
+ <children>
11
+ <catalin_seo translate="title" module="catalin_seo">
12
+ <title>Catalin SEO</title>
13
+ </catalin_seo>
14
+ </children>
15
+ </config>
16
+ </children>
17
+ </system>
18
+ </children>
19
+ </admin>
20
+ </resources>
21
+ </acl>
22
+ </config>
app/code/community/Catalin/SEO/etc/config.xml ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <global>
4
+ <modules>
5
+ <Catalin_SEO>
6
+ <version>1.0.0</version>
7
+ </Catalin_SEO>
8
+ </modules>
9
+ <models>
10
+ <catalog>
11
+ <rewrite>
12
+ <layer_filter_item>Catalin_SEO_Model_Catalog_Layer_Filter_Item</layer_filter_item>
13
+ <layer_filter_category>Catalin_SEO_Model_Catalog_Layer_Filter_Category</layer_filter_category>
14
+ <layer_filter_attribute>Catalin_SEO_Model_Catalog_Layer_Filter_Attribute</layer_filter_attribute>
15
+ </rewrite>
16
+ </catalog>
17
+ <catalogsearch>
18
+ <rewrite>
19
+ <layer_filter_attribute>Catalin_SEO_Model_CatalogSearch_Layer_Filter_Attribute</layer_filter_attribute>
20
+ </rewrite>
21
+ </catalogsearch>
22
+ <catalog_resource>
23
+ <rewrite>
24
+ <layer_filter_attribute>Catalin_SEO_Model_Catalog_Resource_Layer_Filter_Attribute</layer_filter_attribute>
25
+ </rewrite>
26
+ </catalog_resource>
27
+ <catalin_seo>
28
+ <class>Catalin_SEO_Model</class>
29
+ </catalin_seo>
30
+ </models>
31
+ <blocks>
32
+ <catalog>
33
+ <rewrite>
34
+ <layer_state>Catalin_SEO_Block_Catalog_Layer_State</layer_state>
35
+ <product_list_toolbar>Catalin_SEO_Block_Catalog_Product_List_Toolbar</product_list_toolbar>
36
+ <layer_filter_attribute>Catalin_SEO_Block_Catalog_Layer_Filter_Attribute</layer_filter_attribute>
37
+ <layer_filter_price>Catalin_SEO_Block_Catalog_Layer_Filter_Price</layer_filter_price>
38
+ </rewrite>
39
+ </catalog>
40
+ <catalogsearch>
41
+ <rewrite>
42
+ <layer_filter_attribute>Catalin_SEO_Block_CatalogSearch_Layer_Filter_Attribute</layer_filter_attribute>
43
+ </rewrite>
44
+ </catalogsearch>
45
+ <catalin_seo>
46
+ <class>Catalin_SEO_Block</class>
47
+ </catalin_seo>
48
+ </blocks>
49
+ <helpers>
50
+ <catalin_seo>
51
+ <class>Catalin_SEO_Helper</class>
52
+ </catalin_seo>
53
+ </helpers>
54
+ <events>
55
+ <controller_front_init_routers>
56
+ <observers>
57
+ <catalin_seo>
58
+ <class>Catalin_SEO_Controller_Router</class>
59
+ <method>initControllerRouters</method>
60
+ </catalin_seo>
61
+ </observers>
62
+ </controller_front_init_routers>
63
+ </events>
64
+ </global>
65
+ <frontend>
66
+ <routers>
67
+ <catalog>
68
+ <args>
69
+ <modules>
70
+ <Catalin_SEO before="Mage_Catalog">Catalin_SEO</Catalin_SEO>
71
+ </modules>
72
+ </args>
73
+ </catalog>
74
+ <catalogsearch>
75
+ <args>
76
+ <modules>
77
+ <Catalin_SEO before="Mage_CatalogSearch">Catalin_SEO</Catalin_SEO>
78
+ </modules>
79
+ </args>
80
+ </catalogsearch>
81
+ </routers>
82
+ <layout>
83
+ <updates>
84
+ <catalin_seo module="Catalin_SEO">
85
+ <file>catalin_seo.xml</file>
86
+ </catalin_seo>
87
+ </updates>
88
+ </layout>
89
+ </frontend>
90
+ <default>
91
+ <catalin_seo>
92
+ <catalog>
93
+ <enabled>1</enabled>
94
+ <ajax_enabled>1</ajax_enabled>
95
+ <price_slider>1</price_slider>
96
+ <multiple_choise_filters>1</multiple_choise_filters>
97
+ </catalog>
98
+ </catalin_seo>
99
+ </default>
100
+ </config>
app/code/community/Catalin/SEO/etc/system.xml ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <tabs>
4
+ <catalin translate="label" module="catalin_seo">
5
+ <label>Catalin</label>
6
+ <sort_order>300</sort_order>
7
+ </catalin>
8
+ </tabs>
9
+ <sections>
10
+ <catalin_seo translate="label" module="catalin_seo">
11
+ <label>Catalin SEO</label>
12
+ <tab>catalin</tab>
13
+ <frontend_type>text</frontend_type>
14
+ <sort_order>1</sort_order>
15
+ <show_in_default>1</show_in_default>
16
+ <show_in_website>1</show_in_website>
17
+ <show_in_store>1</show_in_store>
18
+ <groups>
19
+ <catalog translate="label">
20
+ <label>Catalog Layered Navigation</label>
21
+ <frontend_type>text</frontend_type>
22
+ <sort_order>2</sort_order>
23
+ <show_in_default>1</show_in_default>
24
+ <show_in_website>1</show_in_website>
25
+ <show_in_store>1</show_in_store>
26
+ <fields>
27
+ <enabled translate="label">
28
+ <label>Enable</label>
29
+ <frontend_type>select</frontend_type>
30
+ <source_model>adminhtml/system_config_source_yesno</source_model>
31
+ <backend_model>catalin_seo/system_config_backend_seo_catalog</backend_model>
32
+ <sort_order>1</sort_order>
33
+ <show_in_default>1</show_in_default>
34
+ <show_in_website>1</show_in_website>
35
+ <show_in_store>1</show_in_store>
36
+ </enabled>
37
+ <ajax_enabled translate="label">
38
+ <label>Enable AJAX</label>
39
+ <frontend_type>select</frontend_type>
40
+ <source_model>adminhtml/system_config_source_yesno</source_model>
41
+ <backend_model>catalin_seo/system_config_backend_seo_catalog</backend_model>
42
+ <sort_order>2</sort_order>
43
+ <show_in_default>1</show_in_default>
44
+ <show_in_website>1</show_in_website>
45
+ <show_in_store>1</show_in_store>
46
+ <depends><enabled>1</enabled></depends>
47
+ </ajax_enabled>
48
+ <price_slider translate="label">
49
+ <label>Enable Price Slider</label>
50
+ <frontend_type>select</frontend_type>
51
+ <source_model>adminhtml/system_config_source_yesno</source_model>
52
+ <backend_model>catalin_seo/system_config_backend_seo_catalog</backend_model>
53
+ <sort_order>3</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <show_in_website>1</show_in_website>
56
+ <show_in_store>1</show_in_store>
57
+ <depends><enabled>1</enabled></depends>
58
+ </price_slider>
59
+ <multiple_choise_filters translate="label">
60
+ <label>Enable Multipe Choise Filter</label>
61
+ <frontend_type>select</frontend_type>
62
+ <source_model>adminhtml/system_config_source_yesno</source_model>
63
+ <backend_model>catalin_seo/system_config_backend_seo_catalog</backend_model>
64
+ <sort_order>4</sort_order>
65
+ <show_in_default>1</show_in_default>
66
+ <show_in_website>1</show_in_website>
67
+ <show_in_store>1</show_in_store>
68
+ <depends><enabled>1</enabled></depends>
69
+ </multiple_choise_filters>
70
+ </fields>
71
+ </catalog>
72
+ </groups>
73
+ </catalin_seo>
74
+ </sections>
75
+ </config>
app/design/frontend/default/default/layout/catalin_seo.xml ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <layout version="0.1.0">
3
+ <catalog_category_layered>
4
+ <reference name="head">
5
+ <action method="addItem">
6
+ <type>skin_css</type>
7
+ <name>css/price_slider/style.css</name>
8
+ </action>
9
+ </reference>
10
+ <reference name="product_list_toolbar">
11
+ <block type="catalin_seo/catalog_product_list_pager" name="product_list_toolbar_pager"/>
12
+ </reference>
13
+ <reference name="product_list">
14
+ <action method="setTemplate">
15
+ <template>catalin_seo/catalog/product/list.phtml</template>
16
+ </action>
17
+ </reference>
18
+ <reference name="catalog.leftnav">
19
+ <action method="setTemplate">
20
+ <template>catalin_seo/catalog/layer/view.phtml</template>
21
+ </action>
22
+ </reference>
23
+ </catalog_category_layered>
24
+
25
+ <catalog_category_layered_ajax_layer>
26
+ <remove name="right"/>
27
+ <remove name="header"/>
28
+ <remove name="head"/>
29
+ <remove name="footer"/>
30
+ </catalog_category_layered_ajax_layer>
31
+
32
+ <catalogsearch_result_index>
33
+ <reference name="head">
34
+ <action method="addItem">
35
+ <type>skin_css</type>
36
+ <name>css/price_slider/style.css</name>
37
+ </action>
38
+ </reference>
39
+ <reference name="search_result_list">
40
+ <action method="setTemplate">
41
+ <template>catalin_seo/catalog/product/list.phtml</template>
42
+ </action>
43
+ </reference>
44
+ <reference name="catalogsearch.leftnav">
45
+ <action method="setTemplate">
46
+ <template>catalin_seo/catalog/layer/view.phtml</template>
47
+ </action>
48
+ </reference>
49
+ <reference name="product_list_toolbar">
50
+ <block type="catalin_seo/catalog_product_list_pager" name="product_list_toolbar_pager"/>
51
+ </reference>
52
+ </catalogsearch_result_index>
53
+ </layout>
app/design/frontend/default/default/template/catalin_seo/catalog/layer/filter.phtml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ol>
2
+ <?php foreach ($this->getItems() as $_item): ?>
3
+ <li>
4
+ <?php if ($_item->getCount() > 0): ?>
5
+ <input type="checkbox"<?php if ($_item->isSelected()): ?> checked="checked" <?php endif; ?>
6
+ <?php if ($this->helper('catalin_seo')->isAjaxEnabled()): ?>
7
+ onclick="$(this).next().click()"
8
+ <?php else: ?>
9
+ onclick="setLocation('<?php echo ($_item->isSelected()) ? $this->urlEscape($_item->getRemoveUrl()) : $this->urlEscape($_item->getUrl()) ?>')"
10
+ <?php endif; ?>
11
+ />
12
+ <a
13
+ <?php if ($_item->isSelected()): ?>
14
+ onclick="$(this).previous().checked = false;"
15
+ <?php else: ?>
16
+ onclick="$(this).previous().checked = true;"
17
+ <?php endif; ?>
18
+ href="<?php echo ($_item->isSelected()) ? $_item->getRemoveUrl() : $_item->getUrl() ?>"
19
+ ><?php echo $_item->getLabel() ?></a>
20
+ <?php else: ?>
21
+ <?php echo $_item->getLabel() ?>
22
+ <?php endif; ?>
23
+ (<?php echo $_item->getCount() ?>)
24
+ </li>
25
+ <?php endforeach ?>
26
+ </ol>
app/design/frontend/default/default/template/catalin_seo/catalog/layer/price.phtml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="price-range" class="filter-track price-slider">
2
+ <span id="price-min" class="filter-handle price-slider-from" title="Scroll to set your minimum value"></span>
3
+ <span id="price-max" class="filter-handle price-slider-to" title="Scroll to set your maximum value"></span>
4
+ </div>
5
+ <ul>
6
+ <li>
7
+ <span id="price-min-display">0</span>
8
+ <span style="float: right;" id="price-max-display"><?php echo $this->getMaxPriceInt(); ?></span>
9
+ </li>
10
+ </ul>
11
+
12
+ <script type="text/javascript">
13
+ var maxPriceInt = <?php echo $this->getMaxPriceInt(); ?>;
14
+
15
+ function handlePriceEvent(val) {
16
+ var link = '<?php echo $this->getUrlPattern(); ?>';
17
+ if (val[0] != 0 || val[1] != maxPriceInt) {
18
+ var price = val.join('-');
19
+ link = link.replace('__PRICE_VALUE__', price);
20
+ <?php if ($this->helper('catalin_seo')->isAjaxEnabled()): ?>
21
+ handleEvent(link);
22
+ <?php else: ?>
23
+ window.location.href = link;
24
+ <?php endif; ?>
25
+ }
26
+ }
27
+
28
+ var handles = [$('price-min'), $('price-max')];
29
+ // horizontal slider control with preset values
30
+ new Control.Slider(handles, 'price-range', {
31
+ range: $R(0, maxPriceInt, false),
32
+ sliderValue: [0, maxPriceInt],
33
+ values: [
34
+ <?php for ($i = 0; $i <= $this->getMaxPriceInt(); $i++): ?>
35
+ <?php echo $i ?><?php echo ($i == $this->getMaxPriceInt()) ? '' : ',' ?>
36
+ <?php endfor; ?>
37
+ ],
38
+
39
+ restricted: true,
40
+ onChange: function(val){
41
+ handlePriceEvent(val);
42
+ },
43
+ onSlide: function(val){
44
+ $('price-max-display').innerHTML = val[1];
45
+ $('price-min-display').innerHTML = val[0];
46
+ }
47
+ });
48
+ </script>
app/design/frontend/default/default/template/catalin_seo/catalog/layer/view.phtml ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ($this->canShowBlock()): ?>
2
+ <?php if (!$this->getRequest()->isAjax()): ?>
3
+ <div id="layered-navigation">
4
+ <?php endif; ?>
5
+ <div class="block block-layered-nav">
6
+ <div class="block-title">
7
+ <strong><span><?php echo $this->__('Shop By') ?></span></strong>
8
+ </div>
9
+ <?php echo $this->getStateHtml() ?>
10
+ <div class="block-content">
11
+ <?php if ($this->getLayer()->getState()->getFilters()): ?>
12
+ <div class="actions"><a href="<?php echo $this->getClearUrl() ?>"><?php echo $this->__('Clear All') ?></a></div>
13
+ <?php endif; ?>
14
+ <?php if ($this->canShowOptions()): ?>
15
+ <p class="block-subtitle"><?php echo $this->__('Shopping Options') ?></p>
16
+ <dl id="narrow-by-list">
17
+ <?php $_filters = $this->getFilters() ?>
18
+ <?php foreach ($_filters as $_filter): ?>
19
+ <?php if ($_filter->getItemsCount()): ?>
20
+ <dt><?php echo $this->__($_filter->getName()) ?></dt>
21
+ <dd><?php echo $_filter->getHtml() ?></dd>
22
+ <?php endif; ?>
23
+ <?php endforeach; ?>
24
+ </dl>
25
+ <script type="text/javascript">decorateDataList('narrow-by-list')</script>
26
+ <?php endif; ?>
27
+ <?php if ($this->getLayer()->getState()->getFilters()): ?>
28
+ <div class="actions"><a href="<?php echo $this->getClearUrl() ?>"><?php echo $this->__('Clear All') ?></a></div>
29
+ <?php endif; ?>
30
+ </div>
31
+ </div>
32
+ <?php if (!$this->getRequest()->isAjax()): ?>
33
+ </div>
34
+ <?php endif; ?>
35
+ <?php endif; ?>
app/design/frontend/default/default/template/catalin_seo/catalog/product/list.phtml ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $_productCollection=$this->getLoadedProductCollection();
3
+ $_helper = $this->helper('catalog/output');
4
+ ?>
5
+ <?php if(!$_productCollection->count()): ?>
6
+ <p class="note-msg"><?php echo $this->__('There are no products matching the selection.') ?></p>
7
+ <?php else: ?>
8
+ <?php if (!$this->getRequest()->isAjax()): ?>
9
+ <div id="ajax-errors" style="display: none;">
10
+ <ul class="messages">
11
+ <li class="error-msg">
12
+ <ul>
13
+ <li><span><?php echo $this->__('An error occurred, please try again later.'); ?></span></li>
14
+ </ul>
15
+ </li>
16
+ </ul>
17
+ </div>
18
+ <div id="loading" style="display: none; margin-bottom: 10px; text-align: center;">
19
+ <img class="v-middle" alt="" src="<?php echo $this->getSkinUrl('images/opc-ajax-loader.gif'); ?>"> <?php echo $this->__('Loading, please wait...'); ?>
20
+ </div>
21
+ <div id="catalog-listing">
22
+ <?php endif; ?>
23
+ <div class="category-products">
24
+ <?php echo $this->getToolbarHtml() ?>
25
+ <?php // List mode ?>
26
+ <?php if($this->getMode()!='grid'): ?>
27
+ <?php $_iterator = 0; ?>
28
+ <ol class="products-list" id="products-list">
29
+ <?php foreach ($_productCollection as $_product): ?>
30
+ <li class="item<?php if( ++$_iterator == sizeof($_productCollection) ): ?> last<?php endif; ?>">
31
+ <?php // Product Image ?>
32
+ <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" class="product-image"><img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(135); ?>" width="135" height="135" alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" /></a>
33
+ <?php // Product description ?>
34
+ <div class="product-shop">
35
+ <div class="f-fix">
36
+ <?php $_productNameStripped = $this->stripTags($_product->getName(), null, true); ?>
37
+ <h2 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $_productNameStripped; ?>"><?php echo $_helper->productAttribute($_product, $_product->getName() , 'name'); ?></a></h2>
38
+ <?php if($_product->getRatingSummary()): ?>
39
+ <?php echo $this->getReviewsSummaryHtml($_product) ?>
40
+ <?php endif; ?>
41
+ <?php echo $this->getPriceHtml($_product, true) ?>
42
+ <?php if($_product->isSaleable()): ?>
43
+ <p><button type="button" title="<?php echo $this->__('Add to Cart') ?>" class="button btn-cart" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')"><span><span><?php echo $this->__('Add to Cart') ?></span></span></button></p>
44
+ <?php else: ?>
45
+ <p class="availability out-of-stock"><span><?php echo $this->__('Out of stock') ?></span></p>
46
+ <?php endif; ?>
47
+ <div class="desc std">
48
+ <?php echo $_helper->productAttribute($_product, $_product->getShortDescription(), 'short_description') ?>
49
+ <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $_productNameStripped ?>" class="link-learn"><?php echo $this->__('Learn More') ?></a>
50
+ </div>
51
+ <ul class="add-to-links">
52
+ <?php if ($this->helper('wishlist')->isAllow()) : ?>
53
+ <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
54
+ <?php endif; ?>
55
+ <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
56
+ <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
57
+ <?php endif; ?>
58
+ </ul>
59
+ </div>
60
+ </div>
61
+ </li>
62
+ <?php endforeach; ?>
63
+ </ol>
64
+ <script type="text/javascript">decorateList('products-list', 'none-recursive')</script>
65
+
66
+ <?php else: ?>
67
+
68
+ <?php // Grid Mode ?>
69
+
70
+ <?php $_collectionSize = $_productCollection->count() ?>
71
+ <?php $_columnCount = $this->getColumnCount(); ?>
72
+ <?php $i=0; foreach ($_productCollection as $_product): ?>
73
+ <?php if ($i++%$_columnCount==0): ?>
74
+ <ul class="products-grid">
75
+ <?php endif ?>
76
+ <li class="item<?php if(($i-1)%$_columnCount==0): ?> first<?php elseif($i%$_columnCount==0): ?> last<?php endif; ?>">
77
+ <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" class="product-image"><img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(135); ?>" width="135" height="135" alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" /></a>
78
+ <h2 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($_product->getName(), null, true) ?>"><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></a></h2>
79
+ <?php if($_product->getRatingSummary()): ?>
80
+ <?php echo $this->getReviewsSummaryHtml($_product, 'short') ?>
81
+ <?php endif; ?>
82
+ <?php echo $this->getPriceHtml($_product, true) ?>
83
+ <div class="actions">
84
+ <?php if($_product->isSaleable()): ?>
85
+ <button type="button" title="<?php echo $this->__('Add to Cart') ?>" class="button btn-cart" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')"><span><span><?php echo $this->__('Add to Cart') ?></span></span></button>
86
+ <?php else: ?>
87
+ <p class="availability out-of-stock"><span><?php echo $this->__('Out of stock') ?></span></p>
88
+ <?php endif; ?>
89
+ <ul class="add-to-links">
90
+ <?php if ($this->helper('wishlist')->isAllow()) : ?>
91
+ <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
92
+ <?php endif; ?>
93
+ <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
94
+ <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
95
+ <?php endif; ?>
96
+ </ul>
97
+ </div>
98
+ </li>
99
+ <?php if ($i%$_columnCount==0 || $i==$_collectionSize): ?>
100
+ </ul>
101
+ <?php endif ?>
102
+ <?php endforeach ?>
103
+ <script type="text/javascript">decorateGeneric($$('ul.products-grid'), ['odd','even','first','last'])</script>
104
+ <?php endif; ?>
105
+
106
+ <div class="toolbar-bottom">
107
+ <?php echo $this->getToolbarHtml() ?>
108
+ </div>
109
+ </div>
110
+ <?php if (!$this->getRequest()->isAjax()): ?>
111
+ </div>
112
+ <?php endif; ?>
113
+ <?php endif; ?>
114
+
115
+ <?php if ($this->helper('catalin_seo')->isAjaxEnabled() && !$this->getRequest()->isAjax()): ?>
116
+ <script type="text/javascript">
117
+ //<![CDATA[
118
+ function handleEvent(el, event) {
119
+ var link;
120
+ if (typeof el === 'string') {
121
+ link = el;
122
+ } else if (el.tagName.toLowerCase() === 'a') {
123
+ link = $(el).readAttribute('href');
124
+ } else if (el.tagName.toLowerCase() === 'select') {
125
+ link = $(el).getValue();
126
+ }
127
+
128
+ <?php // Add this parameter for full page caching systems ?>
129
+ if (link.indexOf('?') != -1) {
130
+ link = link + '&isLayerAjax=1';
131
+ } else {
132
+ link = link + '?isLayerAjax=1';
133
+ }
134
+
135
+ $('loading').show();
136
+ $('ajax-errors').hide();
137
+
138
+ new Ajax.Request(link, {
139
+ method: 'get',
140
+ onSuccess: function(transport) {
141
+ if (transport.responseJSON) {
142
+ $('catalog-listing').update(transport.responseJSON.listing);
143
+ $('layered-navigation').update(transport.responseJSON.layer);
144
+ ajaxListener();
145
+ } else {
146
+ $('ajax-errors').show();
147
+ }
148
+ $('loading').hide();
149
+ }
150
+ });
151
+ if (event) {
152
+ event.preventDefault();
153
+ }
154
+ }
155
+ function ajaxListener() {
156
+ var els;
157
+ els = $$('div.pager a').concat(
158
+ $$('div.sorter a'),
159
+ $$('div.pager select'),
160
+ $$('div.sorter select'),
161
+ $$('div.block-layered-nav a')
162
+ );
163
+ els.each(function(el) {
164
+ if (el.tagName.toLowerCase() === 'a') {
165
+ $(el).observe('click', function(event) {
166
+ handleEvent(this, event);
167
+ });
168
+ } else if (el.tagName.toLowerCase() === 'select') {
169
+ $(el).setAttribute('onchange', '');
170
+ $(el).observe('change', function(event) {
171
+ handleEvent(this, event);
172
+ });
173
+ }
174
+ });
175
+ }
176
+ document.observe("dom:loaded", function() {
177
+ ajaxListener();
178
+ });
179
+ //]]>
180
+ </script>
181
+ <?php endif; ?>
app/etc/modules/Catalin_SEO.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Catalin_SEO>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Catalog/>
9
+ </depends>
10
+ </Catalin_SEO>
11
+ </modules>
12
+ </config>
package.xml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Catalin_Seo</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">OSL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>ajax, seo urls, price slider, multiple selection for the same attribute.</summary>
10
+ <description>&lt;h2&gt;Layered Navigation SEO&lt;/h2&gt;&#xD;
11
+ &lt;p&gt;ajax, seo urls, price slider, multiple selection for the same attribute.&lt;/p&gt;&#xD;
12
+ &lt;h2&gt;Features&lt;/h2&gt;&#xD;
13
+ &lt;ul&gt;&#xD;
14
+ &lt;li&gt;ajax navigation&lt;/li&gt;&#xD;
15
+ &lt;li&gt;simple price slider&lt;/li&gt;&#xD;
16
+ &lt;li&gt;SEO URLs (http://www.example.com/apparel/shoes/list/color/Brown,Blue/shoe_type/Sandal.html)&lt;/li&gt;&#xD;
17
+ &lt;li&gt;multiple filters for the same attribute&lt;/li&gt;&#xD;
18
+ &lt;/ul&gt;&#xD;
19
+ &lt;p&gt;All the above features can be enabled/disabled from backend from "System -&gt; Configuration -&gt; Catalin SEO -&gt; Catalog Layered Navigation"&lt;/p&gt;&#xD;
20
+ &lt;h2&gt;Known Issues&lt;/h2&gt;&#xD;
21
+ &lt;ul&gt;&#xD;
22
+ &lt;li&gt;In the attribute values "," (comma) and "/" (slash) cannot be used.&lt;/li&gt;&#xD;
23
+ &lt;/ul&gt;</description>
24
+ <notes>ajax, seo urls, price slider, multiple selection for the same attribute.</notes>
25
+ <authors><author><name>Catalin</name><user>Ciobanu</user><email>ciobanu.catalin@yahoo.com</email></author></authors>
26
+ <date>2012-11-17</date>
27
+ <time>13:16:33</time>
28
+ <contents><target name="magecommunity"><dir name="Catalin"><dir name="SEO"><dir name="Block"><dir name="Catalog"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="b0fb7deaeec0d46bc170e510c3d6f73a"/><file name="Price.php" hash="73fe2b9d21dab816474ee8d662a530bd"/></dir><file name="State.php" hash="fece6cd5534ae48f0f9f9233a7f714af"/></dir><dir name="Product"><dir name="List"><file name="Pager.php" hash="5f41fc06bddb70fc2f7de3792c933879"/><file name="Toolbar.php" hash="6db34892e1937dd1e527c8ac2fda4746"/></dir></dir></dir><dir name="CatalogSearch"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="120da8cc984bf1d55428ee4cfeaedca5"/></dir></dir></dir></dir><dir name="Controller"><file name="Router.php" hash="71c67346a0c3e89775e5d7762c8a3588"/></dir><dir name="Helper"><file name="Data.php" hash="47a5e37ea96a12615ad1818f919d634f"/></dir><dir name="Model"><dir name="Catalog"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="cd5ef92601544ed236617881b0dd6352"/><file name="Category.php" hash="bc5df542ef28c4e7a9583ae441c550c8"/><file name="Item.php" hash="9d89a99bebad467ca14e50333c556649"/></dir></dir><dir name="Resource"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="ab59cb798f1069786a98408f6ebaf948"/></dir></dir></dir></dir><dir name="CatalogSearch"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="137c0b3795d3eea4da8442db3e05e7a0"/></dir></dir></dir><dir name="System"><dir name="Config"><dir name="Backend"><dir name="Seo"><file name="Catalog.php" hash="ea4cd41cf4e919935919585a22dfea29"/></dir></dir></dir></dir></dir><dir name="controllers"><file name="CategoryController.php" hash="3f3404592e64ffc3d3e302a92e76dc06"/><file name="ResultController.php" hash="660c07990539e5605112cb42e24c02d6"/></dir><dir name="etc"><file name="adminhtml.xml" hash="240f607b0156d1de84667b382ba3f73c"/><file name="config.xml" hash="9e2487e6c0eb5b09c43f65c01db3d882"/><file name="system.xml" hash="9fd01148901e15950868e312b96dbfde"/></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="default"><dir name="default"><dir name="css"><dir name="price_slider"><file name="style.css" hash="61d0b59ed239bc64deaf4aed969652cd"/></dir></dir><dir name="images"><dir name="price_slider"><file name="bkg_slider.png" hash="1b7a1eb7add1d2b2002501f4602c3d3e"/><file name="slider.png" hash="d77b417b68ba91402c3b7180b165110c"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Catalin_SEO.xml" hash="e0ad01abfe976aefb6587fcfb3bf0d2b"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="default"><dir name="default"><dir name="template"><dir name="catalin_seo"><dir><dir name="catalog"><dir name="layer"><file name="filter.phtml" hash="dd1d3278e691814f0cd242179e5bf53f"/><file name="price.phtml" hash="19f1583df9e7f14d81318c633b334a88"/><file name="view.phtml" hash="bc5f21109be4dab996b152e7a756fe03"/></dir><dir name="product"><file name="list.phtml" hash="bd332a192ed36c56c00968e13b599cd3"/></dir></dir></dir></dir></dir><dir name="layout"><file name="catalin_seo.xml" hash="61db4d9d696f2d12c562ae70a5164e4c"/></dir></dir></dir></dir></target></contents>
29
+ <compatible/>
30
+ <dependencies><required><php><min>5.2.0</min><max>5.4.0</max></php></required></dependencies>
31
+ </package>
skin/frontend/default/default/css/price_slider/style.css ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div.price-slider {
2
+ background: url("../../images/price_slider/bkg_slider.png") repeat-x scroll 0 0 transparent;
3
+ height: 17px;
4
+ }
5
+ div.price-slider .filter-handle {
6
+ height: 17px;
7
+ width: 17px;
8
+ cursor: e-resize;
9
+ display: block;
10
+ }
11
+ div.price-slider .price-slider-from {
12
+ background: url("../../images/price_slider/slider.png") no-repeat scroll 0 0 transparent;
13
+ }
14
+ div.price-slider .price-slider-to {
15
+ background: url("../../images/price_slider/slider.png") no-repeat scroll -19px 0 transparent;
16
+ cursor: w-resize;
17
+ margin-top: -17px;
18
+ }
skin/frontend/default/default/images/price_slider/bkg_slider.png ADDED
Binary file
skin/frontend/default/default/images/price_slider/slider.png ADDED
Binary file