Zero1_Seoredirects - Version 1.1.9

Version Notes

- added fix for persist query issue
- added fix for https:// / http:// redirect caching issue

Download this release

Release Info

Developer Arron Moss
Extension Zero1_Seoredirects
Version 1.1.9
Comparing to
See all releases


Code changes from version 1.1.1 to 1.1.9

Files changed (49) hide show
  1. app/code/community/Zero1/Seoredirects/Block/Adminhtml/Import.php +17 -10
  2. app/code/community/Zero1/Seoredirects/Block/Adminhtml/Import/Status.php +14 -0
  3. app/code/community/Zero1/Seoredirects/Block/Adminhtml/Import/StatusSummary.php +17 -0
  4. app/code/community/Zero1/Seoredirects/Block/Adminhtml/ImportLog.php +94 -0
  5. app/code/community/Zero1/Seoredirects/Block/Adminhtml/ImportLog/Grid.php +105 -0
  6. app/code/community/Zero1/Seoredirects/Block/Adminhtml/Manage.php +5 -5
  7. app/code/community/Zero1/Seoredirects/Block/Adminhtml/Manage/Grid.php +4 -0
  8. app/code/community/Zero1/Seoredirects/Block/Adminhtml/Manage/Report.php +14 -11
  9. app/code/community/Zero1/Seoredirects/Block/Adminhtml/System/Config/ImportUnlock.php +73 -0
  10. app/code/community/Zero1/Seoredirects/Helper/Data.php +43 -21
  11. app/code/community/Zero1/Seoredirects/Helper/License.php +57 -28
  12. app/code/community/Zero1/Seoredirects/Helper/Urls.php +2 -5
  13. app/code/community/Zero1/Seoredirects/Model/ImportLog.php +23 -0
  14. app/code/community/Zero1/Seoredirects/Model/ImportStatus.php +32 -0
  15. app/code/community/Zero1/Seoredirects/Model/Importer.php +206 -527
  16. app/code/community/Zero1/Seoredirects/Model/Importer/Abstract.php +339 -0
  17. app/code/community/Zero1/Seoredirects/Model/Importer/Google.php +155 -0
  18. app/code/community/Zero1/Seoredirects/Model/Importer/Local.php +46 -0
  19. app/code/community/Zero1/Seoredirects/Model/Observer.php +16 -10
  20. app/code/community/Zero1/Seoredirects/Model/Redirecter.php +216 -0
  21. app/code/community/Zero1/Seoredirects/Model/Redirection.php +133 -161
  22. app/code/community/Zero1/Seoredirects/Model/RedirectionValidator.php +97 -0
  23. app/code/community/Zero1/Seoredirects/Model/Redirector.php +0 -1
  24. app/code/community/Zero1/Seoredirects/Model/Resource/ImportLog.php +8 -0
  25. app/code/community/Zero1/Seoredirects/Model/Resource/ImportLog/Collection.php +24 -0
  26. app/code/community/Zero1/Seoredirects/Model/Resource/ImportStatus.php +8 -0
  27. app/code/community/Zero1/Seoredirects/Model/Resource/ImportStatus/Collection.php +21 -0
  28. app/code/community/Zero1/Seoredirects/Model/Resource/Redirection.php +30 -0
  29. app/code/community/Zero1/Seoredirects/Model/Url.php +197 -0
  30. app/code/community/Zero1/Seoredirects/Model/UrlFactory.php +213 -0
  31. app/code/community/Zero1/Seoredirects/README.md +23 -0
  32. app/code/community/Zero1/Seoredirects/controllers/Adminhtml/Seoredirects/ImportController.php +33 -1
  33. app/code/community/Zero1/Seoredirects/controllers/Adminhtml/Seoredirects/ImportLogController.php +19 -0
  34. app/code/community/Zero1/Seoredirects/controllers/Adminhtml/Seoredirects/ManageController.php +1 -0
  35. app/code/community/Zero1/Seoredirects/docs/tests.md +69 -0
  36. app/code/community/Zero1/Seoredirects/docs/tests/1/0.md +57 -0
  37. app/code/community/Zero1/Seoredirects/docs/tests/2/0.md +20 -0
  38. app/code/community/Zero1/Seoredirects/etc/adminhtml.xml +8 -1
  39. app/code/community/Zero1/Seoredirects/etc/config.xml +7 -1
  40. app/code/community/Zero1/Seoredirects/etc/system.xml +29 -31
  41. app/code/community/Zero1/Seoredirects/scripts/import.php +12 -0
  42. app/code/community/Zero1/Seoredirects/sql/zero1_seoredirects_setup/upgrade-1.1.1-1.1.2.php +84 -0
  43. app/design/adminhtml/default/default/layout/zero1/seoredirects.xml +14 -1
  44. app/design/adminhtml/default/default/template/zero1/seoredirects/import/container.phtml +3 -0
  45. app/design/adminhtml/default/default/template/zero1/seoredirects/import/status.phtml +6 -0
  46. app/design/adminhtml/default/default/template/zero1/seoredirects/import/status_summary.phtml +43 -0
  47. app/design/adminhtml/default/default/template/zero1/seoredirects/importLog.phtml +13 -0
  48. app/design/adminhtml/default/default/template/zero1/seoredirects/system/config/import_unlock.phtml +24 -0
  49. package.xml +6 -18
app/code/community/Zero1/Seoredirects/Block/Adminhtml/Import.php CHANGED
@@ -11,16 +11,23 @@ class Zero1_Seoredirects_Block_Adminhtml_Import extends Mage_Adminhtml_Block_Wid
11
 
12
  protected function _prepareLayout()
13
  {
14
- $this->_addButton('run', array(
15
- 'label' => Mage::helper('core')->__('Run Import'),
16
- 'onclick' =>
17
- 'new Ajax.Request(\''.$this->getUrl('*/*/run').'\', {
18
- onSuccess: function(transport){
19
- $(\'report-container\').update(transport.responseText);
20
- }
21
- });',
22
- 'class' => 'add',
23
- ));
 
 
 
 
 
 
 
24
 
25
  return parent::_prepareLayout();
26
  }
11
 
12
  protected function _prepareLayout()
13
  {
14
+ if(Zero1_Seoredirects_Model_Importer::isRunning()){
15
+ $this->_addButton('refresh_data', array(
16
+ 'label' => Mage::helper('core')->__('Refresh Data'),
17
+ 'onclick' => 'window.location =\''.$this->getUrl('*/*/*').'\';',
18
+ 'class' => 'add',
19
+ ));
20
+ }else{
21
+ $this->_addButton('run', array(
22
+ 'label' => Mage::helper('core')->__('Run Import'),
23
+ 'onclick' =>
24
+ 'new Ajax.Request(\''.$this->getUrl('*/*/run').'\', {
25
+ asynchronous: false,
26
+ method: \'get\'
27
+ }); window.location =\''.$this->getUrl('*/*/*').'\';',
28
+ 'class' => 'add',
29
+ ));
30
+ }
31
 
32
  return parent::_prepareLayout();
33
  }
app/code/community/Zero1/Seoredirects/Block/Adminhtml/Import/Status.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Block_Adminhtml_Import_Status extends Mage_Adminhtml_Block_Template{
3
+
4
+ public function __construct()
5
+ {
6
+ parent::__construct();
7
+ $this->setTemplate('zero1/seoredirects/import/status.phtml');
8
+ }
9
+
10
+ public function getStatus()
11
+ {
12
+ return Zero1_Seoredirects_Model_Importer::getStatus();
13
+ }
14
+ }
app/code/community/Zero1/Seoredirects/Block/Adminhtml/Import/StatusSummary.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Block_Adminhtml_Import_StatusSummary extends Mage_Adminhtml_Block_Template{
3
+
4
+ public function __construct()
5
+ {
6
+ parent::__construct();
7
+ $this->setTemplate('zero1/seoredirects/import/status_summary.phtml');
8
+ }
9
+
10
+ /**
11
+ * @return Zero1_Seoredirects_Model_Resource_ImportStatus_Collection
12
+ */
13
+ public function getStatusCollection()
14
+ {
15
+ return Mage::getModel('zero1_seo_redirects/importStatus')->getCollection();
16
+ }
17
+ }
app/code/community/Zero1/Seoredirects/Block/Adminhtml/ImportLog.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category Mage
22
+ * @package Mage_Adminhtml
23
+ * @copyright Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)
24
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25
+ */
26
+
27
+ /**
28
+ * Catalog manage products block
29
+ *
30
+ * @category Mage
31
+ * @package Mage_Adminhtml
32
+ * @author Magento Core Team <core@magentocommerce.com>
33
+ */
34
+ class Zero1_Seoredirects_Block_Adminhtml_ImportLog extends Mage_Adminhtml_Block_Widget_Container
35
+ {
36
+ /**
37
+ * Set template
38
+ */
39
+ public function __construct()
40
+ {
41
+ parent::__construct();
42
+ $this->setTemplate('zero1/seoredirects/importLog.phtml');
43
+ }
44
+
45
+ /**
46
+ * Prepare button and grid
47
+ *
48
+ * @return Zero1_Seoredirects_Block_Adminhtml_Manage
49
+ */
50
+ protected function _prepareLayout()
51
+ {
52
+ $this->_addButton('back', array(
53
+ 'label' => Mage::helper('catalog')->__('Back'),
54
+ 'onclick' => "setLocation('".$this->getUrl('*/seoredirects_manage/index')."')",
55
+ 'class' => 'back'
56
+ ));
57
+
58
+ $this->setChild('grid', $this->getLayout()->createBlock('zero1_seo_redirects/adminhtml_importLog_grid', 'import.grid'));
59
+ return parent::_prepareLayout();
60
+ }
61
+
62
+ /**
63
+ * Deprecated since 1.3.2
64
+ *
65
+ * @return string
66
+ */
67
+ public function getAddNewButtonHtml()
68
+ {
69
+ return $this->getChildHtml('add_new_button');
70
+ }
71
+
72
+ /**
73
+ * Render grid
74
+ *
75
+ * @return string
76
+ */
77
+ public function getGridHtml()
78
+ {
79
+ return $this->getChildHtml('grid');
80
+ }
81
+
82
+ /**
83
+ * Check whether it is single store mode
84
+ *
85
+ * @return bool
86
+ */
87
+ public function isSingleStoreMode()
88
+ {
89
+ if (!Mage::app()->isSingleStoreMode()) {
90
+ return false;
91
+ }
92
+ return true;
93
+ }
94
+ }
app/code/community/Zero1/Seoredirects/Block/Adminhtml/ImportLog/Grid.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category Mage
22
+ * @package Mage_Adminhtml
23
+ * @copyright Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)
24
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25
+ */
26
+
27
+ /**
28
+ * Adminhtml customer grid block
29
+ *
30
+ * @category Mage
31
+ * @package Mage_Adminhtml
32
+ * @author Magento Core Team <core@magentocommerce.com>
33
+ */
34
+ class Zero1_Seoredirects_Block_Adminhtml_ImportLog_Grid extends Mage_Adminhtml_Block_Widget_Grid
35
+ {
36
+
37
+ public function __construct()
38
+ {
39
+ parent::__construct();
40
+ $this->setId('importLogGrid');
41
+ $this->setDefaultSort('id');
42
+ $this->setDefaultDir('DESC');
43
+ $this->setSaveParametersInSession(true);
44
+ $this->setUseAjax(true);
45
+ //$this->setVarNameFilter('product_filter');
46
+ }
47
+
48
+ protected function _getStore()
49
+ {
50
+ $storeId = (int) $this->getRequest()->getParam('store', 0);
51
+ return Mage::app()->getStore($storeId);
52
+ }
53
+
54
+ protected function _prepareCollection()
55
+ {
56
+ /* @var $collection Zero1_Seoredirects_Model_Resource_ImportLog_Collection */
57
+ $collection = Mage::getModel('zero1_seo_redirects/importLog')->getCollection();
58
+ $this->setCollection($collection);
59
+ parent::_prepareCollection();
60
+ return $this;
61
+ }
62
+
63
+ protected function _prepareColumns()
64
+ {
65
+ $this->addColumn('id',
66
+ array(
67
+ 'header'=> Mage::helper('catalog')->__('ID'),
68
+ 'width' => '50px',
69
+ 'type' => 'number',
70
+ 'index' => 'id',
71
+ 'is_system' => true,
72
+ ));
73
+
74
+ $this->addColumn('scope', array(
75
+ 'header' => Mage::helper('catalog')->__('Scope'),
76
+ 'index' => 'scope',
77
+ ));
78
+
79
+ $this->addColumn('scope_id', array(
80
+ 'header' => Mage::helper('catalog')->__('Scope ID'),
81
+ 'index' => 'scope_id',
82
+ ));
83
+
84
+ $this->addColumn('severity', array(
85
+ 'header' => Mage::helper('catalog')->__('Severity'),
86
+ 'index' => 'severity',
87
+ ));
88
+
89
+ $this->addColumn('line_number', array(
90
+ 'header' => Mage::helper('catalog')->__('Line Number'),
91
+ 'index' => 'line_number',
92
+ ));
93
+
94
+ $this->addColumn('message', array(
95
+ 'header' => Mage::helper('catalog')->__('Message'),
96
+ 'index' => 'message',
97
+ ));
98
+ return parent::_prepareColumns();
99
+ }
100
+
101
+ public function getGridUrl()
102
+ {
103
+ return $this->getUrl('*/*/grid', array('_current'=>true));
104
+ }
105
+ }
app/code/community/Zero1/Seoredirects/Block/Adminhtml/Manage.php CHANGED
@@ -54,11 +54,11 @@ class Zero1_Seoredirects_Block_Adminhtml_Manage extends Mage_Adminhtml_Block_Wid
54
  'onclick' => "setLocation('".$this->getUrl('*/*/new')."')",
55
  'class' => 'add'
56
  ));
57
- // $this->_addButton('refresh', array(
58
- // 'label' => Mage::helper('catalog')->__('Refresh URLs'),
59
- // 'onclick' => "setLocation('{$this->getUrl('*/*/update')}')",
60
- // 'class' => 'refresh'
61
- // ));
62
 
63
  $this->setChild('grid', $this->getLayout()->createBlock('zero1_seo_redirects/adminhtml_manage_grid', 'redirect.grid'));
64
  return parent::_prepareLayout();
54
  'onclick' => "setLocation('".$this->getUrl('*/*/new')."')",
55
  'class' => 'add'
56
  ));
57
+ $this->_addButton('import_log', array(
58
+ 'label' => Mage::helper('catalog')->__('View Import Logs'),
59
+ 'onclick' => "setLocation('{$this->getUrl('*/seoredirects_importLog/index')}')",
60
+ 'class' => 'refresh'
61
+ ));
62
 
63
  $this->setChild('grid', $this->getLayout()->createBlock('zero1_seo_redirects/adminhtml_manage_grid', 'redirect.grid'));
64
  return parent::_prepareLayout();
app/code/community/Zero1/Seoredirects/Block/Adminhtml/Manage/Grid.php CHANGED
@@ -61,6 +61,10 @@ class Zero1_Seoredirects_Block_Adminhtml_Manage_Grid extends Mage_Adminhtml_Bloc
61
  'CONCAT({{from_url_path}}, IF({{from_url_query}}=\'\', \'\', \'?\'), {{from_url_query}})',
62
  array('from_url_path'=>'from_url_path', 'from_url_query'=>'from_url_query')
63
  );
 
 
 
 
64
 
65
  if ($store->getId()) {
66
  $collection->addFieldToFilter('store_id', $store->getId());
61
  'CONCAT({{from_url_path}}, IF({{from_url_query}}=\'\', \'\', \'?\'), {{from_url_query}})',
62
  array('from_url_path'=>'from_url_path', 'from_url_query'=>'from_url_query')
63
  );
64
+ $collection->addFilterToMap(
65
+ 'CONCAT(from_url_path, IF(from_url_query=\'\', \'\', \'?\'), from_url_query)',
66
+ 'CONCAT(from_url_path, IF(from_url_query="", "", "?"), from_url_query)'
67
+ );
68
 
69
  if ($store->getId()) {
70
  $collection->addFieldToFilter('store_id', $store->getId());
app/code/community/Zero1/Seoredirects/Block/Adminhtml/Manage/Report.php CHANGED
@@ -8,26 +8,29 @@ class Zero1_Seoredirects_Block_Adminhtml_Manage_Report extends Mage_Adminhtml_Bl
8
  }
9
 
10
  public function getLicenseCounts(){
11
- /* @var $redirection Zero1_Seoredirects_Model_Redirection */
12
- $redirection = Mage::getModel('zero1_seo_redirects/redirection');
13
- $resource = $redirection->getResource();
14
- $con = $resource->getReadConnection();
15
 
16
- $select = $con->select();
17
- $select->from('core_store as store_table', array(
18
- 'store_table.store_id',
19
- 'store_table.name',
20
- new Zend_Db_Expr('IF(store_table.store_id = 0,
 
 
 
21
  (SELECT
22
  COUNT(*)
23
  FROM
24
- zero1_seoredirects_redirection
25
  where
26
  status = 1),
27
  (SELECT
28
  COUNT(*)
29
  FROM
30
- zero1_seoredirects_redirection
31
  where
32
  store_id = store_table.store_id and status = 1)) as count')));
33
 
8
  }
9
 
10
  public function getLicenseCounts(){
11
+ /* @var $redirection Zero1_Seoredirects_Model_Redirection */
12
+ $redirection = Mage::getModel('zero1_seo_redirects/redirection');
13
+ $resource = $redirection->getResource();
14
+ $con = $resource->getReadConnection();
15
 
16
+ $storeTable = $resource->getTable('core/store');
17
+ $redirectsTable = $resource->getTable('zero1_seo_redirects/redirection');
18
+
19
+ $select = $con->select();
20
+ $select->from($storeTable.' as store_table', array(
21
+ 'store_table.store_id',
22
+ 'store_table.name',
23
+ new Zend_Db_Expr('IF(store_table.store_id = 0,
24
  (SELECT
25
  COUNT(*)
26
  FROM
27
+ '.$redirectsTable.'
28
  where
29
  status = 1),
30
  (SELECT
31
  COUNT(*)
32
  FROM
33
+ '.$redirectsTable.'
34
  where
35
  store_id = store_table.store_id and status = 1)) as count')));
36
 
app/code/community/Zero1/Seoredirects/Block/Adminhtml/System/Config/ImportUnlock.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Block_Adminhtml_System_Config_ImportUnlock
3
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
4
+ {
5
+ /*
6
+ * Set template
7
+ */
8
+ protected function _construct()
9
+ {
10
+ parent::_construct();
11
+ $this->setTemplate('zero1/seoredirects/system/config/import_unlock.phtml');
12
+ }
13
+
14
+ /**
15
+ * Remove scope label
16
+ *
17
+ * @param Varien_Data_Form_Element_Abstract $element
18
+ * @return string
19
+ */
20
+ public function render(Varien_Data_Form_Element_Abstract $element)
21
+ {
22
+ $element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
23
+ return parent::render($element);
24
+ }
25
+
26
+ /**
27
+ * Return element html
28
+ *
29
+ * @param Varien_Data_Form_Element_Abstract $element
30
+ * @return string
31
+ */
32
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
33
+ {
34
+ return $this->_toHtml();
35
+ }
36
+
37
+ public function getUnlockUrl()
38
+ {
39
+ return Mage::getSingleton('adminhtml/url')->getUrl('*/seoredirects_import/unlock');
40
+ }
41
+
42
+ /**
43
+ * Generate synchronize button html
44
+ * @return string
45
+ */
46
+ public function getButtonHtml()
47
+ {
48
+ $button = $this->getLayout()->createBlock('adminhtml/widget_button')
49
+ ->setData(array(
50
+ 'id' => 'unlock_button',
51
+ 'label' => $this->helper('adminhtml')->__('Unlock Import'),
52
+ 'onclick' => 'javascript:unlockImport(); return false;'
53
+ ));
54
+
55
+ return $button->toHtml();
56
+ }
57
+
58
+ public function getTrueImportStatus()
59
+ {
60
+ $result = exec('ps aux | grep Seoredirects/scripts/import.php | grep -v grep');
61
+
62
+ if($result){
63
+ return Zero1_Seoredirects_Model_Importer::RUNLOCK_RUNNING;
64
+ }else{
65
+ return Zero1_Seoredirects_Model_Importer::RUNLOCK_NOT_RUNNING;
66
+ }
67
+ }
68
+
69
+ public function getDBImportStatus()
70
+ {
71
+ return Zero1_Seoredirects_Model_Importer::getStatus();
72
+ }
73
+ }
app/code/community/Zero1/Seoredirects/Helper/Data.php CHANGED
@@ -9,8 +9,7 @@ class Zero1_Seoredirects_Helper_Data extends Mage_Core_Helper_Abstract
9
  const USE_GOOGLE_DOC_CONFIG_PATH = 'seoredirects/settings/use_google_docs';
10
  const LOG_404S_CONFIG_PATH = 'seoredirects/advanced_settings/log_404s';
11
  const LOG_404S_LIMIT_CONFIG_PATH = 'seoredirects/advanced_settings/log_404s_limit';
12
- const ENABLED_DEBUG_CONFIG_PATH = 'seoredirects/debug_settings/enable_debug';
13
- const DEBUG_IPS_CONFIG_PATH = 'seoredirects/debug_settings/debug_ips';
14
 
15
  const CONFIG_PATH_IMPORT_LOG_LEVEL = 'seoredirects/advanced_settings/import_log_level';
16
 
@@ -64,25 +63,34 @@ class Zero1_Seoredirects_Helper_Data extends Mage_Core_Helper_Abstract
64
  return $ips;
65
  }
66
 
67
- public function canDebug($store = null, $ip = null){
68
- if(!$this->getIsDebugEnabled($store)){
69
- return false;
70
- }
71
- if(!$ip){
72
- $ip = Mage::app()->getRequest()->getClientIp();
73
- }
74
- $debugIps = $this->getDebugIps($store);
75
- if(!empty($debugIps) && array_search($ip, $debugIps) === false){
76
- return false;
77
- }
78
-
79
- return true;
80
- }
81
-
82
  public function getLog404Limit($storeId = null){
83
  return (int)Mage::getStoreConfig(self::LOG_404S_LIMIT_CONFIG_PATH, $storeId);
84
  }
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  public function stripIgnoreables($storeId = null, $args = array()){
87
  if(!$storeId){
88
  $storeId = Mage::app()->getStore()->getId();
@@ -233,11 +241,25 @@ class Zero1_Seoredirects_Helper_Data extends Mage_Core_Helper_Abstract
233
  return $read->fetchAll($select, $params);
234
  }
235
 
236
- public function debug($message){
237
- if(!$this->canDebug()){return;}
238
- }
239
-
240
  public function getImportLogLevel($store = null){
241
  return (int)Mage::getStoreConfig(self::CONFIG_PATH_IMPORT_LOG_LEVEL, $store);
242
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
9
  const USE_GOOGLE_DOC_CONFIG_PATH = 'seoredirects/settings/use_google_docs';
10
  const LOG_404S_CONFIG_PATH = 'seoredirects/advanced_settings/log_404s';
11
  const LOG_404S_LIMIT_CONFIG_PATH = 'seoredirects/advanced_settings/log_404s_limit';
12
+ const PATH_TO_PHP = 'seoredirects/advanced_settings/path_to_php';
 
13
 
14
  const CONFIG_PATH_IMPORT_LOG_LEVEL = 'seoredirects/advanced_settings/import_log_level';
15
 
63
  return $ips;
64
  }
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  public function getLog404Limit($storeId = null){
67
  return (int)Mage::getStoreConfig(self::LOG_404S_LIMIT_CONFIG_PATH, $storeId);
68
  }
69
 
70
+ public function shouldLog404($storeId = null)
71
+ {
72
+ if($storeId){
73
+ $storeId = Mage::app()->getStore()->getId();
74
+ }
75
+ if(!$this->getIsLog404Enabled($storeId)){
76
+ return false;
77
+ }
78
+ $limit = $this->getLog404Limit($storeId);
79
+ if($limit == 0){
80
+ return true;
81
+ }
82
+ $loggedCount = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
83
+ ->addFieldToFilter('store_id', $storeId)
84
+ ->addFieldToFilter('source', Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_LOGGED_VALUE)
85
+ ->count();
86
+
87
+ if($loggedCount >= $limit){
88
+ return false;
89
+ }else{
90
+ return true;
91
+ }
92
+ }
93
+
94
  public function stripIgnoreables($storeId = null, $args = array()){
95
  if(!$storeId){
96
  $storeId = Mage::app()->getStore()->getId();
241
  return $read->fetchAll($select, $params);
242
  }
243
 
 
 
 
 
244
  public function getImportLogLevel($store = null){
245
  return (int)Mage::getStoreConfig(self::CONFIG_PATH_IMPORT_LOG_LEVEL, $store);
246
  }
247
+
248
+ public function getPhpLocation()
249
+ {
250
+ $phpLocation = exec('which php');
251
+ if(!$phpLocation){
252
+ $phpLocation = exec('php -v');
253
+ if($phpLocation && strpos($phpLocation, 'command not found') === false){
254
+ return 'php';
255
+ }
256
+ $phpLocation = Mage::getStoreConfig(self::PATH_TO_PHP);
257
+ if(!$phpLocation){
258
+ return 'php';
259
+ }
260
+ return $phpLocation;
261
+ }
262
+ return $phpLocation;
263
+ }
264
+
265
  }
app/code/community/Zero1/Seoredirects/Helper/License.php CHANGED
@@ -5,6 +5,8 @@ class Zero1_Seoredirects_Helper_License extends Mage_Core_Helper_Abstract
5
  private $_license_required_for_enterprise = true;
6
  protected $_licenceLimit = null;
7
 
 
 
8
  const DEFAULT_LIMIT = 50;
9
 
10
  public function isEnterprise()
@@ -25,10 +27,8 @@ class Zero1_Seoredirects_Helper_License extends Mage_Core_Helper_Abstract
25
  return false;
26
  }
27
 
28
- public function isValid()
29
  {
30
- $data = $this->getData();
31
-
32
  if($this->isEnterprise())
33
  {
34
  if($this->_license_required_for_enterprise && !isset($data['enterprise']))
@@ -37,12 +37,21 @@ class Zero1_Seoredirects_Helper_License extends Mage_Core_Helper_Abstract
37
  if($this->_license_required_for_community && !isset($data['community']))
38
  return false;
39
  }
 
 
 
 
40
 
41
  return true;
42
  }
43
 
44
  public function getData()
45
  {
 
 
 
 
 
46
  $store = Mage::app()->getStore(0);
47
 
48
  $data = array();
@@ -50,17 +59,49 @@ class Zero1_Seoredirects_Helper_License extends Mage_Core_Helper_Abstract
50
  $module_name = strtolower($module_name);
51
  $serial = base64_decode($store->getConfig($module_name.'/settings/serial'));
52
  $url = $store->getConfig('web/unsecure/base_url');
53
-
54
- if(!empty($url) && !empty($serial))
55
- {
56
- $hash = hash('sha256', '$4$W8DgMGQZ$Twn84iicE6FQo7wCrxnL4Aow5/w$'.$module_name.$url, true);
57
- $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
58
- $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
59
- $data = @unserialize(mcrypt_decrypt(MCRYPT_BLOWFISH, $hash, $serial, MCRYPT_MODE_ECB, $iv));
60
- $data = (!is_array($data)) ? array() : $data;
61
- }
62
-
63
- return $data;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
  public function getRequestURL($store = null)
@@ -76,19 +117,7 @@ class Zero1_Seoredirects_Helper_License extends Mage_Core_Helper_Abstract
76
 
77
  public function getLicenceLimit()
78
  {
79
- if(isset($this->_licenceLimit)) {
80
- $this->_licenceLimit;
81
- }
82
-
83
- $this->_licenceLimit = self::DEFAULT_LIMIT;
84
- if($this->isValid()) {
85
- $license_data = $this->getData();
86
-
87
- if(isset($license_data['limit'])) {
88
- $this->_licenceLimit = $license_data['limit'];
89
- }
90
- }
91
-
92
- return $this->_licenceLimit;
93
  }
94
  }
5
  private $_license_required_for_enterprise = true;
6
  protected $_licenceLimit = null;
7
 
8
+ private $licenseData = null;
9
+
10
  const DEFAULT_LIMIT = 50;
11
 
12
  public function isEnterprise()
27
  return false;
28
  }
29
 
30
+ public function isValid($data)
31
  {
 
 
32
  if($this->isEnterprise())
33
  {
34
  if($this->_license_required_for_enterprise && !isset($data['enterprise']))
37
  if($this->_license_required_for_community && !isset($data['community']))
38
  return false;
39
  }
40
+
41
+ if(!isset($data['limit'])){
42
+ return false;
43
+ }
44
 
45
  return true;
46
  }
47
 
48
  public function getData()
49
  {
50
+ if($this->licenseData){
51
+ return $this->licenseData;
52
+ }
53
+ $this->buildDefaultData();
54
+
55
  $store = Mage::app()->getStore(0);
56
 
57
  $data = array();
59
  $module_name = strtolower($module_name);
60
  $serial = base64_decode($store->getConfig($module_name.'/settings/serial'));
61
  $url = $store->getConfig('web/unsecure/base_url');
62
+
63
+ if(!$serial || !$url){
64
+ return $this->licenseData;
65
+ }
66
+
67
+ //try using legacy method full base url
68
+ $data = $this->decrypt($module_name, $url, $serial);
69
+ if($this->isValid($data)){
70
+ $this->licenseData = $data;
71
+ return $this->licenseData;
72
+ }
73
+
74
+ //try using new method domain only
75
+ $url = parse_url($url, PHP_URL_HOST);
76
+ $data = $this->decrypt($module_name, $url, $serial);
77
+ if($this->isValid($data)){
78
+ $this->licenseData = $data;
79
+ return $this->licenseData;
80
+ }
81
+
82
+ //nothing is valid
83
+ return $this->licenseData;
84
+ }
85
+
86
+ protected function decrypt($moduleName, $url, $serial)
87
+ {
88
+ $hash = hash('sha256', '$4$W8DgMGQZ$Twn84iicE6FQo7wCrxnL4Aow5/w$'.$moduleName.$url, true);
89
+ $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
90
+ $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
91
+ $data = @unserialize(mcrypt_decrypt(MCRYPT_BLOWFISH, $hash, $serial, MCRYPT_MODE_ECB, $iv));
92
+ $data = (!is_array($data)) ? array() : $data;
93
+ return $data;
94
+ }
95
+
96
+ protected function buildDefaultData()
97
+ {
98
+ $this->licenseData = array();
99
+ if($this->isEnterprise()){
100
+ $this->licenseData['enterprise'] = 1;
101
+ }else{
102
+ $this->licenseData['community'] = 1;
103
+ }
104
+ $this->licenseData['limit'] = self::DEFAULT_LIMIT;
105
  }
106
 
107
  public function getRequestURL($store = null)
117
 
118
  public function getLicenceLimit()
119
  {
120
+ $data = $this->getData();
121
+ return $data['limit'];
 
 
 
 
 
 
 
 
 
 
 
 
122
  }
123
  }
app/code/community/Zero1/Seoredirects/Helper/Urls.php CHANGED
@@ -8,7 +8,6 @@ class Zero1_Seoredirects_Helper_Urls extends Mage_Core_Helper_Abstract
8
  * @return array
9
  */
10
  public function parseUrl($url = '', $storeId = null){
11
- $this->_getHelper()->debug('parseUrl');
12
  $parsed = parse_url($url);
13
 
14
  //sort out issue where BASE PATH is domain.com/a/b
@@ -56,7 +55,6 @@ class Zero1_Seoredirects_Helper_Urls extends Mage_Core_Helper_Abstract
56
  $parsed['path'] = substr($parsed['path'], $stringLengthDifference);
57
  }
58
  }
59
- $this->_getHelper()->debug('base url: '.$baseUrl.PHP_EOL.'parsed: '.json_encode($parsed));
60
  }
61
 
62
  public function getAssocQuery($query){
@@ -64,9 +62,8 @@ class Zero1_Seoredirects_Helper_Urls extends Mage_Core_Helper_Abstract
64
  if($query == null || $query == ''){
65
  return $urlParams;
66
  }
67
- if($query[0] == '?'){
68
- $query = substr($query, 1);
69
- }
70
  if(strpos($query, '&') !== false){
71
  $params = explode('&', $query);
72
  }else{
8
  * @return array
9
  */
10
  public function parseUrl($url = '', $storeId = null){
 
11
  $parsed = parse_url($url);
12
 
13
  //sort out issue where BASE PATH is domain.com/a/b
55
  $parsed['path'] = substr($parsed['path'], $stringLengthDifference);
56
  }
57
  }
 
58
  }
59
 
60
  public function getAssocQuery($query){
62
  if($query == null || $query == ''){
63
  return $urlParams;
64
  }
65
+ $query = ltrim($query, '?');
66
+
 
67
  if(strpos($query, '&') !== false){
68
  $params = explode('&', $query);
69
  }else{
app/code/community/Zero1/Seoredirects/Model/ImportLog.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Zero1_Seoredirects_Model_ImportLog
4
+ *
5
+ * @method Zero1_Seoredirects_Model_ImportLog setScope(string $scope)
6
+ * @method string getScope()
7
+ * @method Zero1_Seoredirects_Model_ImportLog setScopeId(int $scopeId)
8
+ * @method int getScopeId()
9
+ * @method Zero1_Seoredirects_Model_ImportLog setSeverity(int $severity)
10
+ * @method int getSeverity()
11
+ * @method Zero1_Seoredirects_Model_ImportLog setLineNumber($lineNumber)
12
+ * @method int|null getLineNumber()
13
+ * @method Zero1_Seoredirects_Model_ImportLog setMessage(string $message)
14
+ * @method string getMessage()
15
+ * @method int getCreatedAt()
16
+ */
17
+ class Zero1_Seoredirects_Model_ImportLog extends Mage_Core_Model_Abstract
18
+ {
19
+ protected function _construct()
20
+ {
21
+ $this->_init('zero1_seo_redirects/importLog');
22
+ }
23
+ }
app/code/community/Zero1/Seoredirects/Model/ImportStatus.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Zero1_Seoredirects_Model_ImportStatus
4
+ *
5
+ * @method Zero1_Seoredirects_Model_ImportStatus setScope(string $scope)
6
+ * @method string getScope()
7
+ * @method Zero1_Seoredirects_Model_ImportStatus setScopeId(int $scopeId)
8
+ * @method int getScopeId()
9
+ * @method Zero1_Seoredirects_Model_ImportStatus setToBeImported(int $toBeImported)
10
+ * @method int getToBeImported()
11
+ * @method Zero1_Seoredirects_Model_ImportStatus setImported(int $imported)
12
+ * @method int getImported()
13
+ * @method int getCreatedAt()
14
+ * @method int getUpdatedAt()
15
+ */
16
+ class Zero1_Seoredirects_Model_ImportStatus extends Mage_Core_Model_Abstract
17
+ {
18
+ protected function _construct()
19
+ {
20
+ $this->_init('zero1_seo_redirects/importStatus');
21
+ }
22
+
23
+ protected function _beforeSave()
24
+ {
25
+ if(!$this->getCreatedAt()){
26
+ $this->setCreatedAt(
27
+ date('Y-m-d H:i:s', Mage::getSingleton('core/date')->timestamp(time()))
28
+ );
29
+ }
30
+ parent::_beforeSave();
31
+ }
32
+ }
app/code/community/Zero1/Seoredirects/Model/Importer.php CHANGED
@@ -4,601 +4,280 @@
4
  * Class Zero1_Seoredirects_Model_Importer
5
  *
6
  * @method Mage_Core_Model_Store getStore()
7
- * @method Mage_Core_Model_Website getWebsite();
 
 
8
  */
9
- class Zero1_Seoredirects_Model_Importer extends Varien_Object{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
- protected $_log = array();
12
- protected $_columns = array();
13
- protected $_lineNumber = 1;
14
- protected $_allowedUrls = null;
15
- protected $_model = null;
16
- protected $_zendHttpClient;
17
- protected $_usedIds = array();
18
-
19
- const COLUMN_PARTICIPATION_MANDATORY = 0;
20
- const COLUMN_PARTICIPATION_OPTIONAL = 1;
21
- const LOCATION_STORE = 0;
22
- const LOCATION_WEBSITE = 1;
23
- const LOCATION_DEFAULT = 2;
24
-
25
- public function _construct(){
26
- $this->_log = array();
27
- $this->_columns = array('from' => array('index' => 0, 'participation' => self::COLUMN_PARTICIPATION_MANDATORY),
28
- 'to' => array('index' => 1, 'participation' => self::COLUMN_PARTICIPATION_MANDATORY),
29
- 'type' => array('index' => 2, 'participation' => self::COLUMN_PARTICIPATION_OPTIONAL),
30
- 'persist_query' => array('index' => 3, 'participation' => self::COLUMN_PARTICIPATION_OPTIONAL),
31
- );
32
  }
33
 
34
- protected function _log($msg = '', $lineNumber = null, $severity = Zend_Log::DEBUG, $force = false){
35
- if($severity > Mage::helper('zero1_seo_redirects')->getImportLogLevel()&& !$force){
36
- return $this;
37
- }
38
- $log = array(
39
- 'line_number' => (($lineNumber === null)? $this->_lineNumber : $lineNumber),
40
- 'message' => $msg,
41
- 'severity' => $severity
42
- );
43
-
44
- switch($this->_getLocation()){
45
- case self::LOCATION_STORE:
46
- if(!isset($this->_log[$this->getWebsite()->getCode()])){
47
- $this->_log[$this->getWebsite()->getCode()] = array();
48
- $this->_log[$this->getWebsite()->getCode()]['log'] = array();
49
- $this->_log[$this->getWebsite()->getCode()]['stores'] = array();
50
- }
51
- if(!isset($this->_log[$this->getWebsite()->getCode()]['stores'][$this->getStore()->getCode()])){
52
- $this->_log[$this->getWebsite()->getCode()]['stores'][$this->getStore()->getCode()] = array();
53
- $this->_log[$this->getWebsite()->getCode()]['stores'][$this->getStore()->getCode()]['log'] = array();
54
- }
55
- $this->_log[$this->getWebsite()->getCode()]['stores'][$this->getStore()->getCode()]['log'][] = $log;
56
- break;
57
- case self::LOCATION_WEBSITE:
58
- if(!isset($this->_log[$this->getWebsite()->getCode()])){
59
- $this->_log[$this->getWebsite()->getCode()] = array();
60
- $this->_log[$this->getWebsite()->getCode()]['log'] = array();
61
- $this->_log[$this->getWebsite()->getCode()]['stores'] = array();
62
- }
63
- $this->_log[$this->getWebsite()->getCode()]['log'][] = $log;
64
- break;
65
- case self::LOCATION_DEFAULT:
66
- if(!isset($this->_log['default'])){
67
- $this->_log['default'] = array();
68
- $this->_log['default']['log'] = array();
69
- }
70
- $this->_log['default']['log'][] = $log;
71
  }
72
- return $this;
73
- }
74
 
75
- protected function _getLocation(){
76
- if($this->getStore() !== null){
77
- return self::LOCATION_STORE;
78
- }
79
- if($this->getWebsite() !== null){
80
- return self::LOCATION_WEBSITE;
 
81
  }
82
- return self::LOCATION_DEFAULT;
83
  }
84
 
85
- /**
86
- * @return Zero1_Seoredirects_Helper_Data
87
- */
88
- protected function _helper(){
89
- return Mage::helper('zero1_seo_redirects');
90
- }
91
-
92
- /**
93
- * @param bool $reset
94
- * @return Zero1_Seoredirects_Model_Redirection
95
- */
96
- protected function _getModel($reset = false){
97
- if($this->_model === null){
98
- $this->_model = Mage::getModel('zero1_seo_redirects/redirection');
99
- }
100
- if($reset){
101
- $this->_model->setData(array());
102
  }
103
- return $this->_model;
104
  }
105
 
106
- /**
107
- * @return Zend_Http_Client
108
- */
109
- protected function _getZendClient(){
110
- if (!$this->_zendHttpClient instanceof Zend_Http_Client) {
111
- $this->_zendHttpClient = new Zend_Http_Client();
112
- }
113
- return $this->_zendHttpClient;
114
- }
 
115
 
116
- public function import($store = null, $website = null){
117
- //get all ids of redirects type 'import'
118
  /* @var $website Mage_Core_Model_Website */
119
  foreach(Mage::app()->getWebsites(false) as $websiteId => $website){
120
  $this->setWebsite($website);
 
 
121
  $this->checkAndImportEnableds(null, $website->getId());
122
  /* @var $store Mage_Core_Model_Store */
123
  foreach($website->getStores(false) as $storeId => $store){
124
  $this->setStore($store);
 
 
125
  $this->checkAndImportEnableds($store->getId(), null);
126
 
127
  $this->setStore(null);
128
- $this->_allowedUrls = null;
129
  }
130
  $this->setWebsite(null);
131
- $this->_allowedUrls = null;
132
  }
133
  //do default to finish
 
 
134
  $this->checkAndImportEnableds();
135
 
136
- //delete now unused urls, and refresh license count
137
- $this->_clearUrls();
138
 
139
- return $this->_log;
 
 
 
 
140
  }
141
 
142
- protected function checkAndImportEnableds($storeId = null, $websiteId = null){
143
- if($this->_helper()->getIsEnabled($storeId, $websiteId)){
144
- $this->_log('Is Enabled', 'N/A', Zend_Log::INFO, true);
145
- if($this->_helper()->getIsGoogleDocEnabled($storeId, $websiteId)){
146
- $this->_log('Google Docs Is Enabled', 'N/A', Zend_Log::INFO, true);
147
- if($this->_helper()->getHasRemoteFile($storeId, $websiteId)){
148
- $this->_importRemote($this->_helper()->getRemoteFileUrl($storeId, $websiteId));
149
- }else{
150
- $this->_log('No remote file found', 'N/A', Zend_Log::INFO, true);
151
- }
152
- }else{
153
- $this->_log('Google Docs Is Not Enabled', 'N/A', Zend_Log::INFO, true);
154
- }
155
-
156
- if($this->_helper()->getIsLocalFileEnabled($storeId, $websiteId)){
157
- $this->_log('Local File Is Enabled', 'N/A', Zend_Log::INFO, true);
158
- if($this->_helper()->getHasLocalFile($storeId, $websiteId)){
159
- $this->_importLocal(Mage::helper('zero1_seo_redirects/files')->getFile($storeId, $websiteId));
160
- }else{
161
- $this->_log('Not local file found', 'N/A', Zend_Log::INFO, true);
162
- }
163
- }else{
164
- $this->_log('Local File Is Not Enabled', 'N/A', Zend_Log::INFO, true);
165
- }
166
 
167
- }else{
168
- $this->_log('Not enabled', 'N/A', Zend_Log::INFO, true);
169
- }
170
- }
 
 
 
 
 
171
 
172
- /**
173
- * @param $file Zero1_Seoredirects_Model_File
174
- */
175
- protected function _importLocal($file){
176
- $this->_log('Importing local file: '.$file->getInternalPath(),'N/A', Zend_Log::INFO, true);
177
- $handle = fopen($file->getInternalPath(), 'r');
178
- $this->_lineNumber = 0;
179
 
180
- while(!feof($handle)){
181
- $line = fgetcsv($handle);
182
- if($this->_lineNumber == 0){
183
- if(!$this->_checkHeaders($line)){
184
- $this->_importRow($line);
185
- }
186
- }else{
187
- $this->_importRow($line);
188
- }
189
- $this->_lineNumber++;
190
- }
191
- $this->_log('Total number of lines parsed: '.$this->_lineNumber, 'N/A', Zend_Log::INFO, true);
192
- fclose($handle);
193
- }
194
 
195
- protected function _importRemote($url = ''){
196
- $this->_log('Importing remote file: "'.$url.'"','N/A', Zend_Log::INFO, true);
197
- preg_match('/output=csv/', $url, $results, PREG_OFFSET_CAPTURE);
198
- if(!empty($results)){
199
- return $this->_importRemoteCsv($url);
200
- }else{
201
- preg_match('/pubhtml/', $url, $results, PREG_OFFSET_CAPTURE);
202
- if(!empty($results)){
203
- return $this->_importRemoteHtml($url);
204
- }else{
205
- $this->_log('File type could not be verified, aborting.','N/A', Zend_Log::WARN);
206
- return;
207
- }
208
  }
 
 
 
 
 
 
 
 
 
 
 
209
  }
210
 
211
- protected function _importRemoteHtml($url){
212
- $this->_log('Importing remote html: "'.$url.'"','N/A', Zend_Log::INFO, true);
213
- $content = '';
214
- try {
215
- $this->_getZendClient()->setUri($url);
216
- $content = $this->_getZendClient()->request()->getBody();
217
- } catch(Exception $e) {
218
- $this->_log('Failed to retrieve content from remote document "'.$url.'" Error: '.$e->getMessage(), 'N/A', Zend_Log::WARN);
219
- return;
220
- }
221
- if(preg_match('~<!DOCTYPE html>~', $content) != 1){
222
- $this->_log('Content from remote url, does not appear to html "'.$url.'"', 'N/A', Zend_Log::WARN);
223
- }
224
-
225
- $this->_lineNumber = 1;
226
- $doc = new DOMDocument();
227
- $doc->loadHTML($content);
228
- /* @var $tables DOMNodeList */
229
- $tables = $doc->getElementsByTagName('table');
230
- $table = $tables->item(0);
231
-
232
- /* @var $child DOMElement */
233
- foreach($table->childNodes as $child){
234
- if($child->nodeName !== 'tbody'){
235
- continue;
236
- }else{
237
- /* @var $row DOMElement */
238
- /* @var $cell DOMElement */
239
- foreach($child->childNodes as $row){
240
- $data = array();
241
- foreach($row->childNodes as $cell){
242
- if($cell->nodeName === 'td'){
243
- $data[] = $cell->textContent;
244
- }
245
- }
246
- if($this->_lineNumber == 1){
247
- if(!$this->_checkHeaders($data)){
248
- $this->_importRow($data);
249
- }
250
- }else{
251
- $this->_importRow($data);
252
- }
253
- $this->_lineNumber++;
254
  }
255
- $this->_log('Total number of lines parsed: '.$this->_lineNumber, 'N/A', Zend_Log::NOTICE, true);
256
- return;
257
  }
258
- }
259
- }
260
 
261
- protected function _importRemoteCsv($url){
262
- $this->_log('Importing remote csv: "'.$url.'"','N/A', Zend_Log::INFO, true);
263
- try {
264
- $this->_getZendClient()->setUri($url);
265
- $content = $this->_getZendClient()->request()->getBody();
266
- } catch(Exception $e) {
267
- $this->_log('Failed to retrieve content from remote document "'.$url.'" Error: '.$e->getMessage(), 'N/A', Zend_Log::WARN);
268
- return;
269
- }
270
-
271
- $this->_lineNumber = 1;
272
- foreach (explode(PHP_EOL, $content) as $line) {
273
- $data = str_getcsv($line);
274
- if($this->_lineNumber == 1){
275
- if(!$this->_checkHeaders($data)){
276
- $this->_importRow($data);
277
  }
278
  }else{
279
- $this->_importRow($data);
280
  }
281
- $this->_lineNumber++;
282
- }
283
- $this->_log('Total number of lines parsed: '.$this->_lineNumber, 'N/A', Zend_Log::NOTICE, true);
284
- return;
285
- }
286
 
287
- protected function _checkHeaders($data){
288
- $from = array_search('from-url', $data);
289
- $to = array_search('to-url', $data);
290
- $type = array_search('type', $data);
291
- $persistQuery = array_search('persist-query', $data);
292
- if($from === false || $to === false){
293
- $this->_log('No headers found, for headers to be found, you should at least specify \'from-url\' and \'to-url\' columns. You may also specify \'type\' and \'persist-query\'', null, Zend_Log::WARN);
294
- if($from === false){
295
- $this->_columns['from']['index'] = 0;
296
- }else{
297
- $this->_columns['from']['index'] = $from;
298
- }
299
- if($to === false){
300
- $this->_columns['to']['index'] = 1;
301
- }else{
302
- $this->_columns['to']['index'] = $to;
303
- }
304
- return false;
305
- }
306
- $this->_columns['from']['index'] = $from;
307
- $this->_columns['to']['index'] = $to;
308
- if($type !== false){
309
- $this->_columns['type']['index'] = $type;
310
- }
311
- if($persistQuery !== false){
312
- $this->_columns['persist_query']['index'] = $persistQuery;
313
- }
314
- $this->_log('Headers found ('.json_encode(array_keys($this->_columns)).')', null, Zend_Log::INFO);
315
- return true;
316
- }
317
-
318
- protected function _importRow($data){
319
- $this->_log('_importRow: '.json_encode($data), null, Zend_Log::DEBUG);
320
- $from = $this->_getCell('from', $this->_columns['from'], $data);
321
- $to = $this->_getCell('to', $this->_columns['to'], $data);
322
- if($from === false || $to === false){ return; }
323
-
324
- $type = $this->_parseType($this->_getCell('type', $this->_columns['type'], $data));
325
- $persistQuery = $this->_parsePersistQuery($this->_getCell('persist-query', $this->_columns['persist_query'], $data));
326
-
327
- $allowedUrls = $this->_getAllowedUrls();
328
-
329
- //check that there is a match in the allowed urls
330
- $storeMatched = false;
331
- $currentMatch = '';
332
- foreach($allowedUrls as $storeUrl => $data){
333
- if(strpos($from, $storeUrl) === 0){
334
- if(strlen($storeUrl) > strlen($currentMatch)){
335
- $storeMatched = true;
336
- $currentMatch = $storeUrl;
337
- }
338
- }
339
- }
340
-
341
- if($storeMatched){
342
- $storeId = $allowedUrls[$currentMatch]['store_id'];
343
- }else{
344
-
345
- if(strpos($from, '://') !== false || $from[0] !== '/'){
346
- $this->_log('Skipped as from url location did not match any of the allowed stores.', null, Zend_Log::WARN);
347
- return;
348
- }
349
-
350
- $this->_log('Relative path found, prepending both \'from\' and \'to\' with current scope url', null, Zend_Log::NOTICE);
351
-
352
- switch($this->_getLocation()){
353
- case self::LOCATION_STORE:
354
- $storeId = $this->getStore()->getId();
355
- break;
356
- case self::LOCATION_WEBSITE:
357
- $storeId = $this->getWebsite()->getId();
358
- break;
359
- default:
360
- $storeId = 0;
361
- }
362
- $from = $this->getBaseUrl().substr($from, 1);
363
- $to = $this->getBaseUrl().substr($to, 1);
364
- }
365
-
366
- $from = Mage::helper('zero1_seo_redirects/urls')->parseUrl($from, $storeId);
367
- $to = Mage::helper('zero1_seo_redirects/urls')->parseUrl($to, $storeId);
368
-
369
- if(!isset($from['scheme'], $from['host'], $from['path'], $to['scheme'], $to['host'], $to['path']) ||
370
- $from['scheme'] != $to['scheme'] || $from['host'] != $to['host']
371
- ){
372
- $this->_log('Skipped as to url location did not match the domain as the from url', null, Zend_Log::WARN);
373
- return;
374
- }
375
-
376
- //has this redirect previously been imported?
377
- /* @var $redirectCollection Zero1_Seoredirects_Model_Resource_Redirection_Collection */
378
- $redirectCollection = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
379
- ->addFieldToFilter('from_url_path', $from['path'])
380
- ->addFieldToFilter('from_url_query', (isset($from['query'])? $from['query'] : null))
381
- ->addFieldToFilter('store_id', $storeId);
382
-
383
- //the redirect has already imported/created so just make sure that it has a IMPORT source
384
- if($redirectCollection->count()){
385
- $redirect = $redirectCollection->getFirstItem();
386
- //check if redirect has already been used.
387
- if($this->_checkId($redirect->getId()) !== false){
388
- $redirect = $this->_getModel(true);
389
- $redirect->setFromUrlPath($from['path'])
390
- ->setFromUrlQuery((isset($from['query'])? $from['query'] : null))
391
- ->setStoreId($storeId)
392
- ->setFromType($type)
393
- ->setPersistQuery($persistQuery);
394
- }
395
  }else{
396
- //no redirect exists
397
- $redirect = $this->_getModel(true);
398
- $redirect->setFromUrlPath($from['path'])
399
- ->setFromUrlQuery((isset($from['query'])? $from['query'] : null))
400
- ->setStoreId($storeId)
401
- ->setFromType($type)
402
- ->setPersistQuery($persistQuery);
403
- }
404
- $redirect->setSource(Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_IMPORT_VALUE)
405
- ->setToUrl($this->_buildUrl($to));
406
- try{
407
- $redirect->save();
408
- $this->_removeId($redirect->getId());
409
- }
410
- catch(Zero1_Seoredirects_Exception $e){
411
- $messages = $e->getMessages();
412
- foreach($messages as $err){
413
- $this->_log($err.' Redirect was not imported.', null, Zend_Log::WARN);
414
- }
415
- }
416
- catch(Exception $e){
417
- //TODO maybe just throw this?
418
- $this->_log($e->getMessage(), null, Zend_Log::CRIT);
419
  }
420
-
421
  }
422
 
423
- protected function _getCell($colName, $col, $data){
424
- if(isset($data[$col['index']])){
425
- $result = $data[$col['index']];
426
- }else{
427
- if($col['participation'] == self::COLUMN_PARTICIPATION_MANDATORY){
428
- $this->_log('Could not find column "'.$colName.'", skipping this row', null, Zend_Log::WARN);
429
- }else{
430
- $this->_log('Could not find column "'.$colName.'"', null, Zend_Log::NOTICE);
431
- }
432
- return false;
433
- }
434
- if($result == ''){
435
- if($col['participation'] == self::COLUMN_PARTICIPATION_MANDATORY){
436
- $this->_log('Empty cell in column "'.$colName.'", skipping this row', null, Zend_Log::WARN);
437
- }else{
438
- $this->_log('Empty cell in column "'.$colName.'"', null, Zend_Log::NOTICE);
439
- }
440
- $result = false;
441
- }
442
- return $result;
443
- }
444
-
445
  /**
446
- * returns an array of urls that are allowed for the current location
447
- * @return array
448
  */
449
- protected function _getAllowedUrls(){
450
- if($this->_allowedUrls !== null){
451
- return $this->_allowedUrls;
452
- }
453
- $this->_allowedUrls = array();
454
- switch($this->_getLocation()){
455
- case self::LOCATION_STORE:
456
- $this->_addToAlloweds($this->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false), $this->getStore());
457
- $this->_addToAlloweds($this->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true), $this->getStore());
458
- break;
459
- case self::LOCATION_WEBSITE:
460
- foreach($this->getWebsite()->getStores(false) as $storeId => $store){
461
- $this->_addToAlloweds($store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false), $store);
462
- $this->_addToAlloweds($store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true), $store);
463
- }
464
- break;
465
- case self::LOCATION_DEFAULT:
466
- foreach(Mage::app()->getWebsites(false) as $websiteId => $website){
467
- foreach($website->getStores(false) as $storeId => $store){
468
- $this->_addToAlloweds($store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false), $store);
469
- $this->_addToAlloweds($store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true), $store);
470
- }
471
- }
472
- }
473
- return $this->_allowedUrls;
474
- }
475
- protected function getBaseUrl(){
476
- switch($this->_getLocation()){
477
- case self::LOCATION_STORE:
478
- $url = Mage::app()->getStore($this->getStore()->getId())->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false);
479
- break;
480
- case self::LOCATION_WEBSITE:
481
- $url = Mage::app()->getWebsite($this->getWebsite()->getId())->getConfig('web/unsecure/base_link_url');
482
- if(strpos($url, '{{unsecure_base_url}}') !== false){
483
- $url = Mage::app()->getStore(0)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false);
484
- }
485
- break;
486
- case self::LOCATION_DEFAULT:
487
- default:
488
- $url = Mage::app()->getStore(0)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false);
489
- break;
490
- }
491
- return $url;
492
- }
493
- protected function _addToAlloweds($url, $store){
494
- $this->_allowedUrls[$url] = array(
495
- 'store_id' => $store->getId(),
496
- 'url' => parse_url($url),
497
- );
498
- }
499
- protected function _parseType($type = null){
500
- switch($type){
501
- case Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_LABEL:
502
- $t = Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_VALUE;
503
- break;
504
- case Zero1_Seoredirects_Model_Redirection::FROM_TYPE_OPEN_ENDED_QUERY_LABEL:
505
- $t = Zero1_Seoredirects_Model_Redirection::FROM_TYPE_OPEN_ENDED_QUERY_VALUE;
506
- break;
507
- default:
508
- $t = Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_VALUE;
509
- $this->_log('No type found defaulting to fixed, options are: '.Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_LABEL.', '.Zero1_Seoredirects_Model_Redirection::FROM_TYPE_OPEN_ENDED_QUERY_LABEL, null, Zend_Log::INFO);
510
- }
511
- return $t;
512
- }
513
-
514
- protected function _parsePersistQuery($persistQuery = null){
515
- switch($persistQuery){
516
- case 'No':
517
- $t = 0;
518
- break;
519
- case 'Yes':
520
- $t = 1;
521
- break;
522
- default:
523
- $t = 0;
524
- $this->_log('No matching value found for persist query, options are: \'Yes\' or \'No\'. Defaulting to No', null, Zend_Log::INFO);
525
- }
526
- return $t;
527
- }
528
-
529
- /**
530
- * Remove id from the pool of allowed ids
531
- * @param $id
532
- */
533
- protected function _removeId($id){
534
- $this->_usedIds[] = $id;
535
- }
536
-
537
- /**
538
- * check if the redirect has been imported already
539
- * @param $id
540
- */
541
- protected function _checkId($id){
542
- return array_search($id, $this->_usedIds);
543
- }
544
-
545
- /**
546
- * Any url that is of type import and wasn't imported this run, remove.
547
- */
548
- protected function _clearUrls(){
549
- if(empty($this->_usedIds)){
550
- return;
551
- }
552
- //delete all imported urls for this store that are of type import
553
  /* @var $redirectionCollection Zero1_Seoredirects_Model_Resource_Redirection_Collection */
554
  $redirectionCollection = Mage::getModel('zero1_seo_redirects/redirection')->getCollection();
555
- $redirectionCollection
556
- ->addFieldToFilter('source', Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_IMPORT_VALUE)
557
- ->addFieldToFilter('redirection_id', array('nin' => array($this->_usedIds)));
558
- $this->_log('Deleting: '.$redirectionCollection->count().' redirects', 'N/A', Zend_Log::INFO);
559
- $redirectionCollection->delete();
560
- $this->_recalculateStatuses();
 
 
 
561
  }
562
 
563
- /**
564
- * If the number of enabled redirects is lower than the limit, and there are disabled redirects, enable all up to limit
565
- * this occurs because a clean down of the urls occurs last.
566
- */
567
- protected function _recalculateStatuses(){
568
- /* @var $redirectionCollection Zero1_Seoredirects_Model_Resource_Redirection_Collection */
569
- $enabledRedirectionCount = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
570
- ->addFieldToFilter('status', Zero1_Seoredirects_Model_Redirection::REDIRECTION_STATUS_ENABLED_VALUE)
571
- ->count();
 
 
572
 
573
  /* @var $licenseHelper Zero1_SeoRedirects_Helper_License */
574
  $licenseHelper = Mage::helper('zero1_seo_redirects/license');
575
  $licenseLimit = $licenseHelper->getLicenceLimit();
576
 
577
- if($enabledRedirectionCount < $licenseLimit || $licenseLimit == 0){
578
- $redirectionCollection = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
579
  ->addFieldToFilter('source', array('neq' => Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_LOGGED_VALUE))
580
- ->addFieldToFilter('status', Zero1_Seoredirects_Model_Redirection::REDIRECTION_STATUS_DISABLED_VALUE);
581
 
582
  if($licenseLimit > 0){
583
  $redirectionCollection->setPageSize($licenseLimit - $enabledRedirectionCount);
584
  $redirectionCollection->setCurPage(1);
585
  }
586
- /* @var $redirect Zero1_Seoredirects_Model_Redirection */
587
- foreach($redirectionCollection as $redirect){
588
- $redirect->setStatus(Zero1_Seoredirects_Model_Redirection::REDIRECTION_STATUS_ENABLED_VALUE);
589
- $redirect->save();
590
- }
591
- }
592
- }
593
-
594
- protected function _buildUrl($parsedUrl){
595
- $url = $parsedUrl['path'];
596
- if(isset($parsedUrl['query'])){
597
- $url .= '?'.$parsedUrl['query'];
598
- }
599
- return $url;
600
- }
601
 
 
 
 
 
 
 
602
 
 
 
 
 
 
 
 
 
 
603
 
 
 
 
 
 
 
 
 
604
  }
4
  * Class Zero1_Seoredirects_Model_Importer
5
  *
6
  * @method Mage_Core_Model_Store getStore()
7
+ * @method setStore(Mage_Core_Model_Store $storeId)
8
+ * @method Mage_Core_Model_Website getWebsite()
9
+ * @method setWebsite(Mage_Core_Model_Website $websiteId)
10
  */
11
+ class Zero1_Seoredirects_Model_Importer extends Varien_Object
12
+ {
13
+ const CONFIG_PATH_RUNLOCK = 'seoredirects/advanced_settings/import_status';
14
+ const RUNLOCK_RUNNING = 'running';
15
+ const RUNLOCK_NOT_RUNNING = 'not running';
16
+ const RUNLOCK_ERRORED = 'error';
17
+
18
+ protected $redirector = null;
19
+ protected $localImporter = null;
20
+ protected $googleImporter = null;
21
+ protected $startTime = null;
22
+
23
+ protected $scope = null;
24
+ protected $scopeId = null;
25
+ const SCOPE_DEFAULT = 'default';
26
+ const SCOPE_STORE = 'store';
27
+ const SCOPE_WEBSITE = 'website';
28
+ const SCOPE_SYSTEM = 'system';
29
+ const SCOPE_SUMMARY = 'summary';
30
 
31
+ /**
32
+ * @return Zero1_Seoredirects_Helper_Data
33
+ */
34
+ protected function getHelper()
35
+ {
36
+ return Mage::helper('zero1_seo_redirects');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
 
39
+ /**
40
+ * @return Zero1_Seoredirects_Model_Importer_Local
41
+ */
42
+ protected function getLocalImporter()
43
+ {
44
+ if(!$this->localImporter){
45
+ $this->localImporter = Mage::getModel('zero1_seo_redirects/importer_local');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
+ return $this->localImporter;
48
+ }
49
 
50
+ /**
51
+ * @return Zero1_Seoredirects_Model_Importer_Google
52
+ */
53
+ protected function getGoogleImporter()
54
+ {
55
+ if(!$this->googleImporter){
56
+ $this->googleImporter = Mage::getModel('zero1_seo_redirects/importer_google');
57
  }
58
+ return $this->googleImporter;
59
  }
60
 
61
+ public function import()
62
+ {
63
+ try{
64
+ $this->run();
65
+ }catch(Exception $e){
66
+ $this->log($e->getMessage().PHP_EOL.$e->getTraceAsString(), null, Zend_Log::CRIT, self::SCOPE_SYSTEM, 0);
67
+ /** @var Mage_Core_Model_Config_Data $config */
68
+ $config = $this->getRunLockConfig();
69
+ $config->setValue(self::RUNLOCK_ERRORED)->save();
70
+ Mage::log($e->getMessage(), Zend_Log::DEBUG, 'seo.log', true);
71
+ Mage::log($e->getTraceAsString(), Zend_Log::DEBUG, 'seo.log', true);
 
 
 
 
 
 
72
  }
 
73
  }
74
 
75
+ protected function run()
76
+ {
77
+ if($this->isRunning()){
78
+ //Mage::log('already running', Zend_Log::ALERT, 'seo.log', true);
79
+ return;
80
+ }
81
+ //set running lock
82
+ $this->start();
83
+ //clear down log and status tables
84
+ $this->cleanUp();
85
 
 
 
86
  /* @var $website Mage_Core_Model_Website */
87
  foreach(Mage::app()->getWebsites(false) as $websiteId => $website){
88
  $this->setWebsite($website);
89
+ $this->scope = self::SCOPE_WEBSITE;
90
+ $this->scopeId = $websiteId;
91
  $this->checkAndImportEnableds(null, $website->getId());
92
  /* @var $store Mage_Core_Model_Store */
93
  foreach($website->getStores(false) as $storeId => $store){
94
  $this->setStore($store);
95
+ $this->scope = self::SCOPE_STORE;
96
+ $this->scopeId = $storeId;
97
  $this->checkAndImportEnableds($store->getId(), null);
98
 
99
  $this->setStore(null);
 
100
  }
101
  $this->setWebsite(null);
 
102
  }
103
  //do default to finish
104
+ $this->scope = self::SCOPE_DEFAULT;
105
+ $this->scopeId = 0;
106
  $this->checkAndImportEnableds();
107
 
108
+ //delete now unused urls, and
109
+ $this->removeOldImportedUrls();
110
 
111
+ //refresh license count
112
+ $this->updateStatuses();
113
+
114
+ //remove running lock
115
+ $this->end();
116
  }
117
 
118
+ /**
119
+ * @return Mage_Core_Model_Config_Data
120
+ */
121
+ protected function getRunLockConfig()
122
+ {
123
+ /** @var Mage_Core_Model_Config_Data $config */
124
+ $config = Mage::getModel('core/config_data')->load(self::CONFIG_PATH_RUNLOCK, 'path');
125
+ if(!$config->getId()){
126
+ $config->setScope('default')
127
+ ->setScopeId(0)
128
+ ->setPath(self::CONFIG_PATH_RUNLOCK);
129
+ }
130
+ return $config;
131
+ }
 
 
 
 
 
 
 
 
 
 
132
 
133
+ protected function start()
134
+ {
135
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
136
+ $config = $this->getRunLockConfig();
137
+ if($config->getValue() == self::RUNLOCK_RUNNING){
138
+ throw new Exception('Importer Already Running');
139
+ }
140
+ $config->setValue(self::RUNLOCK_RUNNING)->save();
141
+ $this->startTime = Mage::getSingleton('core/date')->timestamp(time());
142
 
143
+ }
 
 
 
 
 
 
144
 
145
+ protected function cleanUp()
146
+ {
147
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
148
+ /** @var Zero1_Seoredirects_Model_Resource_ImportLog_Collection $importLogCollection */
149
+ $importLogCollection = Mage::getModel('zero1_seo_redirects/importLog')->getCollection();
150
+ $importLogCollection->deleteAll();
151
+ /** @var Zero1_Seoredirects_Model_Resource_ImportStatus_Collection $importStatusCollection */
152
+ $importStatusCollection = Mage::getModel('zero1_seo_redirects/importStatus')->getCollection();
153
+ $importStatusCollection->deleteAll();
154
+ }
 
 
 
 
155
 
156
+ protected function log($message, $lineNumber = null, $severity = Zend_Log::INFO, $scope = null, $scopeId = null)
157
+ {
158
+ if($scope === null){
159
+ $scope = $this->scope;
 
 
 
 
 
 
 
 
 
160
  }
161
+ if($scopeId === null){
162
+ $scopeId = $this->scopeId;
163
+ }
164
+ /** @var Zero1_Seoredirects_Model_ImportLog $importLog */
165
+ $importLog = Mage::getModel('zero1_seo_redirects/importLog');
166
+ $importLog->setMessage($message)
167
+ ->setScope($scope)
168
+ ->setScopeId($scopeId)
169
+ ->setSeverity($severity)
170
+ ->setLineNumber($lineNumber)
171
+ ->save();
172
  }
173
 
174
+ protected function checkAndImportEnableds($storeId = null, $websiteId = null)
175
+ {
176
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
177
+ if($this->getHelper()->getIsEnabled($storeId, $websiteId)){
178
+ $this->log('Is Enabled');
179
+ if($this->getHelper()->getIsGoogleDocEnabled($storeId, $websiteId)){
180
+ $this->log('Google Docs Is Enabled');
181
+ if($this->getHelper()->getHasRemoteFile($storeId, $websiteId)){
182
+ $this->getGoogleImporter()->import($storeId, $websiteId);
183
+ }else{
184
+ $this->log('No remote file found');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
186
+ }else{
187
+ $this->log('Google Docs Is Not Enabled');
188
  }
 
 
189
 
190
+ if($this->getHelper()->getIsLocalFileEnabled($storeId, $websiteId)){
191
+ $this->log('Local File Is Enabled');
192
+ if($this->getHelper()->getHasLocalFile($storeId, $websiteId)){
193
+ $this->getLocalImporter()->import($storeId, $websiteId);
194
+ }else{
195
+ $this->log('Not local file found');
 
 
 
 
 
 
 
 
 
 
196
  }
197
  }else{
198
+ $this->log('Local File Is Not Enabled');
199
  }
 
 
 
 
 
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  }else{
202
+ $this->log('Not enabled');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  }
 
204
  }
205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  /**
207
+ * If an 'imported' url wasnt updated in the import, then it has been removed from the sheet and will need to be removed
 
208
  */
209
+ protected function removeOldImportedUrls()
210
+ {
211
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  /* @var $redirectionCollection Zero1_Seoredirects_Model_Resource_Redirection_Collection */
213
  $redirectionCollection = Mage::getModel('zero1_seo_redirects/redirection')->getCollection();
214
+ $date = date('Y-m-d H:i:s', $this->startTime);
215
+
216
+ $redirectionCollection->addFieldToFilter('source', Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_IMPORT_VALUE);
217
+ $redirectionCollection->addFieldToFilter('updated_at', array('lt' => $date));
218
+ $this->log(sprintf('Deleted %d old url(s)', $redirectionCollection->count()), null, Zend_Log::INFO, self::SCOPE_SUMMARY, 0);
219
+
220
+ //Mage::log('deleting: source = "'.Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_IMPORT_VALUE.'" AND updated_at < "'.$date.'"', Zend_Log::DEBUG, 'seo.log', true);
221
+ $redirectionCollection->getConnection()->delete($redirectionCollection->getMainTable(),
222
+ 'source = "'.Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_IMPORT_VALUE.'" AND updated_at < "'.$date.'"');
223
  }
224
 
225
+ /**
226
+ * If the number of enabled redirects is lower than the limit, and there are disabled redirects, enable all up to limit
227
+ * this occurs because a clean down of the urls occurs last.
228
+ */
229
+ protected function updateStatuses()
230
+ {
231
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
232
+ /* @var $redirectionCollection Zero1_Seoredirects_Model_Resource_Redirection_Collection */
233
+ $enabledRedirectionCount = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
234
+ ->addFieldToFilter('status', Zero1_Seoredirects_Model_Redirection::REDIRECTION_STATUS_ENABLED_VALUE)
235
+ ->count();
236
 
237
  /* @var $licenseHelper Zero1_SeoRedirects_Helper_License */
238
  $licenseHelper = Mage::helper('zero1_seo_redirects/license');
239
  $licenseLimit = $licenseHelper->getLicenceLimit();
240
 
241
+ if($enabledRedirectionCount < $licenseLimit || $licenseLimit == 0){
242
+ $redirectionCollection = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
243
  ->addFieldToFilter('source', array('neq' => Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_LOGGED_VALUE))
244
+ ->addFieldToFilter('status', Zero1_Seoredirects_Model_Redirection::REDIRECTION_STATUS_DISABLED_VALUE);
245
 
246
  if($licenseLimit > 0){
247
  $redirectionCollection->setPageSize($licenseLimit - $enabledRedirectionCount);
248
  $redirectionCollection->setCurPage(1);
249
  }
250
+ /* @var $redirect Zero1_Seoredirects_Model_Redirection */
251
+ foreach($redirectionCollection as $redirect){
252
+ $redirect->setStatus(Zero1_Seoredirects_Model_Redirection::REDIRECTION_STATUS_ENABLED_VALUE);
253
+ $redirect->save();
254
+ }
255
+ }
256
+ }
 
 
 
 
 
 
 
 
257
 
258
+ protected function end()
259
+ {
260
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
261
+ $config = $this->getRunLockConfig();
262
+ $config->setValue(self::RUNLOCK_NOT_RUNNING)->save();
263
+ }
264
 
265
+ public static function isRunning()
266
+ {
267
+ $value = Mage::getStoreConfig(self::CONFIG_PATH_RUNLOCK);
268
+ if($value == self::RUNLOCK_RUNNING){
269
+ return true;
270
+ }else{
271
+ return false;
272
+ }
273
+ }
274
 
275
+ public static function getStatus()
276
+ {
277
+ $value = Mage::getStoreConfig(self::CONFIG_PATH_RUNLOCK);
278
+ if(!$value){
279
+ $value = self::RUNLOCK_NOT_RUNNING;
280
+ }
281
+ return $value;
282
+ }
283
  }
app/code/community/Zero1/Seoredirects/Model/Importer/Abstract.php ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Zero1_Seoredirects_Model_Importer_Abstract
4
+ */
5
+ abstract class Zero1_Seoredirects_Model_Importer_Abstract
6
+ {
7
+ protected $websiteId = null;
8
+ protected $storeId = null;
9
+ protected $scope = null;
10
+ protected $scopeId = null;
11
+ const SCOPE_DEFAULT = 'default';
12
+ const SCOPE_STORE = 'store';
13
+ const SCOPE_WEBSITE = 'website';
14
+ protected $status = null;
15
+ protected $lineNumber = 0;
16
+ protected $columns;
17
+ protected $allowedUrls;
18
+ protected $redirector = null;
19
+
20
+ const HEADER_FROM_URL = 'from-url';
21
+ const HEADER_TO_URL = 'to-url';
22
+ const HEADER_TYPE = 'type';
23
+ const HEADER_PERSIST_QUERY = 'persist-query';
24
+ const COLUMN_PARTICIPATION_MANDATORY = 'mandatory';
25
+ const COLUMN_PARTICIPATION_OPTIONAL = 'optional';
26
+
27
+ const STATUS_UPDATE_SET_SIZE = 50;
28
+
29
+ /**
30
+ * @return Zero1_Seoredirects_Helper_Data
31
+ */
32
+ protected function getHelper()
33
+ {
34
+ return Mage::helper('zero1_seo_redirects');
35
+ }
36
+
37
+ /**
38
+ * @return Zero1_Seoredirects_Model_ImportStatus
39
+ */
40
+ protected function getStatus()
41
+ {
42
+ if(!$this->status){
43
+ $this->status = Mage::getModel('zero1_seo_redirects/importStatus');
44
+ }
45
+ return $this->status;
46
+ }
47
+
48
+ final public function import($storeId, $websiteId)
49
+ {
50
+ $this->start($storeId, $websiteId);
51
+ $this->run();
52
+ $this->end();
53
+ }
54
+
55
+ protected function start($storeId, $websiteId)
56
+ {
57
+ if($storeId === null && $websiteId === null){
58
+ $this->scopeId = 0;
59
+ $this->scope = self::SCOPE_DEFAULT;
60
+ }elseif($storeId === null){
61
+ $this->scopeId = $websiteId;
62
+ $this->scope = self::SCOPE_WEBSITE;
63
+ }else{
64
+ $this->scopeId = $storeId;
65
+ $this->scope = self::SCOPE_STORE;
66
+ }
67
+ $this->storeId = $storeId;
68
+ $this->websiteId = $websiteId;
69
+
70
+ $this->getStatus()->setScope($this->scope)
71
+ ->setScopeId($this->scopeId)
72
+ ->save();
73
+ $this->lineNumber = 0;
74
+
75
+ $this->initColumns();
76
+ $this->initAllowedUrls();
77
+ }
78
+
79
+ protected function initColumns()
80
+ {
81
+ $self = $this;
82
+ $this->columns = array(
83
+ self::HEADER_FROM_URL => array(
84
+ 'index' => 0,
85
+ 'participation' => self::COLUMN_PARTICIPATION_MANDATORY,
86
+ 'parse' => function($value) use ($self) {
87
+ return $value;
88
+ }
89
+ ),
90
+ self::HEADER_TO_URL => array(
91
+ 'index' => 1,
92
+ 'participation' => self::COLUMN_PARTICIPATION_MANDATORY,
93
+ 'parse' => function($value) use ($self) {
94
+ return $value;
95
+ }
96
+ ),
97
+ self::HEADER_TYPE => array(
98
+ 'index' => 2,
99
+ 'participation' => self::COLUMN_PARTICIPATION_OPTIONAL,
100
+ 'parse' => function($value) use ($self) {
101
+ switch($value){
102
+ case Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_LABEL:
103
+ $t = Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_VALUE;
104
+ break;
105
+ case Zero1_Seoredirects_Model_Redirection::FROM_TYPE_OPEN_ENDED_QUERY_LABEL:
106
+ $t = Zero1_Seoredirects_Model_Redirection::FROM_TYPE_OPEN_ENDED_QUERY_VALUE;
107
+ break;
108
+ default:
109
+ $t = Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_VALUE;
110
+ $self->log('No type found defaulting to fixed, options are: '.Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_LABEL.', '.Zero1_Seoredirects_Model_Redirection::FROM_TYPE_OPEN_ENDED_QUERY_LABEL, $self->getLineNumber(), Zend_Log::INFO);
111
+ }
112
+ return $t;
113
+ }
114
+ ),
115
+ self::HEADER_PERSIST_QUERY => array(
116
+ 'index' => 3,
117
+ 'participation' => self::COLUMN_PARTICIPATION_OPTIONAL,
118
+ 'parse' => function($value) use ($self) {
119
+ switch($value){
120
+ case 'No':
121
+ $t = 0;
122
+ break;
123
+ case 'Yes':
124
+ $t = 1;
125
+ break;
126
+ default:
127
+ $t = 0;
128
+ $self->log('No matching value found for persist query, options are: \'Yes\' or \'No\'. Defaulting to No', $self->getLineNumber(), Zend_Log::INFO);
129
+ }
130
+ return $t;
131
+ }
132
+ ),
133
+ );
134
+ }
135
+
136
+ protected function initAllowedUrls()
137
+ {
138
+ $this->allowedUrls = array();
139
+ /** @var $store Mage_Core_Model_Store */
140
+ /** @var $website Mage_Core_Model_Website */
141
+ switch($this->scope){
142
+ case self::SCOPE_STORE:
143
+ $store = Mage::app()->getStore($this->scopeId);
144
+ $this->allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false)] = $store->getId();
145
+ $this->allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true)] = $store->getId();
146
+ break;
147
+ case self::SCOPE_WEBSITE:
148
+ $website = Mage::app()->getWebsite($this->scopeId);
149
+ foreach($website->getStores(false) as $storeId => $store){
150
+ $this->allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false)] = $storeId;
151
+ $this->allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true)] = $storeId;
152
+ }
153
+ break;
154
+ case self::SCOPE_DEFAULT:
155
+ foreach(Mage::app()->getWebsites(false) as $websiteId => $website){
156
+ foreach($website->getStores(false) as $storeId => $store){
157
+ $this->allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false)] = $storeId;
158
+ $this->allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true)] = $storeId;
159
+ }
160
+ }
161
+ break;
162
+ }
163
+ }
164
+
165
+ abstract function run();
166
+
167
+ protected function end()
168
+ {
169
+ $this->getStatus()->setDataChanges(true);
170
+ $this->getStatus()->save();
171
+ }
172
+
173
+ public function log($message, $lineNumber = null, $severity = Zend_Log::INFO, $scope = null, $scopeId = null)
174
+ {
175
+ if($scope === null){
176
+ $scope = $this->scope;
177
+ }
178
+ if($scopeId === null){
179
+ $scopeId = $this->scopeId;
180
+ }
181
+
182
+ /** @var Zero1_Seoredirects_Model_ImportLog $importLog */
183
+ $importLog = Mage::getModel('zero1_seo_redirects/importLog');
184
+ $importLog->setMessage($message)
185
+ ->setScope($scope)
186
+ ->setScopeId($scopeId)
187
+ ->setSeverity($severity)
188
+ ->setLineNumber($lineNumber)
189
+ ->save();
190
+ }
191
+
192
+ protected function hasHeaders($data)
193
+ {
194
+ $from = array_search(self::HEADER_FROM_URL, $data);
195
+ $to = array_search(self::HEADER_TO_URL, $data);
196
+ if($from === false || $to === false){
197
+ $this->log(sprintf('No headers found, for headers to be found, you should at least specify \'%s\' and \'%s\' columns. You may also specify \'%s\' and \'$s\'',
198
+ self::HEADER_FROM_URL, self::HEADER_FROM_URL, self::HEADER_PERSIST_QUERY, self::HEADER_TYPE),
199
+ $this->lineNumber, Zend_Log::WARN);
200
+ return false;
201
+ }
202
+ return true;
203
+ }
204
+
205
+ protected function importHeaders($data)
206
+ {
207
+ $from = array_search(self::HEADER_FROM_URL, $data);
208
+ $to = array_search(self::HEADER_TO_URL, $data);
209
+ $type = array_search(self::HEADER_TYPE, $data);
210
+ $persistQuery = array_search(self::HEADER_PERSIST_QUERY, $data);
211
+
212
+ if($from !== false){
213
+ $this->columns[self::HEADER_FROM_URL]['index'] = $from;
214
+ }
215
+ if($to !== false){
216
+ $this->columns[self::HEADER_TO_URL]['index'] = $to;
217
+ }
218
+ if($type !== false){
219
+ $this->columns[self::HEADER_TYPE]['index'] = $type;
220
+ }
221
+ if($persistQuery !== false){
222
+ $this->columns[self::HEADER_PERSIST_QUERY]['index'] = $persistQuery;
223
+ }
224
+ $this->log('Headers found ('.json_encode(array_keys($this->columns)).')', $this->lineNumber, Zend_Log::INFO);
225
+ return true;
226
+ }
227
+
228
+ protected function updateStatus($force = false)
229
+ {
230
+ if(($this->lineNumber % self::STATUS_UPDATE_SET_SIZE) == 0 || $force){
231
+ $this->getStatus()->setImported($this->lineNumber)->save();
232
+ }
233
+ }
234
+
235
+ protected function importRow($data)
236
+ {
237
+ $this->log(sprintf('Importing row: %s', json_encode($data)), $this->lineNumber, Zend_Log::DEBUG);
238
+ $from = $this->getCell(self::HEADER_FROM_URL, $data);
239
+ $to = $this->getCell(self::HEADER_TO_URL, $data);
240
+
241
+ if($from === false || $to === false){
242
+ return;
243
+ }
244
+
245
+ $type = $this->getCell(self::HEADER_TYPE, $data);
246
+ $persistQuery = $this->getCell(self::HEADER_PERSIST_QUERY, $data);
247
+
248
+ /** @var Zero1_Seoredirects_Model_UrlFactory $urlFactory */
249
+ $urlFactory = Mage::getModel('zero1_seo_redirects/urlFactory');
250
+ $urlFactory->setAllowedUrls($this->allowedUrls);
251
+
252
+ /** @var Zero1_Seoredirects_Model_Url $fromUrl */
253
+ $fromUrl = $urlFactory->buildUrl($from);
254
+ if(!$fromUrl->getStoreId()){
255
+ $this->log('Skipped Url: "'.$from.'" as couldn\'t find matching store', $this->lineNumber, Zend_Log::WARN);
256
+ return;
257
+ }
258
+ $urlFactory->lockToUrl($fromUrl);
259
+ /** @var Zero1_Seoredirects_Model_Url $toUrl */
260
+ $toUrl = $urlFactory->buildUrl($to);
261
+ if(!$toUrl->getStoreId()){
262
+ $this->log('Skipped Url: "'.$to.'" as couldn\'t find matching store', $this->lineNumber, Zend_Log::WARN);
263
+ return;
264
+ }
265
+ $urlFactory->unlockToUrl();
266
+
267
+ //has this redirect previously been imported?
268
+ $this->log(sprintf('Looking for redirect, store: %d, url: %s',$fromUrl->getStoreId(), $fromUrl->getUrl()));
269
+ list($redirectId, $resultToUrl) = $this->getRedirector()->getRedirectId($fromUrl->getStoreId(), $fromUrl->getUrl(), true);
270
+ //Mage::log(sprintf('Id found: %s', $redirectId), Zend_Log::DEBUG, 'seo.log', true);
271
+ $this->log(sprintf('Id found: %s', $redirectId));
272
+
273
+ /** @var Zero1_Seoredirects_Model_Redirection $redirection */
274
+ $redirection = Mage::getModel('zero1_seo_redirects/redirection');
275
+ if($redirectId){
276
+ $this->log(sprintf('loaded: %d', $redirectId));
277
+ $redirection->load($redirectId);
278
+ }
279
+
280
+ $redirection->setStoreId($fromUrl->getStoreId())
281
+ ->setFromUrlInstance($fromUrl)
282
+ ->setToUrlInstance($toUrl)
283
+ ->setFromType($type)
284
+ ->setPersistQuery($persistQuery)
285
+ ->setSource(Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_IMPORT_VALUE);
286
+
287
+ $this->log(sprintf('saving: %s', json_encode($redirection->getData())));
288
+ try{
289
+ //Mage::log('saving, model has changes?'.json_encode($redirection->hasDataChanges()), Zend_Log::DEBUG, 'seo.log', true);
290
+ $redirection->save();
291
+ }
292
+ catch(Zero1_Seoredirects_Exception $e){
293
+ $messages = $e->getMessages();
294
+ foreach($messages as $err){
295
+ $this->log($err.' Redirect was not imported.', $this->lineNumber, Zend_Log::WARN);
296
+ }
297
+ }
298
+ catch(Exception $e){
299
+ //TODO maybe just throw this?
300
+ $this->log($e->getMessage(), $this->lineNumber, Zend_Log::CRIT);
301
+ }
302
+ }
303
+
304
+ protected function getCell($cell, $data)
305
+ {
306
+ $index = $this->columns[$cell]['index'];
307
+ $participation = $this->columns[$cell]['participation'];
308
+ $parse = $this->columns[$cell]['parse'];
309
+
310
+ $dataValue = (isset($data[$index])? $data[$index] : '');
311
+ $result = $parse($dataValue);
312
+
313
+ if($result == ''){
314
+ if($participation == self::COLUMN_PARTICIPATION_MANDATORY){
315
+ $this->log('Could not find column "'.$cell.'", skipping this row', $this->lineNumber, Zend_Log::WARN);
316
+ }else{
317
+ $this->log('Could not find column "'.$cell.'"', $this->lineNumber, Zend_Log::NOTICE);
318
+ }
319
+ return false;
320
+ }
321
+ return $result;
322
+ }
323
+
324
+ /**
325
+ * @return Zero1_Seoredirects_Model_Redirecter
326
+ */
327
+ protected function getRedirector()
328
+ {
329
+ if(!$this->redirector){
330
+ $this->redirector = Mage::getModel('zero1_seo_redirects/redirecter');
331
+ }
332
+ return $this->redirector;
333
+ }
334
+
335
+ public function getLineNumber()
336
+ {
337
+ return $this->lineNumber;
338
+ }
339
+ }
app/code/community/Zero1/Seoredirects/Model/Importer/Google.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Zero1_Seoredirects_Model_Importer_Google
4
+ */
5
+ class Zero1_Seoredirects_Model_Importer_Google extends Zero1_Seoredirects_Model_Importer_Abstract
6
+ {
7
+ protected $_zendHttpClient;
8
+
9
+ public function run()
10
+ {
11
+ $url = $this->getHelper()->getRemoteFileUrl($this->storeId, $this->websiteId);
12
+ $this->log(sprintf('Importing Google Doc From: %s', $url));
13
+ preg_match('/output=csv/', $url, $results, PREG_OFFSET_CAPTURE);
14
+ if(!empty($results)){
15
+ $this->runCsv($url);
16
+ }else{
17
+ preg_match('/pubhtml/', $url, $results, PREG_OFFSET_CAPTURE);
18
+ if(!empty($results)){
19
+ $this->runHtml($url);
20
+ }else{
21
+ $this->log('File type could not be verified, aborting.', null, Zend_Log::WARN);
22
+ }
23
+ }
24
+ }
25
+
26
+ /**
27
+ * @return Zend_Http_Client
28
+ */
29
+ protected function getZendClient()
30
+ {
31
+ if (!$this->_zendHttpClient instanceof Zend_Http_Client) {
32
+ $this->_zendHttpClient = new Zend_Http_Client();
33
+ }
34
+ return $this->_zendHttpClient;
35
+ }
36
+
37
+ protected function runHtml($url)
38
+ {
39
+ $this->log('Importing remote html: "'.$url.'"');
40
+ $content = '';
41
+ try {
42
+ $this->getZendClient()->setUri($url);
43
+ $content = $this->getZendClient()->request()->getBody();
44
+ } catch(Exception $e) {
45
+ $this->log('Failed to retrieve content from remote document "'.$url.'" Error: '.$e->getMessage(), null, Zend_Log::WARN);
46
+ return;
47
+ }
48
+ if(preg_match('~<!DOCTYPE html>~', $content) != 1){
49
+ $this->log('Content from remote url, does not appear to html "'.$url.'"', null, Zend_Log::WARN);
50
+ }
51
+
52
+ $this->lineNumber = 0;
53
+ $totalLines = 0;
54
+ $doc = new DOMDocument();
55
+ try {
56
+ @$doc->loadHTML($content);
57
+ }catch(Exception $e){
58
+ //file_put_contents('temp.html', $content);
59
+ throw $e;
60
+ }
61
+
62
+ /* @var $tables DOMNodeList */
63
+ $tables = $doc->getElementsByTagName('table');
64
+ $table = $tables->item(0);
65
+
66
+ /* @var $child DOMElement */
67
+ foreach($table->childNodes as $child){
68
+ if($child->nodeName !== 'tbody'){
69
+ continue;
70
+ }else{
71
+ /* @var $row DOMElement */
72
+ /* @var $cell DOMElement */
73
+ foreach($child->childNodes as $row){
74
+ $data = array();
75
+ foreach($row->childNodes as $cell){
76
+ if($cell->nodeName === 'td'){
77
+ $data[] = $cell->textContent;
78
+ }
79
+ }
80
+ $totalLines++;
81
+ }
82
+ break;
83
+ }
84
+ }
85
+
86
+ $this->getStatus()->setToBeImported($totalLines)->save();
87
+
88
+ /* @var $child DOMElement */
89
+ foreach($table->childNodes as $child){
90
+ if($child->nodeName !== 'tbody'){
91
+ continue;
92
+ }else{
93
+ /* @var $row DOMElement */
94
+ /* @var $cell DOMElement */
95
+ foreach($child->childNodes as $row){
96
+ $data = array();
97
+ foreach($row->childNodes as $cell){
98
+ if($cell->nodeName === 'td'){
99
+ $data[] = $cell->textContent;
100
+ }
101
+ }
102
+ if($this->lineNumber == 0){
103
+ $this->importHeaders($data);
104
+ if(!$this->hasHeaders($data)){
105
+ $this->importRow($data);
106
+ }
107
+ }else{
108
+ $this->importRow($data);
109
+ }
110
+
111
+ $this->lineNumber++;
112
+ $this->updateStatus();
113
+ }
114
+ break;
115
+ }
116
+ }
117
+ $this->updateStatus(true);
118
+ }
119
+
120
+ protected function runCsv($url)
121
+ {
122
+ $this->log('Importing remote csv: "'.$url.'"');
123
+ try {
124
+ $this->getZendClient()->setUri($url);
125
+ $content = $this->getZendClient()->request()->getBody();
126
+ } catch(Exception $e) {
127
+ $this->log('Failed to retrieve content from remote document "'.$url.'" Error: '.$e->getMessage(), null, Zend_Log::WARN);
128
+ return;
129
+ }
130
+
131
+ $file = explode(PHP_EOL, $content);
132
+ $totalLines = 0;
133
+ foreach ($file as $line) {
134
+ $totalLines++;
135
+ }
136
+ $this->getStatus()->setToBeImported($totalLines)->save();
137
+ reset($file);
138
+
139
+ $this->lineNumber = 0;
140
+ foreach ($file as $line) {
141
+ $line = str_getcsv($line);
142
+ if($this->lineNumber == 0){
143
+ $this->importHeaders($line);
144
+ if(!$this->hasHeaders($line)){
145
+ $this->importRow($line);
146
+ }
147
+ }else{
148
+ $this->importRow($line);
149
+ }
150
+ $this->updateStatus();
151
+ $this->lineNumber++;
152
+ }
153
+ $this->updateStatus(true);
154
+ }
155
+ }
app/code/community/Zero1/Seoredirects/Model/Importer/Local.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Zero1_Seoredirects_Model_Importer_Local
4
+ */
5
+ class Zero1_Seoredirects_Model_Importer_Local extends Zero1_Seoredirects_Model_Importer_Abstract
6
+ {
7
+ public function run()
8
+ {
9
+ /** @var Zero1_Seoredirects_Model_File $file */
10
+ $file = $this->getFileHelper()->getFile($this->storeId, $this->websiteId);
11
+ $fileHandle = fopen($file->getInternalPath(), 'r');
12
+ $this->log(sprintf('Importing: %s', $file->getInternalPath()));
13
+
14
+ $totalLines = 0;
15
+ while(!feof($fileHandle)){
16
+ $line = fgets($fileHandle);
17
+ $totalLines++;
18
+ }
19
+ $this->getStatus()->setToBeImported($totalLines)->save();
20
+ rewind($fileHandle);
21
+
22
+ while(!feof($fileHandle)){
23
+ $line = fgetcsv($fileHandle);
24
+ if($this->lineNumber == 0){
25
+ $this->importHeaders($line);
26
+ if(!$this->hasHeaders($line)){
27
+ $this->importRow($line);
28
+ }
29
+ }else{
30
+ $this->importRow($line);
31
+ }
32
+ $this->lineNumber++;
33
+ $this->updateStatus();
34
+ }
35
+ fclose($fileHandle);
36
+ $this->updateStatus(true);
37
+ }
38
+
39
+ /**
40
+ * @return Zero1_Seoredirects_Helper_Files
41
+ */
42
+ protected function getFileHelper()
43
+ {
44
+ return Mage::helper('zero1_seo_redirects/files');
45
+ }
46
+ }
app/code/community/Zero1/Seoredirects/Model/Observer.php CHANGED
@@ -7,18 +7,26 @@ class Zero1_Seoredirects_Model_Observer
7
  protected function checkForRedirection($observer)
8
  {
9
  // There is a valid route, nothing to do
10
- if(Mage::app()->getRequest()->getActionName() != 'noRoute'){ return; }
 
 
 
 
 
 
 
 
 
11
 
12
- /* @var $redirector Zero1_Seoredirects_Model_Redirector */
13
- $redirector = Mage::getModel('zero1_seo_redirects/redirector');
14
 
15
- $result = $redirector->redirect(
16
  Mage::app()->getStore()->getId(),
17
  Mage::helper('core/url')->getCurrentUrl()
18
  );
19
 
20
- if(Mage::helper('zero1_seo_redirects')->canDebug()){
21
- Mage::helper('zero1_seo_redirects')->debug('Result: '.json_encode($result));
22
  }
23
  }
24
 
@@ -27,6 +35,7 @@ class Zero1_Seoredirects_Model_Observer
27
  */
28
  public function controller_front_send_response_before(Varien_Event_Observer $observer)
29
  {
 
30
  $this->checkForRedirection($observer);
31
  }
32
 
@@ -35,10 +44,7 @@ class Zero1_Seoredirects_Model_Observer
35
  */
36
  public function controller_front_send_response_after(Varien_Event_Observer $observer)
37
  {
 
38
  $this->checkForRedirection($observer);
39
  }
40
-
41
- public function cronImport(){
42
-
43
- }
44
  }
7
  protected function checkForRedirection($observer)
8
  {
9
  // There is a valid route, nothing to do
10
+ if(Mage::app()->getRequest()->getActionName() != 'noRoute'){
11
+ return;
12
+ }
13
+
14
+ //Mage::log('registry: '.Mage::registry('zero1_seo_redirects'), Zend_Log::DEBUG, 'seo.log', true);
15
+ if(Mage::registry('zero1_seo_redirects')){
16
+ return;
17
+ }
18
+ /* @var $redirector Zero1_Seoredirects_Model_Redirecter */
19
+ $redirector = Mage::getModel('zero1_seo_redirects/redirecter');
20
 
21
+ //Mage::log('core/url: '.Mage::helper('core/url')->getCurrentUrl(), Zend_Log::DEBUG, 'seo.log', true);
 
22
 
23
+ $redirection = $redirector->redirect(
24
  Mage::app()->getStore()->getId(),
25
  Mage::helper('core/url')->getCurrentUrl()
26
  );
27
 
28
+ if($redirection){
29
+ Mage::register('zero1_seo_redirects', $redirection->getId());
30
  }
31
  }
32
 
35
  */
36
  public function controller_front_send_response_before(Varien_Event_Observer $observer)
37
  {
38
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
39
  $this->checkForRedirection($observer);
40
  }
41
 
44
  */
45
  public function controller_front_send_response_after(Varien_Event_Observer $observer)
46
  {
47
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
48
  $this->checkForRedirection($observer);
49
  }
 
 
 
 
50
  }
app/code/community/Zero1/Seoredirects/Model/Redirecter.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Model_Redirecter{
3
+
4
+ private $originalUrl;
5
+ private $orignalUrlObject;
6
+ private $storeId;
7
+ private $found;
8
+ private $shouldCache;
9
+
10
+ /**
11
+ * @param $storeId
12
+ * @param $url
13
+ * @return Zero1_Seoredirects_Model_Redirection|null
14
+ */
15
+ public function redirect($storeId, $url)
16
+ {
17
+ list($redirectId, $url) = $this->getRedirectId($storeId, $url);
18
+ if($this->found){
19
+ $this->incrementHits($redirectId);
20
+ if($this->shouldCache){
21
+ $this->cache($redirectId, $url);
22
+ }
23
+ $redirection = Mage::getModel('zero1_seo_redirects/redirection')->load($redirectId);
24
+ //Mage::log('redirection: '.json_encode($redirection), Zend_Log::DEBUG, 'seo.log', true);
25
+ if($redirection->isEnabled()){
26
+ $this->redirectTo($url);
27
+ }
28
+ return $redirection;
29
+ }else{
30
+ if($this->getHelper()->shouldLog404()){
31
+ $this->log404();
32
+ }
33
+ }
34
+ }
35
+
36
+ /**
37
+ * @param $storeId
38
+ * @param $url
39
+ * @return string | null
40
+ */
41
+ public function getRedirectId($storeId, $url)
42
+ {
43
+ /** @var Zero1_Seoredirects_Model_UrlFactory $urlFactory */
44
+ $urlFactory = Mage::getModel('zero1_seo_redirects/urlFactory');
45
+ $urlFactory->setAllowedStores(array($storeId));
46
+
47
+ $this->originalUrl = $url;
48
+ $this->orignalUrlObject = $urlFactory->buildUrl($url);
49
+ $this->storeId = $storeId;
50
+
51
+ $this->found = false;
52
+ $this->shouldCache = false;
53
+
54
+ list($redirectionId, $url) = $this->checkCache();
55
+ if($this->found){
56
+ return array($redirectionId, $url);
57
+ }
58
+
59
+ $this->shouldCache = true;
60
+
61
+ list($redirectionId, $url) = $this->checkForFixedRedirect();
62
+ if($this->found){
63
+ return array($redirectionId, $url);
64
+ }
65
+
66
+ list($redirectionId, $url) = $this->checkForOpenEndedRedirect();
67
+ if($this->found){
68
+ return array($redirectionId, $url);
69
+ }
70
+
71
+ return array(false, '');
72
+ }
73
+
74
+ public function checkCache()
75
+ {
76
+ /** @var Zero1_Seoredirects_Model_Redirection_Cache $cachedUrl */
77
+ //have used the private property, as this will have the query string untouched
78
+ $cachedUrl = Mage::getModel('zero1_seo_redirects/redirection_cache')->load($this->originalUrl, 'from_url');
79
+ if($cachedUrl->getId()){
80
+ $this->found = true;
81
+ return array($cachedUrl->getRedirectionId(), $cachedUrl->getToUrl());
82
+ }
83
+ return array(false, '');
84
+ }
85
+
86
+ public function checkForFixedRedirect()
87
+ {
88
+ /* @var $redirection Zero1_Seoredirects_Model_Redirection */
89
+ $redirection = Mage::getModel('zero1_seo_redirects/redirection');
90
+ $redirection->loadFixed($this->storeId, $this->getOriginalUrl()->getPath(), $this->getOriginalUrl()->getQuery());
91
+
92
+ if($redirection->getId()){
93
+ $this->found = true;
94
+ $redirection->getToUrlInstance()->setScheme($this->getOriginalUrl()->getScheme());
95
+ return array($redirection->getId(), $redirection->getToUrlInstance()->getUrl());
96
+ }
97
+ return array(false, '');
98
+ }
99
+
100
+ public function checkForOpenEndedRedirect()
101
+ {
102
+ /* @var $redirectionCollection Zero1_Seoredirects_Model_Resource_Redirection_Collection */
103
+ $redirectionCollection = Mage::getModel('zero1_seo_redirects/redirection')->getCollection();
104
+ $redirectionCollection->addOpenEnded()
105
+ ->addFieldToFilter('store_id', 1)
106
+ ->addFieldToFilter('from_url_path', $this->getOriginalUrl()->getPath());
107
+
108
+ if(!$this->getOriginalUrl()->hasQuery()){
109
+ $redirectionCollection->addFieldToFilter('from_url_query', null);
110
+ }
111
+
112
+ if($redirectionCollection->count() == 0){
113
+ return array(false, '');
114
+ }
115
+
116
+ /** @var $redirection Zero1_Seoredirects_Model_Redirection */
117
+ $redirection = null;
118
+
119
+ if(!$this->getOriginalUrl()->hasQuery()){
120
+ $this->found = true;
121
+ $redirection = $redirectionCollection->getFirstItem();
122
+ return array($redirection->getId(), $redirection->getToUrlInstance()->getUrl());
123
+ }
124
+
125
+ $originalRequestAssocQuery = $this->getOriginalUrl()->getAssocQuery();
126
+ $numberOfParams = count($originalRequestAssocQuery);
127
+
128
+ $highestMatchedCount = 0;
129
+ /** @var $matchedRedirect Zero1_Seoredirects_Model_Redirection */
130
+ $matchedRedirect = null;
131
+
132
+ foreach($redirectionCollection as $redirection){
133
+ $redirectionAssocQuery = $redirection->getFromUrlInstance()->getAssocQuery();
134
+ $matchedQueryParams = count(array_intersect_assoc($originalRequestAssocQuery, $redirectionAssocQuery));
135
+
136
+ if($matchedQueryParams > $highestMatchedCount){
137
+ $highestMatchedCount = $matchedQueryParams;
138
+ $matchedRedirect = $redirection;
139
+ if($matchedQueryParams == $numberOfParams){
140
+ break;
141
+ }
142
+ }
143
+ }
144
+
145
+ if($highestMatchedCount === 0){
146
+ return array(false, '');
147
+ }
148
+ $this->found = true;
149
+
150
+ if($matchedRedirect->shouldPersistQuery()){
151
+ $matchedRedirect->getToUrlInstance()->mergeQuery($originalRequestAssocQuery);
152
+ }
153
+ return array($matchedRedirect->getId(), $matchedRedirect->getToUrlInstance(true)->getUrl());
154
+ }
155
+
156
+ /**
157
+ * @return Zero1_Seoredirects_Model_Url
158
+ */
159
+ protected function getOriginalUrl()
160
+ {
161
+ return $this->orignalUrlObject;
162
+ }
163
+
164
+ protected function incrementHits($redirectionId)
165
+ {
166
+ //Mage::log(__METHOD__.'::START', Zend_Log::DEBUG, 'seo.log', true);
167
+ /* @var $r Zero1_Seoredirects_Model_Redirection */
168
+ $r = Mage::getModel('zero1_seo_redirects/redirection')->load($redirectionId);
169
+ //Mage::log('$r: '.json_encode($r->getData()), Zend_Log::DEBUG, 'seo.log', true);
170
+ if($r->getId()){
171
+ $r->incrementHits();
172
+ //Mage::log('$r: '.json_encode($r->getData()), Zend_Log::DEBUG, 'seo.log', true);
173
+ $r->save();
174
+ }
175
+ //Mage::log(__METHOD__.'::END', Zend_Log::DEBUG, 'seo.log', true);
176
+ }
177
+
178
+ protected function cache($redirectionId, $toUrl)
179
+ {
180
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'seo.log', true);
181
+ /* @var $cached Zero1_Seoredirects_Model_Redirection_Cache */
182
+ $cached = Mage::getModel('zero1_seo_redirects/redirection_cache');
183
+ $cached->setRedirectionId($redirectionId)
184
+ ->setFromUrl($this->originalUrl)
185
+ ->setToUrl($toUrl)
186
+ ->save();
187
+ //Mage::log(__METHOD__.'::END', Zend_Log::DEBUG, 'seo.log', true);
188
+ }
189
+
190
+ /**
191
+ * @return Zero1_Seoredirects_Helper_Data
192
+ */
193
+ protected function getHelper()
194
+ {
195
+ return Mage::helper('zero1_seo_redirects');
196
+ }
197
+
198
+ protected function log404()
199
+ {
200
+ /* @var $redirection Zero1_Seoredirects_Model_Redirection */
201
+ $redirection = Mage::getModel('zero1_seo_redirects/redirection');
202
+ $redirection->setFromUrlInstance($this->getOriginalUrl())
203
+ ->setSource(Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_LOGGED_VALUE)
204
+ ->setStatus(0)
205
+ ->setFromType(Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_VALUE)
206
+ ->setHits(1)
207
+ ->save();
208
+ }
209
+
210
+ protected function redirectTo($url)
211
+ {
212
+ header('HTTP/1.1 301 Moved Permanently');
213
+ header('Location: '.$url);
214
+ die();
215
+ }
216
+ }
app/code/community/Zero1/Seoredirects/Model/Redirection.php CHANGED
@@ -7,6 +7,7 @@
7
  * @method string getToUrl()
8
  * @method Zero1_Seoredirects_Model_Redirection setToUrl(string $toUrl)
9
  * @method Zero1_Seoredirects_Model_Redirection setStoreId(int $storeId)
 
10
  * @method Zero1_Seoredirects_Model_Redirection setSource(int $source)
11
  * @method int getSource()
12
  * @method Zero1_Seoredirects_Model_Redirection setStatus(int $status)
@@ -37,12 +38,31 @@ class Zero1_Seoredirects_Model_Redirection extends Mage_Core_Model_Abstract
37
  const REDIRECTION_STATUS_ENABLED_VALUE = 1;
38
  const REDIRECTION_STATUS_ENABLED_LABEL = 'Enabled';
39
 
40
- protected function _construct()
41
- {
42
- $this->_init('zero1_seo_redirects/redirection');
43
- }
44
 
45
- protected function _afterLoad(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  $this->setFromUrl($this->getFromUrlPath().(($this->getFromUrlQuery() != '')? '?'.$this->getFromUrlQuery() : ''));
47
  }
48
 
@@ -62,11 +82,17 @@ class Zero1_Seoredirects_Model_Redirection extends Mage_Core_Model_Abstract
62
  }
63
  }
64
 
65
- public function save(){
 
66
  if (!$this->_hasModelChanged()) {
67
  return parent::save();
68
  }
69
- $validation = $this->validate();
 
 
 
 
 
70
  if(!$validation['result']){
71
  /* @var $ex Zero1_Seoredirects_Exception */
72
  $ex = Mage::exception('Zero1_Seoredirects', implode('<br />', $validation['errors']));
@@ -75,6 +101,13 @@ class Zero1_Seoredirects_Model_Redirection extends Mage_Core_Model_Abstract
75
  }
76
  //if its not new and anything other than just hits has changed clear cache for this redirect
77
  $diff = array_diff_assoc((($this->getOrigData() == null)? array() : $this->getOrigData()), $this->getData());
 
 
 
 
 
 
 
78
  if(count($diff) > 1 || !isset($diff['hits'])){
79
  /* @var $cacheCollection Zero1_Seoredirects_Model_Resource_Redirection_Cache_Collection */
80
  $cacheCollection = Mage::getModel('zero1_seo_redirects/redirection_cache')->getCollection();
@@ -97,151 +130,33 @@ class Zero1_Seoredirects_Model_Redirection extends Mage_Core_Model_Abstract
97
  return parent::save();
98
  }
99
 
100
- public function validate(){
101
- $v = array(
102
- 'result' => true,
103
- 'errors' => array(),
104
- );
105
- //check urls and order the query strings
106
- $v = $this->_validateURLs($v);
107
- //check if from url exists
108
- $v = $this->_checkFrom($v);
109
- //check if to url exists
110
- $v = $this->_checkTo($v);
111
- //check to and from
112
- $v = $this->_checkToAndFrom($v);
113
- $v = $this->_checkPersistQuery($v);
114
-
115
- //TODO check license
116
- $v = $this->_checkStatus($v);
117
-
118
- return $v;
119
- }
120
-
121
- protected function _validateURLs($v){
122
- //do from url
123
- $url = preg_replace('/\/$/','',$this->getStoreUrl())
124
- .'/'.preg_replace('/^\//','',$this->getFromUrlPath());
125
-
126
- list($url, $v) = $this->_parseAndValidateUrl($url, $v);
127
-
128
- if($v['result']){
129
- $this->setFromUrlPath($url['path']);
130
- if(isset($url['query'])){
131
- $this->setFromUrlQuery($url['query']);
132
- }else{
133
- $this->setFromUrlQuery(null);
134
- }
135
- }
136
-
137
- //do to url
138
- //default logged urls to homepage
139
- $url = preg_replace('/\/$/','',$this->getStoreUrl()).'/';
140
- if($this->getSource() != self::SOURCE_TYPE_LOGGED_VALUE){
141
- $url .= preg_replace('/^\//','',$this->getToUrl());
142
- }
143
-
144
- list($url, $v) = $this->_parseAndValidateUrl($url, $v);
145
- if($v['result']){
146
- $this->setToUrl($url['path'].(isset($url['query'])? '?'.$url['query'] : ''));
147
- }
148
-
149
- return $v;
150
- }
151
- protected function _parseAndValidateUrl($url, $result){
152
- if(!filter_var($url, FILTER_VALIDATE_URL)){
153
- $result['result'] = false;
154
- $result['errors'][] = $this->getHelper()->__('Failed to validate url. '.$url);
155
- }
156
- if(!$u = parse_url($url)){
157
- $result['result'] = false;
158
- $result['errors'][] = $this->getHelper()->__('Failed to parse url.'.$url);
159
- }elseif(isset($u['query']) && substr_count($u['query'], '=') == 0){
160
- $result['result'] = false;
161
- $result['errors'][] = $this->getHelper()->__('Failed to validate url, could not find \'=\' in query string. '.$url);
162
- }else{
163
- $url = $this->_getUrlHelper()->parseUrl($url, $this->getStoreId());
164
- }
165
- return array($url, $result);
166
- }
167
-
168
- protected function _checkFrom($v){
169
- /* @var $redirector Zero1_Seoredirects_Model_Redirector */
170
- $redirector = Mage::getModel('zero1_seo_redirects/redirector');
171
- $result = $redirector->redirect(
172
- $this->getStoreId(),
173
- $this->getFromUrl(),
174
- true
175
- );
176
-
177
- if($result && $result != $this->getId()){
178
- $v['result'] = false;
179
- $v['errors'][] = $this->getHelper()->__('A redirect for this location already exists ('.$result.').');
180
- }
181
-
182
- return $v;
183
- }
184
-
185
- protected function _checkTo($v){
186
- /* @var $redirector Zero1_Seoredirects_Model_Redirector */
187
- $redirector = Mage::getModel('zero1_seo_redirects/redirector');
188
- $result = $redirector->redirect(
189
- $this->getStoreId(),
190
- $this->getToUrl(),
191
- true
192
- );
193
-
194
- if($result){
195
- $v['result'] = false;
196
- $v['errors'][] = $this->getHelper()->__('A redirect for the location you are redirecting to already exists ('.$result.').');
197
- }
198
-
199
- return $v;
200
- }
201
-
202
- protected function _checkToAndFrom($v){
203
- if($this->getToUrl() == $this->getFromUrlPath().((!$this->getFromUrlQuery())? '' : '?'.$this->getFromUrlQuery())){
204
- $v['result'] = false;
205
- $v['errors'][] = $this->getHelper()->__('A redirect cannot have a to and from that are the same');
206
- }
207
- return $v;
208
- }
209
-
210
- protected function _checkPersistQuery($v){
211
- if($this->getFromType() != self::FROM_TYPE_OPEN_ENDED_QUERY_VALUE){
212
- $this->setPersistQuery(false);
213
- }
214
- return $v;
215
- }
216
-
217
- protected function _checkStatus($v){
218
-
219
  if($this->getSource() == self::SOURCE_TYPE_LOGGED_VALUE){
220
  $this->setStatus(self::REDIRECTION_STATUS_DISABLED_VALUE);
221
- return $v;
222
  }
223
 
224
  //TODO figure out a better way to do this
225
  $cCount = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
226
  ->addFieldToFilter('status', self::REDIRECTION_STATUS_ENABLED_VALUE);
227
- if($this->getRedirectionId()){
228
- $cCount->addFieldToFilter('redirection_id', array('neq' => $this->getRedirectionId()));
229
- }
230
- $cCount = $cCount->count();
231
 
232
- $lCount = $this->_getLicenseHelper()->getLicenceLimit();
233
 
234
  if($cCount < $lCount || $lCount == 0){
235
- $this->setStatus(self::REDIRECTION_STATUS_ENABLED_VALUE);
236
  }else{
237
- $this->setStatus(self::REDIRECTION_STATUS_DISABLED_VALUE);
238
  }
239
-
240
- return $v;
241
  }
242
 
243
  //helpers
244
- public function getStoreUrl(){
 
245
  if(!$this->getData('store_url')){
246
  $this->setStoreUrl(Mage::app()->getStore($this->getStoreId())->getBaseUrl());
247
  }
@@ -251,52 +166,109 @@ class Zero1_Seoredirects_Model_Redirection extends Mage_Core_Model_Abstract
251
  /**
252
  * @return Zero1_Seoredirects_Helper_Data
253
  */
254
- public function getHelper(){
 
255
  return Mage::helper('zero1_seo_redirects');
256
  }
257
 
258
  /**
259
  * @return Zero1_Seoredirects_Helper_Urls
260
  */
261
- protected function _getUrlHelper(){
262
  return Mage::helper('zero1_seo_redirects/urls');
263
  }
264
 
265
  /**
266
  * @return Zero1_Seoredirects_Helper_License
267
  */
268
- protected function _getLicenseHelper(){
 
269
  return Mage::helper('zero1_seo_redirects/license');
270
  }
271
 
 
 
 
 
272
 
273
- public function incrementHits(){
274
- return $this->setHits($this->getHits() + 1);
275
- }
276
-
277
- public function isEnabled(){
278
  return (bool)$this->getStatus();
279
  }
280
 
281
- public function shouldPersistQuery(){
 
282
  return (bool)$this->getPersistQuery();
283
  }
284
 
285
- public function setPersistQuery($persist = false){
286
- $this->setData('persist_query', (bool)$persist);
287
- return $this;
288
- }
289
-
290
- public function getFromUrl(){
291
- if(!$this->getData('from_url')){
292
- $storeUrl = parse_url($this->getStoreUrl());
293
- $this->setFromUrl(
294
- $storeUrl['scheme'].'://'.
295
- preg_replace('/\/$/','',$storeUrl['host']).'/'.
296
- preg_replace('/^\//','',$this->getFromUrlPath()).
297
- ((!$this->getFromUrlQuery())? '' : '?'.$this->getFromUrlQuery())
298
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  }
300
- return $this->getData('from_url');
301
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  }
7
  * @method string getToUrl()
8
  * @method Zero1_Seoredirects_Model_Redirection setToUrl(string $toUrl)
9
  * @method Zero1_Seoredirects_Model_Redirection setStoreId(int $storeId)
10
+ * @method int getStoreId()
11
  * @method Zero1_Seoredirects_Model_Redirection setSource(int $source)
12
  * @method int getSource()
13
  * @method Zero1_Seoredirects_Model_Redirection setStatus(int $status)
38
  const REDIRECTION_STATUS_ENABLED_VALUE = 1;
39
  const REDIRECTION_STATUS_ENABLED_LABEL = 'Enabled';
40
 
41
+ protected $fromUrlInstance;
42
+ protected $toUrlInstance;
43
+ protected $validator;
 
44
 
45
+ protected $urlFactory;
46
+
47
+ protected function _construct()
48
+ {
49
+ $this->_init('zero1_seo_redirects/redirection');
50
+ }
51
+
52
+ /**
53
+ * @return Zero1_Seoredirects_Model_RedirectionValidator
54
+ */
55
+ protected function getValidator()
56
+ {
57
+ if(!$this->validator){
58
+ $this->validator = Mage::getModel('zero1_seo_redirects/redirectionValidator');
59
+ }
60
+ return $this->validator;
61
+ }
62
+
63
+ protected function _afterLoad()
64
+ {
65
+ //todo remove?
66
  $this->setFromUrl($this->getFromUrlPath().(($this->getFromUrlQuery() != '')? '?'.$this->getFromUrlQuery() : ''));
67
  }
68
 
82
  }
83
  }
84
 
85
+ public function save()
86
+ {
87
  if (!$this->_hasModelChanged()) {
88
  return parent::save();
89
  }
90
+
91
+ $this->setFromUrlPath(ltrim($this->getFromUrlPath(), '/'));
92
+ $this->setToUrl(ltrim($this->getToUrl(), '/'));
93
+
94
+ $validation = $this->getValidator()->validate($this);
95
+ $this->checkLicenseState();
96
  if(!$validation['result']){
97
  /* @var $ex Zero1_Seoredirects_Exception */
98
  $ex = Mage::exception('Zero1_Seoredirects', implode('<br />', $validation['errors']));
101
  }
102
  //if its not new and anything other than just hits has changed clear cache for this redirect
103
  $diff = array_diff_assoc((($this->getOrigData() == null)? array() : $this->getOrigData()), $this->getData());
104
+ // fix to get around persist query issue
105
+ if(isset($diff['persist_query']) &&
106
+ ((bool)$this->getOrigData('persist_data') == ((bool)$this->getData('persist_query')))
107
+ ){
108
+ unset($diff['persist_query']);
109
+ }
110
+
111
  if(count($diff) > 1 || !isset($diff['hits'])){
112
  /* @var $cacheCollection Zero1_Seoredirects_Model_Resource_Redirection_Cache_Collection */
113
  $cacheCollection = Mage::getModel('zero1_seo_redirects/redirection_cache')->getCollection();
130
  return parent::save();
131
  }
132
 
133
+ protected function checkLicenseState()
134
+ {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  if($this->getSource() == self::SOURCE_TYPE_LOGGED_VALUE){
136
  $this->setStatus(self::REDIRECTION_STATUS_DISABLED_VALUE);
137
+ return;
138
  }
139
 
140
  //TODO figure out a better way to do this
141
  $cCount = Mage::getModel('zero1_seo_redirects/redirection')->getCollection()
142
  ->addFieldToFilter('status', self::REDIRECTION_STATUS_ENABLED_VALUE);
143
+ if($this->getRedirectionId()){
144
+ $cCount->addFieldToFilter('redirection_id', array('neq' => $this->getRedirectionId()));
145
+ }
146
+ $cCount = $cCount->count();
147
 
148
+ $lCount = $this->getLicenseHelper()->getLicenceLimit();
149
 
150
  if($cCount < $lCount || $lCount == 0){
151
+ $this->setStatus(self::REDIRECTION_STATUS_ENABLED_VALUE);
152
  }else{
153
+ $this->setStatus(self::REDIRECTION_STATUS_DISABLED_VALUE);
154
  }
 
 
155
  }
156
 
157
  //helpers
158
+ public function getStoreUrl()
159
+ {
160
  if(!$this->getData('store_url')){
161
  $this->setStoreUrl(Mage::app()->getStore($this->getStoreId())->getBaseUrl());
162
  }
166
  /**
167
  * @return Zero1_Seoredirects_Helper_Data
168
  */
169
+ public function getHelper()
170
+ {
171
  return Mage::helper('zero1_seo_redirects');
172
  }
173
 
174
  /**
175
  * @return Zero1_Seoredirects_Helper_Urls
176
  */
177
+ protected function getUrlHelper(){
178
  return Mage::helper('zero1_seo_redirects/urls');
179
  }
180
 
181
  /**
182
  * @return Zero1_Seoredirects_Helper_License
183
  */
184
+ protected function getLicenseHelper()
185
+ {
186
  return Mage::helper('zero1_seo_redirects/license');
187
  }
188
 
189
+ public function incrementHits()
190
+ {
191
+ return $this->setHits($this->getHits() + 1);
192
+ }
193
 
194
+ public function isEnabled()
195
+ {
 
 
 
196
  return (bool)$this->getStatus();
197
  }
198
 
199
+ public function shouldPersistQuery()
200
+ {
201
  return (bool)$this->getPersistQuery();
202
  }
203
 
204
+ public function setPersistQuery($persist = false)
205
+ {
206
+ $this->setData('persist_query', (bool)$persist);
207
+ return $this;
208
+ }
209
+
210
+ /**
211
+ * @param Zero1_Seoredirects_Model_Url $url
212
+ * @return Zero1_Seoredirects_Model_Redirection
213
+ */
214
+ public function setFromUrlInstance(Zero1_Seoredirects_Model_Url $url)
215
+ {
216
+ $this->fromUrlInstance = $url;
217
+ $this->setFromUrlPath($url->getPath());
218
+ $this->setFromUrlQuery($url->getQuery());
219
+ $this->setStoreId($url->getStoreId());
220
+ return $this;
221
+ }
222
+
223
+ /**
224
+ * @return Zero1_Seoredirects_Model_Url
225
+ */
226
+ public function getFromUrlInstance($force = false)
227
+ {
228
+ if(!$this->fromUrlInstance || $force){
229
+ $url = $this->getFromUrlPath().(($this->getFromUrlQuery())? '?'.$this->getFromUrlQuery() : '');
230
+ $this->fromUrlInstance = $this->getUrlFactory()
231
+ ->setAllowedStores(array($this->getStoreId()))
232
+ ->buildUrl($this->getToUrl($url));
233
  }
234
+ return $this->fromUrlInstance;
235
  }
236
+
237
+ /**
238
+ * @param Zero1_Seoredirects_Model_Url $url
239
+ * @return Zero1_Seoredirects_Model_Redirection
240
+ */
241
+ public function setToUrlInstance(Zero1_Seoredirects_Model_Url $url)
242
+ {
243
+ $this->toUrlInstance = $url;
244
+ $this->setToUrl('/'.$url->getUrl(false, false, true, true));
245
+ $this->setStoreId($url->getStoreId());
246
+ return $this;
247
+ }
248
+
249
+ /**
250
+ * @return Zero1_Seoredirects_Model_UrlFactory
251
+ */
252
+ protected function getUrlFactory()
253
+ {
254
+ if(!$this->urlFactory){
255
+ $this->urlFactory = Mage::getModel('zero1_seo_redirects/urlFactory');
256
+ }
257
+ return $this->urlFactory;
258
+ }
259
+
260
+ /**
261
+ * @param bool $force
262
+ * @return Zero1_Seoredirects_Model_Url
263
+ */
264
+ public function getToUrlInstance($force = false)
265
+ {
266
+ if(!$this->toUrlInstance || $force){
267
+ $this->toUrlInstance = $this->getUrlFactory()
268
+ ->setAllowedStores(array($this->getStoreId()))
269
+ ->buildUrl('/'.ltrim($this->getToUrl(), '/'));
270
+ }
271
+ return $this->toUrlInstance;
272
+ }
273
+
274
  }
app/code/community/Zero1/Seoredirects/Model/RedirectionValidator.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Model_RedirectionValidator
3
+ {
4
+ protected $redirecter;
5
+
6
+ /**
7
+ * @param Zero1_Seoredirects_Model_Redirection $redirection
8
+ * @return array
9
+ */
10
+ public function validate(Zero1_Seoredirects_Model_Redirection &$redirection)
11
+ {
12
+ //Mage::log(__METHOD__.'START', Zend_Log::DEBUG, 'seo.log', true);
13
+ $this->redirection = $redirection;
14
+ $validationResult = array(
15
+ 'result' => true,
16
+ 'errors' => array(),
17
+ );
18
+ $this->validatePersistQuery($validationResult, $redirection);
19
+ $this->validateTo($validationResult, $redirection);
20
+ $this->validateFrom($validationResult, $redirection);
21
+ $this->validateToAndFrom($validationResult, $redirection);
22
+ return $validationResult;
23
+ }
24
+
25
+ protected function validatePersistQuery($validationResult, Zero1_Seoredirects_Model_Redirection &$redirection)
26
+ {
27
+ //Mage::log(__METHOD__.'START', Zend_Log::DEBUG, 'seo.log', true);
28
+ if($redirection->getFromType() != $redirection::FROM_TYPE_OPEN_ENDED_QUERY_VALUE){
29
+ $redirection->setPersistQuery(false);
30
+ }
31
+ return $validationResult;
32
+ }
33
+
34
+ protected function validateTo($validationResult, Zero1_Seoredirects_Model_Redirection &$redirection)
35
+ {
36
+ //Mage::log(__METHOD__.'::START', Zend_Log::DEBUG, 'seo.log', true);
37
+ //Mage::log('url: '.$redirection->getToUrlInstance(true)->getUrl(), Zend_Log::DEBUG, 'seo.log', true);
38
+ $redirecter = $this->getRedirecter();
39
+ list($id, $url) = $redirecter->getRedirectId(
40
+ $redirection->getStoreId(),
41
+ $redirection->getToUrlInstance()->getUrl(),
42
+ true
43
+ );
44
+ if($id){
45
+ $validationResult['result'] = false;
46
+ $validationResult['errors'][] = $this->getHelper()->__('A redirect for the location you are redirecting to already exists ('.$url.').');
47
+ }
48
+ return $validationResult;
49
+ }
50
+
51
+ protected function validateFrom($validationResult, Zero1_Seoredirects_Model_Redirection &$redirection)
52
+ {
53
+ //Mage::log(__METHOD__.'START', Zend_Log::DEBUG, 'seo.log', true);
54
+ $redirecter = $this->getRedirecter();
55
+ list($id, $url) = $redirecter->getRedirectId(
56
+ $redirection->getStoreId(),
57
+ $redirection->getFromUrlPath(),
58
+ true
59
+ );
60
+
61
+ if($id && $id != $redirection->getId()){
62
+ $validationResult['result'] = false;
63
+ $validationResult['errors'][] = $this->getHelper()->__('A redirect for this location already exists ('.$url.').');
64
+ }
65
+ return $validationResult;
66
+ }
67
+
68
+ protected function validateToAndFrom($validationResult, Zero1_Seoredirects_Model_Redirection &$redirection)
69
+ {
70
+ //Mage::log(__METHOD__.'START', Zend_Log::DEBUG, 'seo.log', true);
71
+ if($redirection->getToUrl() == $redirection->getFromUrlInstance()->getUrl(false, false, true, true)){
72
+ $validationResult['result'] = false;
73
+ $validationResult['errors'][] = $this->getHelper()->__('A redirect cannot have a to and from that are the same');
74
+ }
75
+ return $validationResult;
76
+ }
77
+
78
+ /**
79
+ * @return Zero1_Seoredirects_Model_Redirecter
80
+ */
81
+ protected function getRedirecter()
82
+ {
83
+ //Mage::log(__METHOD__.'START', Zend_Log::DEBUG, 'seo.log', true);
84
+ if(!$this->redirecter){
85
+ $this->redirecter = Mage::getModel('zero1_seo_redirects/redirecter');
86
+ }
87
+ return $this->redirecter;
88
+ }
89
+
90
+ /**
91
+ * @return Zero1_Seoredirects_Helper_Data
92
+ */
93
+ protected function getHelper()
94
+ {
95
+ return Mage::helper('zero1_seo_redirects');
96
+ }
97
+ }
app/code/community/Zero1/Seoredirects/Model/Redirector.php CHANGED
@@ -229,7 +229,6 @@ class Zero1_Seoredirects_Model_Redirector{
229
  ->setStatus(0)
230
  ->setFromUrlQuery((isset($parsedUrl['query'])? $parsedUrl['query'] : null))
231
  ->setFromType(Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_VALUE)
232
- ->setHits(1)
233
  ->save();
234
 
235
  if($this->_getHelper()->canDebug()){
229
  ->setStatus(0)
230
  ->setFromUrlQuery((isset($parsedUrl['query'])? $parsedUrl['query'] : null))
231
  ->setFromType(Zero1_Seoredirects_Model_Redirection::FROM_TYPE_FIXED_QUERY_VALUE)
 
232
  ->save();
233
 
234
  if($this->_getHelper()->canDebug()){
app/code/community/Zero1/Seoredirects/Model/Resource/ImportLog.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Model_Resource_ImportLog extends Mage_Core_Model_Mysql4_Abstract
3
+ {
4
+ protected function _construct()
5
+ {
6
+ $this->_init('zero1_seo_redirects/importLog', 'id');
7
+ }
8
+ }
app/code/community/Zero1/Seoredirects/Model/Resource/ImportLog/Collection.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Model_Resource_ImportLog_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
3
+ {
4
+ protected function _construct()
5
+ {
6
+ $this->_init('zero1_seo_redirects/importLog');
7
+ }
8
+
9
+ public function delete()
10
+ {
11
+ $this->load();
12
+ /** @var Zero1_Seoredirects_Model_ImportLog $r */
13
+ foreach($this->_items as $r){
14
+ $r->delete();
15
+ }
16
+ $this->clear();
17
+ $this->load();
18
+ }
19
+
20
+ public function deleteAll()
21
+ {
22
+ $this->getConnection()->delete($this->getMainTable());
23
+ }
24
+ }
app/code/community/Zero1/Seoredirects/Model/Resource/ImportStatus.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Model_Resource_ImportStatus extends Mage_Core_Model_Mysql4_Abstract
3
+ {
4
+ protected function _construct()
5
+ {
6
+ $this->_init('zero1_seo_redirects/importStatus', 'id');
7
+ }
8
+ }
app/code/community/Zero1/Seoredirects/Model/Resource/ImportStatus/Collection.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Model_Resource_ImportStatus_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
3
+ {
4
+ protected function _construct()
5
+ {
6
+ $this->_init('zero1_seo_redirects/importStatus');
7
+ }
8
+
9
+ public function delete()
10
+ {
11
+ $this->load();
12
+ foreach($this->_items as $r){
13
+ $r->delete();
14
+ }
15
+ }
16
+
17
+ public function deleteAll()
18
+ {
19
+ $this->getConnection()->delete($this->getMainTable());
20
+ }
21
+ }
app/code/community/Zero1/Seoredirects/Model/Resource/Redirection.php CHANGED
@@ -23,4 +23,34 @@ class Zero1_Seoredirects_Model_Resource_Redirection extends Mage_Core_Model_Mysq
23
 
24
  return $read->fetchOne($select);
25
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
23
 
24
  return $read->fetchOne($select);
25
  }
26
+
27
+ /**
28
+ * Prepare data for passed table
29
+ *
30
+ * @param Varien_Object $object
31
+ * @param string $table
32
+ * @return array
33
+ */
34
+ protected function _prepareDataForTable(Varien_Object $object, $table)
35
+ {
36
+ $data = array();
37
+ $fields = $this->_getWriteAdapter()->describeTable($table);
38
+ foreach (array_keys($fields) as $field) {
39
+ if ($object->hasData($field)) {
40
+ $fieldValue = $object->getData($field);
41
+ if ($fieldValue instanceof Zend_Db_Expr) {
42
+ $data[$field] = $fieldValue;
43
+ } else {
44
+ if (null !== $fieldValue) {
45
+ $fieldValue = $this->_prepareTableValueForSave($fieldValue, $fields[$field]['DATA_TYPE']);
46
+ $data[$field] = $this->_getWriteAdapter()->prepareColumnValue($fields[$field], $fieldValue);
47
+ } else if (!empty($fields[$field]['NULLABLE'])) {
48
+ $data[$field] = null;
49
+ }
50
+ }
51
+ }
52
+ }
53
+ $data['updated_at'] = null;
54
+ return $data;
55
+ }
56
  }
app/code/community/Zero1/Seoredirects/Model/Url.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Zero1_Seoredirects_Model_Url
4
+ */
5
+ class Zero1_Seoredirects_Model_Url
6
+ {
7
+ const SCHEME_HTTPS = 'https';
8
+ const SCHEME_HTTP = 'http';
9
+
10
+ //example https://www.mysite.com/uk/catalog/product?a=1&b=2
11
+ protected $scheme; // https
12
+ protected $host;// www.mysite.com/uk/
13
+ protected $path;// catalog/product
14
+ protected $query;// a=1&b=2
15
+ protected $storeId;
16
+
17
+ /**
18
+ * @param bool $scheme
19
+ * @param bool $host
20
+ * @param bool $path
21
+ * @param bool $query
22
+ * @return string
23
+ */
24
+ public function getUrl($scheme = true, $host = true, $path = true, $query = true)
25
+ {
26
+ $url = '';
27
+ if($scheme){
28
+ $url .= $this->scheme.'://';
29
+ }
30
+ if($host){
31
+ $url .= $this->host;
32
+ }
33
+ if($path){
34
+ $url .= $this->path;
35
+ }
36
+ if($query){
37
+ if($this->query != ''){
38
+ $url .= '?'.$this->query;
39
+ }
40
+ }
41
+ return $url;
42
+ }
43
+
44
+ /**
45
+ * @param $scheme
46
+ * @return $this
47
+ * @throws Exception
48
+ */
49
+ public function setScheme($scheme)
50
+ {
51
+ if($scheme != self::SCHEME_HTTP && $scheme != self::SCHEME_HTTPS){
52
+ throw new Exception(sprintf('Invalid Scheme: %s', $scheme));
53
+ }
54
+ $this->scheme = $scheme;
55
+ return $this;
56
+ }
57
+
58
+ /**
59
+ * @return mixed
60
+ */
61
+ public function getScheme()
62
+ {
63
+ return $this->scheme;
64
+ }
65
+
66
+ /**
67
+ * @param $host
68
+ * @return $this
69
+ */
70
+ public function setHost($host)
71
+ {
72
+ $host = rtrim($host, '/').'/';
73
+ $this->host = $host;
74
+ return $this;
75
+ }
76
+
77
+ /**
78
+ * @return mixed
79
+ */
80
+ public function getHost()
81
+ {
82
+ return $this->host;
83
+ }
84
+
85
+ /**
86
+ * @param $path
87
+ * @return $this
88
+ */
89
+ public function setPath($path)
90
+ {
91
+ $this->path = ltrim($path, '/');
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * @return mixed
97
+ */
98
+ public function getPath()
99
+ {
100
+ return $this->path;
101
+ }
102
+
103
+ /**
104
+ * @param $query
105
+ * @return $this
106
+ */
107
+ public function setQuery($query)
108
+ {
109
+ $this->query = $query;
110
+ if($this->storeId){
111
+ $strippedQuery = $this->getHelper()->stripIgnoreables($this->storeId, $this->getAssocQuery());
112
+ if(empty($strippedQuery)){
113
+ $this->query = null;
114
+ }else{
115
+ $this->query = http_build_query($strippedQuery);
116
+ }
117
+ }
118
+
119
+ return $this;
120
+ }
121
+
122
+ /**
123
+ * @return mixed
124
+ */
125
+ public function getQuery()
126
+ {
127
+ return $this->query;
128
+ }
129
+
130
+ public function hasQuery()
131
+ {
132
+ if($this->query == '' || $this->query == null || $this->query == false){
133
+ return false;
134
+ }else{
135
+ return true;
136
+ }
137
+ }
138
+
139
+ public function mergeQuery(array $mergingQueryParams)
140
+ {
141
+ $currentParams = $this->getAssocQuery();
142
+ foreach($mergingQueryParams as $k => $v){
143
+ $currentParams[$k] = $v;
144
+ }
145
+ $this->setQuery(http_build_query($currentParams));
146
+ }
147
+
148
+ /**
149
+ * @param $id
150
+ * @return $this
151
+ */
152
+ public function setStoreId($id)
153
+ {
154
+ $this->storeId = $id;
155
+ return $this;
156
+ }
157
+
158
+ /**
159
+ * @return mixed
160
+ */
161
+ public function getStoreId()
162
+ {
163
+ return $this->storeId;
164
+ }
165
+
166
+ /**
167
+ * @return Zero1_Seoredirects_Helper_Data
168
+ */
169
+ protected function getHelper()
170
+ {
171
+ return Mage::helper('zero1_seo_redirects');
172
+ }
173
+
174
+ public function getAssocQuery()
175
+ {
176
+ $query = $this->query;
177
+ $urlParams = array();
178
+ if($query == null || $query == ''){
179
+ return $urlParams;
180
+ }
181
+ $query = ltrim($query, '?');
182
+
183
+ if(strpos($query, '&') !== false){
184
+ $params = explode('&', $query);
185
+ }else{
186
+ $params = array($query);
187
+ }
188
+ if(empty($params)){
189
+ return $urlParams;
190
+ }
191
+ foreach($params as $pair){
192
+ list($key, $value) = explode('=', $pair);
193
+ $urlParams[$key] = $value;
194
+ }
195
+ return $urlParams;
196
+ }
197
+ }
app/code/community/Zero1/Seoredirects/Model/UrlFactory.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Zero1_Seoredirects_Model_UrlFactory
4
+ *
5
+ */
6
+ class Zero1_Seoredirects_Model_UrlFactory
7
+ {
8
+ protected $lockedUrl = null;
9
+ protected $allowedUrls;
10
+
11
+ const SCHEME_HTTP = 'http';
12
+ const SCHEME_HTTPS = 'https';
13
+
14
+ /**
15
+ * @param $url
16
+ * @return Zero1_Seoredirects_Model_Url
17
+ */
18
+ public function buildUrl($url)
19
+ {
20
+ $matchFound = false;
21
+ $biggestMatch = '';
22
+ $biggestMatchValue = -1;
23
+ if($this->lockedUrl === null){
24
+ foreach($this->allowedUrls as $storeUrl => $storeUlrObj){
25
+ list($found, $matchValue) = $this->match($storeUlrObj, $url);
26
+ if($found){
27
+ $matchFound = true;
28
+ if($matchValue > $biggestMatchValue){
29
+ $biggestMatch = $storeUrl;
30
+ $biggestMatchValue = $matchValue;
31
+ }
32
+ }
33
+ }
34
+ }else{
35
+ list($found, $matchValue) = $this->match($this->lockedUrl, $url);
36
+ if($found){
37
+ $matchFound = true;
38
+ $biggestMatch = $this->lockedUrl->getUrl(true, true, false, false);
39
+ }
40
+ }
41
+
42
+ if(!$matchFound){
43
+ /** @var Zero1_Seoredirects_Model_Url $urlObj */
44
+ $urlObj = Mage::getModel('zero1_seo_redirects/url');
45
+ return $urlObj;
46
+ }
47
+
48
+ return $this->buildMatchedUrl($this->allowedUrls[$biggestMatch], $url);
49
+ }
50
+
51
+ protected function match(Zero1_Seoredirects_Model_Url $storeUrl, $toBeCheckedUrl)
52
+ {
53
+ $parsedToBeCheckedUrl = $this->parseUrl($toBeCheckedUrl);
54
+ if(!isset($parsedToBeCheckedUrl['host'])){
55
+ return array(true, 0);
56
+ }
57
+
58
+ if(isset($parsedToBeCheckedUrl['scheme'])){
59
+ if($parsedToBeCheckedUrl['scheme'] != $storeUrl->getScheme()){
60
+ return array(false, 0);
61
+ }
62
+ }
63
+
64
+ $toBeCheckedHostAndPath = '';
65
+ if(isset($parsedToBeCheckedUrl['host'])){
66
+ $toBeCheckedHostAndPath .= rtrim($parsedToBeCheckedUrl['host'], '/').'/';
67
+ }
68
+ if(isset($parsedToBeCheckedUrl['path'])){
69
+ $toBeCheckedHostAndPath .= ltrim($parsedToBeCheckedUrl['path'], '/');
70
+ }
71
+
72
+ $index = strpos($toBeCheckedHostAndPath, $storeUrl->getUrl(false, true, false, false));
73
+ if($index !== 0){
74
+ return array(false, 0);
75
+ }
76
+
77
+ return array(true, strlen($toBeCheckedHostAndPath));
78
+ }
79
+
80
+ protected function buildMatchedUrl(Zero1_Seoredirects_Model_Url $storeUrl, $toBeBuiltUrl)
81
+ {
82
+ $parsedToBeBuilt = $this->parseUrl($toBeBuiltUrl);
83
+ /** @var Zero1_Seoredirects_Model_Url $urlObj */
84
+ $urlObj = Mage::getModel('zero1_seo_redirects/url');
85
+ $urlObj->setStoreId($storeUrl->getStoreId());
86
+
87
+ if(!isset($parsedToBeBuilt['scheme'])){
88
+ $urlObj->setScheme($storeUrl->getScheme());
89
+ }else{
90
+ $urlObj->setScheme($parsedToBeBuilt['scheme']);
91
+ }
92
+
93
+ if(!isset($parsedToBeBuilt['host'])){
94
+ $urlObj->setHost($storeUrl->getHost());
95
+ if(isset($parsedToBeBuilt['path'])){
96
+ $urlObj->setPath($parsedToBeBuilt['path']);
97
+ }
98
+ }else{
99
+ $toBeBuiltHostAndPath = $parsedToBeBuilt['host'];
100
+ if(isset($parsedToBeBuilt['path'])){
101
+ $toBeBuiltHostAndPath .= $parsedToBeBuilt['path'];
102
+ }
103
+ if(strpos($toBeBuiltHostAndPath, $storeUrl->getHost()) !== 0){
104
+ die('Error');
105
+ }
106
+ $length = strlen($storeUrl->getHost());
107
+ $urlObj->setHost(substr($toBeBuiltHostAndPath, 0, $length));
108
+ $urlObj->setPath(substr($toBeBuiltHostAndPath, $length));
109
+ }
110
+
111
+ if(isset($parsedToBeBuilt['query'])){
112
+ $urlObj->setQuery($parsedToBeBuilt['query']);
113
+ }
114
+ return $urlObj;
115
+ }
116
+
117
+ public function lockToUrl(Zero1_Seoredirects_Model_Url $url)
118
+ {
119
+ $this->lockedUrl = $url;
120
+ }
121
+
122
+ public function unlockToUrl()
123
+ {
124
+ $this->lockedUrl = null;
125
+ }
126
+
127
+ public function setAllowedUrls(array $allowedUrls)
128
+ {
129
+ $this->allowedUrls = array();
130
+ foreach($allowedUrls as $storeUrl => $storeId){
131
+ $urlObj = $this->buildAllowedUrl($storeUrl, $storeId);
132
+ $this->allowedUrls[$urlObj->getUrl()] = $urlObj;
133
+ }
134
+ return $this;
135
+ }
136
+
137
+ public function setAllowedStores(array $storeIds)
138
+ {
139
+ $allowedUrls = array();
140
+ foreach($storeIds as $storeId){
141
+ /** @var Mage_Core_Model_Store $store */
142
+ $store = Mage::app()->getStore($storeId);
143
+ $allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, false)] = $storeId;
144
+ $allowedUrls[$store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true)] = $storeId;
145
+ }
146
+ return $this->setAllowedUrls($allowedUrls);
147
+ }
148
+
149
+ protected function buildAllowedUrl($url, $storeId)
150
+ {
151
+ /** @var Zero1_Seoredirects_Model_Url $urlObj */
152
+ $urlObj = Mage::getModel('zero1_seo_redirects/url');
153
+ $parsed = $this->parseUrl($url);
154
+ $urlObj->setScheme($parsed['scheme']);
155
+ $host = '';
156
+ if(isset($parsed['host'])){
157
+ $host .= $parsed['host'];
158
+ }
159
+ if(isset($parsed['path'])){
160
+ $host .= $parsed['path'];
161
+ }
162
+ $urlObj->setHost($host);
163
+ $urlObj->setStoreId($storeId);
164
+ return $urlObj;
165
+ }
166
+
167
+ protected function parseUrl($url)
168
+ {
169
+ $parsed = array();
170
+
171
+ $index = strpos($url, '://');
172
+ if($index !== false){
173
+ $scheme = substr($url, 0, $index);
174
+ if($this->isValidScheme($scheme)){
175
+ $parsed['scheme'] = $scheme;
176
+ $url = substr($url, ($index + 3));
177
+ }
178
+ }
179
+
180
+ $index = strpos($url, '/');
181
+ if($index === false){
182
+ $parsed['path'] = $url;
183
+ return $parsed;
184
+ }
185
+
186
+ if($index !== 0){
187
+ $parsed['host'] = substr($url, 0, $index);
188
+ $url = substr($url, $index);
189
+ }
190
+
191
+ $index = strpos($url, '?');
192
+ if($index !== false){
193
+ $parsed['path'] = substr($url, 0, $index);
194
+ $url = substr($url, ($index + 1));
195
+ $parsed['query'] = $url;
196
+ }else{
197
+ $parsed['path'] = $url;
198
+ }
199
+
200
+ return $parsed;
201
+ }
202
+
203
+ public function isValidScheme($scheme)
204
+ {
205
+ switch($scheme){
206
+ case self::SCHEME_HTTP:
207
+ case self::SCHEME_HTTPS:
208
+ return true;
209
+ default:
210
+ return false;
211
+ }
212
+ }
213
+ }
app/code/community/Zero1/Seoredirects/README.md ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h1>Seo Redirects</h1>
2
+
3
+ <h3>Developers</h3>
4
+ <p>
5
+ <ul>
6
+ <li>Adam</li>
7
+ <li>Pete</li>
8
+ </ul>
9
+ </p>
10
+
11
+ <h3>Description</h3>
12
+ <p>
13
+ A Module to allow redirects to be imported into magento from multiple sources.
14
+ </p>
15
+
16
+ <h3>Contents</h3>
17
+ <ul>
18
+ <li><a href="docs/tests.md">Tests</a></li>
19
+ <li><a href="">Configuration Examples</a></li>
20
+ <li><a href="">Uses / Actions</a></li>
21
+ <li><a href="">Got Yas</a></li>
22
+ <li><a href="">TODOs</a></li>
23
+ </ul>
app/code/community/Zero1/Seoredirects/controllers/Adminhtml/Seoredirects/ImportController.php CHANGED
@@ -3,6 +3,9 @@ class Zero1_Seoredirects_Adminhtml_Seoredirects_ImportController extends Mage_Ad
3
  {
4
  public function indexAction()
5
  {
 
 
 
6
  $this->_title($this->__('SEO Redirects'))
7
  ->_title($this->__('Import Redirects'));
8
  $this->loadLayout();
@@ -10,7 +13,36 @@ class Zero1_Seoredirects_Adminhtml_Seoredirects_ImportController extends Mage_Ad
10
  $this->renderLayout();
11
  }
12
 
13
- public function runAction(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  /* @var $import Zero1_Seoredirects_Model_Importer */
15
  $import = Mage::getModel('zero1_seo_redirects/importer');
16
  $content = '';
3
  {
4
  public function indexAction()
5
  {
6
+ // if(Zero1_Seoredirects_Model_Importer::isRunning()){
7
+ // return $this->_redirect('*/*/status');
8
+ // }
9
  $this->_title($this->__('SEO Redirects'))
10
  ->_title($this->__('Import Redirects'));
11
  $this->loadLayout();
13
  $this->renderLayout();
14
  }
15
 
16
+ public function runAction()
17
+ {
18
+ //Mage::log(__METHOD__, Zend_Log::DEBUG, 'adam.log', true);
19
+ $pathToScript = Mage::getModuleDir('', 'Zero1_Seoredirects').DS.'scripts'.DS.'import.php';
20
+ $phpLocation = Mage::helper('zero1_seo_redirects')->getPhpLocation();
21
+ $logLocation = Mage::getBaseDir('log').DS.'seo.log';
22
+ $cmd = sprintf('%s %s 1>> %s 2>&1 &', $phpLocation, $pathToScript, $logLocation);
23
+ //Mage::log('cmd: '.$cmd, Zend_Log::DEBUG, 'adam.log', true);
24
+ shell_exec($cmd);
25
+ return;
26
+ }
27
+
28
+ public function unlockAction()
29
+ {
30
+ /** @var Mage_Core_Model_Config_Data $config */
31
+ $config = Mage::getModel('core/config_data')->load(Zero1_Seoredirects_Model_Importer::CONFIG_PATH_RUNLOCK, 'path');
32
+ if(!$config->getId()){
33
+ $config->setScope('default')
34
+ ->setScopeId(0)
35
+ ->setPath(Zero1_Seoredirects_Model_Importer::CONFIG_PATH_RUNLOCK);
36
+ }
37
+ $config->setValue(Zero1_Seoredirects_Model_Importer::RUNLOCK_NOT_RUNNING)->save();
38
+
39
+ echo json_encode(array(
40
+ 'result' => 'OK',
41
+ ));
42
+ die;
43
+ }
44
+
45
+ public function runaAction(){
46
  /* @var $import Zero1_Seoredirects_Model_Importer */
47
  $import = Mage::getModel('zero1_seo_redirects/importer');
48
  $content = '';
app/code/community/Zero1/Seoredirects/controllers/Adminhtml/Seoredirects/ImportLogController.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Zero1_Seoredirects_Adminhtml_Seoredirects_ImportLogController extends Mage_Adminhtml_Controller_Action
3
+ {
4
+ public function indexAction()
5
+ {
6
+ $this->_title($this->__('SEO Redirects'))
7
+ ->_title($this->__('Import Logs'));
8
+
9
+ $this->loadLayout();
10
+ $this->_setActiveMenu('catalog/seoredirects');
11
+ $this->renderLayout();
12
+ }
13
+
14
+ public function gridAction()
15
+ {
16
+ $this->loadLayout(false);
17
+ $this->renderLayout();
18
+ }
19
+ }
app/code/community/Zero1/Seoredirects/controllers/Adminhtml/Seoredirects/ManageController.php CHANGED
@@ -52,6 +52,7 @@ class Zero1_Seoredirects_Adminhtml_Seoredirects_ManageController extends Mage_Ad
52
  //add changes from form
53
  $model->setData($data);
54
  try{
 
55
  $model->save();
56
 
57
  Mage::getSingleton('adminhtml/session')->addSuccess(
52
  //add changes from form
53
  $model->setData($data);
54
  try{
55
+ $model->setSource(Zero1_Seoredirects_Model_Redirection::SOURCE_TYPE_MANUAL_VALUE);
56
  $model->save();
57
 
58
  Mage::getSingleton('adminhtml/session')->addSuccess(
app/code/community/Zero1/Seoredirects/docs/tests.md ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <a href="../README.md">Home</a>/
2
+ <h1>Tests</h1>
3
+ <p>This should be a consolidated list of the use case tests this module should pass</p>
4
+ <table>
5
+ <colgroup>
6
+ <col width="10%">
7
+ <col width="15%">
8
+ <col width="25%">
9
+ <col width="10%">
10
+ <col width="35%">
11
+ </colgroup>
12
+ <tr>
13
+ <th>ID</th>
14
+ <th>Name</th>
15
+ <th>Short Description</th>
16
+ <th>Result</th>
17
+ <th>Notes</th>
18
+ </tr>
19
+ <tr>
20
+ <th colspan="5">Installation Tests</th>
21
+ </tr>
22
+ <tr>
23
+ <td>0.0</td>
24
+ <td><a href="tests/0/0.md">Install Test</a></td>
25
+ <td>Check installation via MCM</td>
26
+ <td></td>
27
+ <td></td>
28
+ </tr>
29
+ </table>
30
+
31
+ <h3>Single Store</h3>
32
+ <p>The following tests should be performed on a single store installation see <a href="">here</a> for specifics</p>
33
+
34
+ <table>
35
+ <colgroup>
36
+ <col width="10%">
37
+ <col width="15%">
38
+ <col width="25%">
39
+ <col width="10%">
40
+ <col width="35%">
41
+ </colgroup>
42
+ <tr>
43
+ <th>ID</th>
44
+ <th>Name</th>
45
+ <th>Short Description</th>
46
+ <th>Result</th>
47
+ <th>Notes</th>
48
+ </tr>
49
+ <tr>
50
+ <th colspan="5">CRUD tests</th>
51
+ </tr>
52
+ <tr>
53
+ <td>1.0</td>
54
+ <td><a href="tests/1/0.md">Create Test</a></td>
55
+ <td>Check manual creation</td>
56
+ <td></td>
57
+ <td></td>
58
+ </tr>
59
+ <tr>
60
+ <th colspan="5">Import Tests</th>
61
+ </tr>
62
+ <tr>
63
+ <td>2.0</td>
64
+ <td><a href="tests/2/0.md">Fixed Import Test</a></td>
65
+ <td>Check basic import functionality</td>
66
+ <td></td>
67
+ <td></td>
68
+ </tr>
69
+ </table>
app/code/community/Zero1/Seoredirects/docs/tests/1/0.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <a href="../../../README.md">Home</a>&nbsp;/&nbsp;<a href="../../tests.md">Tests</a>
2
+ <h1>Manual Create Test</h1>
3
+
4
+ <h3>Dependencies</h3>
5
+ <ul>
6
+ <li>0.*</li>
7
+ </ul>
8
+
9
+
10
+ <h3>Pre Test Setup</h3>
11
+ <ul>
12
+ <li>There should currently be no redirects on the install</li>
13
+ </ul>
14
+
15
+
16
+ <h3>Test</h3>
17
+ <table>
18
+ <colgroup>
19
+ <col width="10%">
20
+ <col width="15%">
21
+ <col width="25%">
22
+ <col width="10%">
23
+ <col width="35%">
24
+ </colgroup>
25
+ <tr>
26
+ <th>ID</th>
27
+ <th>Name</th>
28
+ <th>Short Description</th>
29
+ <th>Result</th>
30
+ <th>Notes</th>
31
+ </tr>
32
+ <tr>
33
+ <td>0.0</td>
34
+ <td><a href="tests/0/0.md">Install Test</a></td>
35
+ <td>Check installation via MCM</td>
36
+ <td></td>
37
+ <td></td>
38
+ </tr>
39
+ <tr>
40
+ <td>1.0</td>
41
+ <td><a href="tests/1/0.md">Create Test</a></td>
42
+ <td>Check manual creation</td>
43
+ <td></td>
44
+ <td></td>
45
+ </tr>
46
+ <tr>
47
+ <td>2.0</td>
48
+ <td><a href="tests/2/0.md">Fixed Import Test</a></td>
49
+ <td>Check basic import functionality</td>
50
+ <td></td>
51
+ <td></td>
52
+ </tr>
53
+ </table>
54
+
55
+
56
+ <h3>Expected Outcome</h3>
57
+ <p>All of the above should pass</p>
app/code/community/Zero1/Seoredirects/docs/tests/2/0.md ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h1>Fixed Import Test</h1>
2
+
3
+ <h3>Dependencies</h3>
4
+ <ul>
5
+ <li>0.*</li>
6
+ <li>1.*</li>
7
+ </ul>
8
+
9
+
10
+ <h3>Pre Test Setup</h3>
11
+ <ul>
12
+ <li>Make sure module is installed</li>
13
+ <li>Make sure there are currently no imported redirects</li>
14
+ </ul>
15
+
16
+
17
+ <h3>Test</h3>
18
+
19
+
20
+ <h3>Expected Outcome</h3>
app/code/community/Zero1/Seoredirects/etc/adminhtml.xml CHANGED
@@ -33,12 +33,19 @@
33
  <config>
34
  <children>
35
  <seoredirects translate="title" module="zero1_seo_redirects">
36
- <title>SEO Redirect</title>
37
  </seoredirects>
38
  </children>
39
  </config>
40
  </children>
41
  </system>
 
 
 
 
 
 
 
42
  </children>
43
  </admin>
44
  </resources>
33
  <config>
34
  <children>
35
  <seoredirects translate="title" module="zero1_seo_redirects">
36
+ <title>SEO Redirects</title>
37
  </seoredirects>
38
  </children>
39
  </config>
40
  </children>
41
  </system>
42
+ <catalog>
43
+ <children>
44
+ <seoredirects translate="title" module="zero1_seo_redirects">
45
+ <title>SEO Redirects</title>
46
+ </seoredirects>
47
+ </children>
48
+ </catalog>
49
  </children>
50
  </admin>
51
  </resources>
app/code/community/Zero1/Seoredirects/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <Zero1_Seoredirects>
5
- <version>1.1.1</version>
6
  </Zero1_Seoredirects>
7
  </modules>
8
 
@@ -22,6 +22,12 @@
22
  <redirection_cache>
23
  <table>zero1_seoredirects_redirection_cache</table>
24
  </redirection_cache>
 
 
 
 
 
 
25
  </entities>
26
  </zero1_seo_redirects_resource>
27
  </models>
2
  <config>
3
  <modules>
4
  <Zero1_Seoredirects>
5
+ <version>1.1.9</version>
6
  </Zero1_Seoredirects>
7
  </modules>
8
 
22
  <redirection_cache>
23
  <table>zero1_seoredirects_redirection_cache</table>
24
  </redirection_cache>
25
+ <importLog>
26
+ <table>zero1_seoredirects_redirection_import_log</table>
27
+ </importLog>
28
+ <importStatus>
29
+ <table>zero1_seoredirects_redirection_import_status</table>
30
+ </importStatus>
31
  </entities>
32
  </zero1_seo_redirects_resource>
33
  </models>
app/code/community/Zero1/Seoredirects/etc/system.xml CHANGED
@@ -140,11 +140,29 @@
140
  <show_in_store>1</show_in_store>
141
  <comment><![CDATA[How much information should be displayed after running an import]]></comment>
142
  </import_log_level>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  <enable_reporting traslate="label">
144
  <label>Enable reporting</label>
145
  <frontend_type>select</frontend_type>
146
  <source_model>adminhtml/system_config_source_yesno</source_model>
147
- <sort_order>13</sort_order>
148
  <show_in_default>1</show_in_default>
149
  <show_in_website>1</show_in_website>
150
  <show_in_store>1</show_in_store>
@@ -153,7 +171,7 @@
153
  <email_addresses>
154
  <label>Email</label>
155
  <frontend_type>text</frontend_type>
156
- <sort_order>14</sort_order>
157
  <show_in_default>1</show_in_default>
158
  <show_in_website>1</show_in_website>
159
  <show_in_store>1</show_in_store>
@@ -164,44 +182,24 @@
164
  <label>Report after a manual import</label>
165
  <frontend_type>select</frontend_type>
166
  <source_model>adminhtml/system_config_source_yesno</source_model>
167
- <sort_order>15</sort_order>
168
  <show_in_default>1</show_in_default>
169
  <show_in_website>1</show_in_website>
170
  <show_in_store>1</show_in_store>
171
  <depends><enable_reporting>1</enable_reporting></depends>
172
  <comment><![CDATA[Enable this to be sent a report after a manual import has ran.]]></comment>
173
  </after_manual_import>
174
- </fields>
175
- </advanced_settings>
176
- <debug_settings>
177
- <label>Debug Settings</label>
178
- <sort_order>40</sort_order>
179
- <show_in_default>1</show_in_default>
180
- <show_in_website>1</show_in_website>
181
- <show_in_store>1</show_in_store>
182
- <fields>
183
- <enable_debug traslate="label">
184
- <label>Enable Debug</label>
185
- <frontend_type>select</frontend_type>
186
- <source_model>adminhtml/system_config_source_yesno</source_model>
187
- <sort_order>10</sort_order>
188
- <show_in_default>1</show_in_default>
189
- <show_in_website>1</show_in_website>
190
- <show_in_store>1</show_in_store>
191
- <comment><![CDATA[Enable debug mode for select IPs.]]></comment>
192
- </enable_debug>
193
- <debug_ips>
194
- <label>IP Addresses</label>
195
  <frontend_type>text</frontend_type>
196
- <sort_order>20</sort_order>
197
  <show_in_default>1</show_in_default>
198
- <show_in_website>1</show_in_website>
199
- <show_in_store>1</show_in_store>
200
- <depends><enable_debug>1</enable_debug></depends>
201
- <comment>Comma seperated list, blank for all</comment>
202
- </debug_ips>
203
  </fields>
204
- </debug_settings>
205
  </groups>
206
  </seoredirects>
207
  </sections>
140
  <show_in_store>1</show_in_store>
141
  <comment><![CDATA[How much information should be displayed after running an import]]></comment>
142
  </import_log_level>
143
+ <import_status traslate="label">
144
+ <label>Import Status</label>
145
+ <frontend_type>label</frontend_type>
146
+ <sort_order>13</sort_order>
147
+ <show_in_default>1</show_in_default>
148
+ <show_in_website>0</show_in_website>
149
+ <show_in_store>0</show_in_store>
150
+ </import_status>
151
+ <import_unlock translate="label">
152
+ <label>Import Unlock</label>
153
+ <frontend_type>button</frontend_type>
154
+ <sort_order>14</sort_order>
155
+ <frontend_model>zero1_seo_redirects/adminhtml_system_config_importUnlock</frontend_model>
156
+ <show_in_default>1</show_in_default>
157
+ <show_in_website>0</show_in_website>
158
+ <show_in_store>0</show_in_store>
159
+ <comment>Do not use unless you know fully what this does, and understand the consequences.</comment>
160
+ </import_unlock>
161
  <enable_reporting traslate="label">
162
  <label>Enable reporting</label>
163
  <frontend_type>select</frontend_type>
164
  <source_model>adminhtml/system_config_source_yesno</source_model>
165
+ <sort_order>18</sort_order>
166
  <show_in_default>1</show_in_default>
167
  <show_in_website>1</show_in_website>
168
  <show_in_store>1</show_in_store>
171
  <email_addresses>
172
  <label>Email</label>
173
  <frontend_type>text</frontend_type>
174
+ <sort_order>19</sort_order>
175
  <show_in_default>1</show_in_default>
176
  <show_in_website>1</show_in_website>
177
  <show_in_store>1</show_in_store>
182
  <label>Report after a manual import</label>
183
  <frontend_type>select</frontend_type>
184
  <source_model>adminhtml/system_config_source_yesno</source_model>
185
+ <sort_order>20</sort_order>
186
  <show_in_default>1</show_in_default>
187
  <show_in_website>1</show_in_website>
188
  <show_in_store>1</show_in_store>
189
  <depends><enable_reporting>1</enable_reporting></depends>
190
  <comment><![CDATA[Enable this to be sent a report after a manual import has ran.]]></comment>
191
  </after_manual_import>
192
+ <path_to_php>
193
+ <label>Path to php</label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  <frontend_type>text</frontend_type>
195
+ <sort_order>21</sort_order>
196
  <show_in_default>1</show_in_default>
197
+ <show_in_website>0</show_in_website>
198
+ <show_in_store>0</show_in_store>
199
+ <comment>This will only be used if "which php" and "php -v" fail</comment>
200
+ </path_to_php>
 
201
  </fields>
202
+ </advanced_settings>
203
  </groups>
204
  </seoredirects>
205
  </sections>
app/code/community/Zero1/Seoredirects/scripts/import.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once('app/Mage.php');
3
+ Mage::app('admin');
4
+ Mage::setIsDeveloperMode(true);
5
+ ini_set('display_errors', 1);
6
+ error_reporting(E_ALL | E_STRICT);
7
+ umask(0);
8
+ set_time_limit(0);
9
+
10
+ /** @var Zero1_Seoredirects_Model_Importer $importer */
11
+ $importer = Mage::getModel('zero1_seo_redirects/importer');
12
+ $importer->import();
app/code/community/Zero1/Seoredirects/sql/zero1_seoredirects_setup/upgrade-1.1.1-1.1.2.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* @var $installer Mage_Eav_Model_Entity_Setup */
3
+ $installer = $this;
4
+ $table = $installer->getTable('zero1_seo_redirects/redirection');
5
+ /** @var Magento_Db_Adapter_Pdo_Mysql $connection */
6
+ $connection = $installer->getConnection();
7
+ $connection->addColumn($table,
8
+ 'updated_at', array(
9
+ 'type' => Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
10
+ 'nullable' => false,
11
+ 'default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT_UPDATE,
12
+ 'comment' => 'Last Updated Timestamp',
13
+ )
14
+ );
15
+
16
+ /**
17
+ * Create table 'zero1_seoredirects/redirection_import_status'
18
+ */
19
+ $table = $installer->getConnection()
20
+ ->newTable($installer->getTable('zero1_seo_redirects/importStatus'))
21
+ ->addColumn('id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
22
+ 'identity' => true,
23
+ 'unsigned' => true,
24
+ 'nullable' => false,
25
+ 'primary' => true,
26
+ ), 'id')
27
+ ->addColumn('scope', Varien_Db_Ddl_Table::TYPE_TEXT, null, array(
28
+ 'nullable' => false,
29
+ ), 'scope')
30
+ ->addColumn('scope_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
31
+ 'unsigned' => true,
32
+ 'nullable' => false,
33
+ ), 'scope id')
34
+ ->addColumn('to_be_imported', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
35
+ 'unsigned' => true,
36
+ 'nullable' => false,
37
+ ), 'total number to be imported')
38
+ ->addColumn('imported', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
39
+ 'unsigned' => true,
40
+ 'nullable' => false,
41
+ ), 'total number imported')
42
+ ->addColumn('created_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array(
43
+ 'default' => 0,
44
+ ), 'started at')
45
+ ->addColumn('updated_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array(
46
+ 'default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT_UPDATE,
47
+ ), 'updated at');
48
+ $installer->getConnection()->createTable($table);
49
+
50
+ /**
51
+ * Create table 'zero1_seoredirects/redirection_import_log'
52
+ */
53
+ $table = $installer->getConnection()
54
+ ->newTable($installer->getTable('zero1_seo_redirects/importLog'))
55
+ ->addColumn('id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
56
+ 'identity' => true,
57
+ 'unsigned' => true,
58
+ 'nullable' => false,
59
+ 'primary' => true,
60
+ ), 'id')
61
+ ->addColumn('scope', Varien_Db_Ddl_Table::TYPE_TEXT, null, array(
62
+ 'nullable' => false,
63
+ ), 'scope')
64
+ ->addColumn('scope_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
65
+ 'unsigned' => true,
66
+ 'nullable' => false,
67
+ ), 'scope id')
68
+ ->addColumn('severity', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
69
+ 'unsigned' => true,
70
+ 'nullable' => false,
71
+ ), 'severity')
72
+ ->addColumn('line_number', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
73
+ 'unsigned' => true,
74
+ 'nullable' => true,
75
+ ), 'line number')
76
+ ->addColumn('message', Varien_Db_Ddl_Table::TYPE_TEXT, null, array(
77
+ 'nullable' => false,
78
+ ), 'log message')
79
+ ->addColumn('created_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array(
80
+ 'default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT,
81
+ ), 'started at');
82
+ $installer->getConnection()->createTable($table);
83
+
84
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/zero1/seoredirects.xml CHANGED
@@ -31,7 +31,20 @@
31
 
32
  <adminhtml_seoredirects_import_index>
33
  <reference name="content">
34
- <block type="zero1_seo_redirects/adminhtml_import" name="seo_redirects_import" />
 
 
35
  </reference>
36
  </adminhtml_seoredirects_import_index>
 
 
 
 
 
 
 
 
 
 
 
37
  </layout>
31
 
32
  <adminhtml_seoredirects_import_index>
33
  <reference name="content">
34
+ <block type="zero1_seo_redirects/adminhtml_import_status" name="import_status"/>
35
+ <block type="zero1_seo_redirects/adminhtml_import" name="seo_redirects_import"/>
36
+ <block type="zero1_seo_redirects/adminhtml_import_statusSummary" name="import_status_summary"/>
37
  </reference>
38
  </adminhtml_seoredirects_import_index>
39
+
40
+ <adminhtml_seoredirects_importlog_index>
41
+ <reference name="content">
42
+ <block type="zero1_seo_redirects/adminhtml_importLog" name="seoredirects_importLog" />
43
+ </reference>
44
+ </adminhtml_seoredirects_importlog_index>
45
+
46
+ <adminhtml_seoredirects_importlog_grid>
47
+ <update handle="formkey"/>
48
+ <block type="zero1_seo_redirects/adminhtml_importLog_grid" name="seoredirects_importLog.ajax" output="toHtml"/>
49
+ </adminhtml_seoredirects_importlog_grid>
50
  </layout>
app/design/adminhtml/default/default/template/zero1/seoredirects/import/container.phtml CHANGED
@@ -8,4 +8,7 @@
8
  </tr>
9
  </table>
10
  </div>
 
 
 
11
  <div id="report-container"></div>
8
  </tr>
9
  </table>
10
  </div>
11
+ <?php echo $this->getChildHtml('import_status'); ?>
12
+ <?php echo $this->getChildHtml('import_status_summary'); ?>
13
+
14
  <div id="report-container"></div>
app/design/adminhtml/default/default/template/zero1/seoredirects/import/status.phtml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php /* @var $this Zero1_Seoredirects_Block_Adminhtml_Import_Status */ ?>
2
+ <div class="switcher">
3
+ <h4>
4
+ <?php echo $this->__('Status: ').$this->getStatus(); ?>
5
+ </h4>
6
+ </div>
app/design/adminhtml/default/default/template/zero1/seoredirects/import/status_summary.phtml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* @var $this Zero1_Seoredirects_Block_Adminhtml_Import_StatusSummary */
3
+ $collection = $this->getStatusCollection();
4
+
5
+ ?>
6
+ <div class="grid" style="margin-bottom: 50px;">
7
+ <table class="data" cellspacing="0">
8
+ <colgroup>
9
+ <col span="1" style="width: 250px;" />
10
+ <col span="1" />
11
+ <col span="1" style="width: 100px;" />
12
+ <col span="1" style="width: 100px;" />
13
+ </colgroup>
14
+ <thead>
15
+ <tr class="headings">
16
+ <th class="no-link"><span class="nobr"><?php echo Mage::helper('core')->__('Store') ?></span></th>
17
+ <th class="no-link"><span class="nobr"><?php echo Mage::helper('core')->__('Progress') ?></span></th>
18
+ <th class="no-link"><span class="nobr"><?php echo Mage::helper('core')->__('Started At') ?></span></th>
19
+ <th class="no-link"><span class="nobr"><?php echo Mage::helper('core')->__('Updated At') ?></span></th>
20
+ </tr>
21
+ </thead>
22
+ <tbody>
23
+ <?php /** @var $status Zero1_Seoredirects_Model_ImportStatus */ ?>
24
+ <?php foreach($collection as $status): ?>
25
+ <tr class="headings">
26
+ <td class="no-link"><span class="nobr"><?php echo Mage::app()->getStore($status->getScopeId())->getName(); ?></span></td>
27
+ <td class="no-link">
28
+ <?php if(!$status->getToBeImported()): ?>
29
+ <?php echo $this->__('To Be Determined'); ?>
30
+ <?php else: ?>
31
+ <?php $percent = sprintf('%.2f', (($status->getImported() / $status->getToBeImported()) * 100)); ?>
32
+ <div style="white-space: nowrap; overflow-x: visible; background: lightgreen; width: <?php echo $percent; ?>%;">
33
+ (<?php echo $status->getImported(); ?> / <?php echo $status->getToBeImported(); ?>) <?php echo $percent; ?>% complete
34
+ </div>
35
+ <?php endif;?>
36
+ </td>
37
+ <td class="no-link"><span class="nobr"><?php echo $status->getCreatedAt(); ?></span></td>
38
+ <td class="no-link"><span class="nobr"><?php echo $status->getUpdatedAt() ?></span></td>
39
+ </tr>
40
+ <?php endforeach; ?>
41
+ </tbody>
42
+ </table>
43
+ </div>
app/design/adminhtml/default/default/template/zero1/seoredirects/importLog.phtml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="content-header">
2
+ <table cellspacing="0">
3
+ <tr>
4
+ <td style="width:50%;"><h3 class="icon-head head-products"><?php echo Mage::helper('catalog')->__('Manage Redirects') ?></h3></td>
5
+ <td class="a-right">
6
+ <?php echo $this->getButtonsHtml() ?>
7
+ </td>
8
+ </tr>
9
+ </table>
10
+ </div>
11
+ <div>
12
+ <?php echo $this->getGridHtml() ?>
13
+ </div>
app/design/adminhtml/default/default/template/zero1/seoredirects/system/config/import_unlock.phtml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /** @var $this Zero1_Seoredirects_Block_Adminhtml_System_Config_ImportUnlock */
3
+ $dbStatus = $this->getDBImportStatus();
4
+ $osStatus = $this->getTrueImportStatus();
5
+ ?>
6
+ <script type="text/javascript">
7
+ function unlockImport() {
8
+ new Ajax.Request('<?php echo $this->getUnlockUrl() ?>', {
9
+ asynchronous: true
10
+ });
11
+ }
12
+ </script>
13
+
14
+ <?php echo $this->getButtonHtml() ?>
15
+ <div>
16
+ <?php if($dbStatus == $osStatus): ?>
17
+ <b><?php echo $this->__('Statuses agree'); ?></b>
18
+ <?php elseif($dbStatus == Zero1_Seoredirects_Model_Importer::RUNLOCK_NOT_RUNNING && $osStatus == Zero1_Seoredirects_Model_Importer::RUNLOCK_NOT_RUNNING): ?>
19
+ <b><?php echo $this->__('This may be a time to use the button'); ?></b>
20
+ <?php else: ?>
21
+ <b><?php echo $this->__('Not a valid time to use the button'); ?></b>
22
+ <?php endif; ?>
23
+ </div>
24
+
package.xml CHANGED
@@ -1,31 +1,19 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Zero1_Seoredirects</name>
4
- <version>1.1.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://shop.zero1.co.uk/LICENSE.txt">Commercial</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Manage you SEO redirects using a Google Doc or and Uploaded File.</summary>
10
  <description>Manage you SEO redirects using a Google Doc or and Uploaded File.</description>
11
- <notes>Upgrade from 1.0.X&#xD;
12
- - Add From Types&#xD;
13
- - Added the ability to persist query&#xD;
14
- - Add the ability to automatically ignore query variables&#xD;
15
- - Reworked import process.&#xD;
16
- - Add the ability to log 404s automatically&#xD;
17
- - Made the redirect key global&#xD;
18
- - Import files are now locked to store scope.&#xD;
19
- - Added redirection summary to view page.&#xD;
20
- - Added reporting options&#xD;
21
- - Added url caching feature, to improve performance.&#xD;
22
- - Added the ability to import a google doc as HTML or CSV&#xD;
23
- - Added the ability to manage redirects from a gid page (add, edit, delete, mass delete, export)&#xD;
24
- - Added Hit counter.</notes>
25
  <authors><author><name>Arron Moss</name><user>zero1limited</user><email>arron.moss@zero1.co.uk</email></author></authors>
26
- <date>2015-04-09</date>
27
- <time>10:19:39</time>
28
- <contents><target name="magecommunity"><dir name="Zero1"><dir name="Seoredirects"><dir name="Block"><dir name="Adminhtml"><dir name="Edit"><file name="Form.php" hash="e5c46b2102e4a9af2a563a19ed462b86"/></dir><file name="Edit.php" hash="8e5eb2ce884f2db36842d17ba9e7a9af"/><dir name="Import"><file name="Report.php" hash="0d26c2b8f8fecd8ba4326d2b11cef1f5"/></dir><file name="Import.php" hash="c19209bfcf6c495deb7b8711ec243e04"/><dir name="Manage"><dir name="Grid"><dir name="Renderer"><file name="Options.php" hash="81156ac356044306cf8a11608afe764a"/><file name="Url.php" hash="c4208700f3531082c72dc4efd6b4a4af"/></dir></dir><file name="Grid.php" hash="f2867600450f3fb577735052110c6cf0"/><file name="Report.php" hash="8ea23cee5ff2988cd4894b69f5676359"/></dir><file name="Manage.php" hash="8e019efa0d59c78b405acf7e74b6e7ee"/><dir name="Settings"><file name="Params.php" hash="87ed9af2d9c11c791988544b7a49c404"/></dir><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="File.php" hash="138093538cccbea31434aacb40fbce1e"/></dir><file name="Field.php" hash="23167e787e4c3692dea5c54ad8cc5fa6"/></dir><file name="Form.php" hash="6d3f19bdd5d6bce464f749eacb6b917d"/></dir></dir></dir></dir><file name="Exception.php" hash="bd003aafc41afb3de920e4a4fbb58dc2"/><dir name="Helper"><file name="Data.php" hash="424e5675964cd1287ef50a270ad63e75"/><file name="Files.php" hash="1a34ab122975730bf44ed4d128c590ac"/><file name="Hints.php" hash="2a3fc3984d10c680dd113b4df0cffaaf"/><file name="License.php" hash="eb24338369084cd47fdaea4b30d697c5"/><file name="Urls.php" hash="685e8c0ca20f897905240905a993684b"/></dir><dir name="Model"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Backend"><file name="File.php" hash="be9bc739028fa9af06fc45235ba4b551"/><file name="Number.php" hash="e21d15ea0eac997b93ea2de45b0fb777"/></dir><dir name="Source"><file name="LogLevels.php" hash="767d3f90a070e1fccdc3f7349516385f"/></dir></dir></dir></dir><file name="File.php" hash="9ebec42806237689d91a389f82a092d3"/><file name="Importer.php" hash="a3bc257d20f99223dadfae67ae2b0d6d"/><file name="Observer.php" hash="17e1298598834a3b7a784f99e7749447"/><dir name="Redirection"><file name="Cache.php" hash="6bcd1757d36f00c5dff1edacd064cdb3"/></dir><file name="Redirection.php" hash="e1d674a25acabd697191f2412bc6cb8b"/><file name="Redirector.php" hash="694b59ce5f60ad2552b899036dced695"/><dir name="Resource"><dir name="Redirection"><dir name="Cache"><file name="Collection.php" hash="4a5438247157f2262fb6c9ade0ef452d"/></dir><file name="Cache.php" hash="5da3db53f90cc665ec372d471db6ed4a"/><file name="Collection.php" hash="5c4f92128b58ede4c0709f452be0709e"/></dir><file name="Redirection.php" hash="43971cae6be73c8be9af886304dac4b6"/></dir></dir><file name="TODO.txt" hash="cd72a0ba8dd2e9c3bdd7cbacdc5d0a04"/><dir name="controllers"><dir name="Adminhtml"><dir name="Seoredirects"><file name="ConfigController.php" hash="263aee27d04fc1326a5a826ce71e9005"/><file name="ImportController.php" hash="89902a8e4dcdde002d8d8e6f25b11556"/><file name="ManageController.php" hash="ba77329cf88d3566429c20e309399ca4"/></dir></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="f2fdfb040bcf0b0a4a23f4dd7d1eacdd"/><file name="config.xml" hash="b326841b9c3b961321354e5665a07f70"/><file name="system.xml" hash="7fefbdaa8fb4697609bd54945d35bc03"/></dir><dir name="sql"><dir name="zero1_seoredirects_setup"><file name="install-1.1.0.php" hash="b508de10922d332b296bc6a90da2170f"/><file name="upgrade-1.1.0-1.1.1.php" hash="b853472314a81c0914b91af9ff3e7f6e"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Zero1_Seoredirects.xml" hash="7894f7794de7240b9bb65384e846a585"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="zero1"><file name="seoredirects.xml" hash="e6be6b7de008d5fd58c1bdc82ee20111"/></dir></dir><dir name="template"><dir name="zero1"><dir name="seoredirects"><file name="edit.phtml" hash="85c0a991007e22ed6ac859b8a08b6a56"/><dir name="import"><file name="container.phtml" hash="ac15394e738869520e333e96290b3e4f"/><file name="report.phtml" hash="8eb36402e30f7fbf58374d4139423246"/></dir><dir name="manage"><file name="report.phtml" hash="0afdc7ef9471e9fb6d69fc97d9a429ea"/></dir><file name="manage.phtml" hash="618639a7e5bba02c21d189e0add457c6"/></dir></dir></dir></dir></dir></dir></target><target name="mage"><dir name="var"><dir name="Zero1"><dir name="SeoRedirects"><dir name="data"><file name="template.csv" hash="8dcfaf8a9de77b2c479de12f504ce379"/></dir></dir></dir></dir></target></contents>
29
  <compatible/>
30
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
31
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Zero1_Seoredirects</name>
4
+ <version>1.1.9</version>
5
  <stability>stable</stability>
6
  <license uri="http://shop.zero1.co.uk/LICENSE.txt">Commercial</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Manage you SEO redirects using a Google Doc or and Uploaded File.</summary>
10
  <description>Manage you SEO redirects using a Google Doc or and Uploaded File.</description>
11
+ <notes>- added fix for persist query issue&#xD;
12
+ - added fix for https:// / http:// redirect caching issue</notes>
 
 
 
 
 
 
 
 
 
 
 
 
13
  <authors><author><name>Arron Moss</name><user>zero1limited</user><email>arron.moss@zero1.co.uk</email></author></authors>
14
+ <date>2016-08-31</date>
15
+ <time>09:08:00</time>
16
+ <contents><target name="magecommunity"><dir name="Zero1"><dir name="Seoredirects"><dir name="Block"><dir name="Adminhtml"><dir name="Edit"><file name="Form.php" hash="e5c46b2102e4a9af2a563a19ed462b86"/></dir><file name="Edit.php" hash="8e5eb2ce884f2db36842d17ba9e7a9af"/><dir name="Import"><file name="Report.php" hash="0d26c2b8f8fecd8ba4326d2b11cef1f5"/><file name="Status.php" hash="8f02c3cad0964e558ef87c0b248a4c1a"/><file name="StatusSummary.php" hash="10c8a26b760f879ffde1aaaacef1a762"/></dir><file name="Import.php" hash="b991ca3ebfc32fd6e0c33e35d856f830"/><dir name="ImportLog"><file name="Grid.php" hash="2e8c8aa86f38829187996d7768a1d1e1"/></dir><file name="ImportLog.php" hash="dc764c6793f4ec9003de627371bfe823"/><dir name="Manage"><dir name="Grid"><dir name="Renderer"><file name="Options.php" hash="81156ac356044306cf8a11608afe764a"/><file name="Url.php" hash="c4208700f3531082c72dc4efd6b4a4af"/></dir></dir><file name="Grid.php" hash="6559d6b87f9a7167fcdb531f2b245dbd"/><file name="Report.php" hash="2b33db72d15efbd6f452f792f90be7e9"/></dir><file name="Manage.php" hash="fef0a7bc9882b7df2fbc3dabe9766515"/><dir name="Settings"><file name="Params.php" hash="87ed9af2d9c11c791988544b7a49c404"/></dir><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="File.php" hash="138093538cccbea31434aacb40fbce1e"/></dir><file name="Field.php" hash="23167e787e4c3692dea5c54ad8cc5fa6"/></dir><file name="Form.php" hash="6d3f19bdd5d6bce464f749eacb6b917d"/><file name="ImportUnlock.php" hash="832d9ba2674b871c07bba2e9fc34653a"/></dir></dir></dir></dir><file name="Exception.php" hash="bd003aafc41afb3de920e4a4fbb58dc2"/><dir name="Helper"><file name="Data.php" hash="6839585d8507036d4c86d92f56d913ef"/><file name="Files.php" hash="1a34ab122975730bf44ed4d128c590ac"/><file name="Hints.php" hash="2a3fc3984d10c680dd113b4df0cffaaf"/><file name="License.php" hash="83818647c50413a003029254098b5588"/><file name="Urls.php" hash="6df70eb6520cf586ac693d3ee48a7ac2"/></dir><dir name="Model"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Backend"><file name="File.php" hash="be9bc739028fa9af06fc45235ba4b551"/><file name="Number.php" hash="e21d15ea0eac997b93ea2de45b0fb777"/></dir><dir name="Source"><file name="LogLevels.php" hash="767d3f90a070e1fccdc3f7349516385f"/></dir></dir></dir></dir><file name="File.php" hash="9ebec42806237689d91a389f82a092d3"/><file name="ImportLog.php" hash="a2634a88451085cd30954c9f76772e36"/><file name="ImportStatus.php" hash="67559ddb026598c2f36c31f7cfb53c6f"/><dir name="Importer"><file name="Abstract.php" hash="27c90772740387c9a5e893641f64fa1e"/><file name="Google.php" hash="1a352d5e227cb07e380e4eb3a7a47d9b"/><file name="Local.php" hash="162edd998e422cd13aaba538745ef576"/></dir><file name="Importer.php" hash="eea34f4e0f6ba5a2bd8734771aafdff8"/><file name="Observer.php" hash="ae1312fdef59244409d3e97c960afa47"/><file name="Redirecter.php" hash="7a9a6ca11b6f4338328ff8fa9b8c68ed"/><dir name="Redirection"><file name="Cache.php" hash="6bcd1757d36f00c5dff1edacd064cdb3"/></dir><file name="Redirection.php" hash="dd2c04cdfe7af4eb918dae7a0a7c3c36"/><file name="RedirectionValidator.php" hash="aca7225b48044d24970bcf06b2a67345"/><file name="Redirector.php" hash="b20eea433ffa8248e147e2eb235894f0"/><dir name="Resource"><dir name="ImportLog"><file name="Collection.php" hash="3429d85bf40d06c456d04ed239cc570b"/></dir><file name="ImportLog.php" hash="8de052e664f7b67cfbad82a6df0429eb"/><dir name="ImportStatus"><file name="Collection.php" hash="2ed1fccb4088a7eb279c75879f4f5d33"/></dir><file name="ImportStatus.php" hash="b47c530e2729b98afdb3901fd8961b10"/><dir name="Redirection"><dir name="Cache"><file name="Collection.php" hash="4a5438247157f2262fb6c9ade0ef452d"/></dir><file name="Cache.php" hash="5da3db53f90cc665ec372d471db6ed4a"/><file name="Collection.php" hash="5c4f92128b58ede4c0709f452be0709e"/></dir><file name="Redirection.php" hash="03de306b256da1b75368599ffa0d7c0f"/></dir><file name="Url.php" hash="d49aa40787c7a5c9315511d6a0eec370"/><file name="UrlFactory.php" hash="98d41270407bcebd57843fb4d83b0ce0"/></dir><file name="README.md" hash="2691121d7e39deba94b03a6df89362d8"/><file name="TODO.txt" hash="cd72a0ba8dd2e9c3bdd7cbacdc5d0a04"/><dir name="controllers"><dir name="Adminhtml"><dir name="Seoredirects"><file name="ConfigController.php" hash="263aee27d04fc1326a5a826ce71e9005"/><file name="ImportController.php" hash="6fe5e48cdab99062e89a2fead020991b"/><file name="ImportLogController.php" hash="9facb06aaf8c6e1478833435dd6b56e6"/><file name="ManageController.php" hash="a6d9a2b5ee82fa0f5217995dd89ab1fb"/></dir></dir></dir><dir name="docs"><dir name="tests"><dir><file name="0.md" hash="d1693c61a35a06ea26c97e647f86a665"/></dir><dir name="1"><file name="0.md" hash="973478961a13583bab1fa40161ca6168"/></dir><dir name="2"><file name="0.md" hash="6e4c5e76e226f7d979a316871aa4d45f"/></dir></dir><file name="tests.md" hash="d5637ef610ca975ae49d746ddfba860c"/></dir><dir name="etc"><file name="adminhtml.xml" hash="3a06c810d96d7d3eef803d64a601152e"/><file name="config.xml" hash="9adf354a5fb77a651373e20dffa812f0"/><file name="system.xml" hash="577cbd6e9c0b69fbdb7fac837cc3c6f3"/></dir><dir name="scripts"><file name="import.php" hash="380a3c6b145a98966f24788370b53ec4"/></dir><dir name="sql"><dir name="zero1_seoredirects_setup"><file name="install-1.1.0.php" hash="b508de10922d332b296bc6a90da2170f"/><file name="upgrade-1.1.0-1.1.1.php" hash="b853472314a81c0914b91af9ff3e7f6e"/><file name="upgrade-1.1.1-1.1.2.php" hash="3b6b401940105906db8e7d35180e9e9d"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Zero1_Seoredirects.xml" hash="7894f7794de7240b9bb65384e846a585"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="zero1"><file name="seoredirects.xml" hash="9ede48b275f7b3544585ce653d27c845"/></dir></dir><dir name="template"><dir name="zero1"><dir name="seoredirects"><file name="edit.phtml" hash="85c0a991007e22ed6ac859b8a08b6a56"/><dir name="import"><file name="container.phtml" hash="877db339c1b5592b9d65bdd9c2f0026d"/><file name="report.phtml" hash="8eb36402e30f7fbf58374d4139423246"/><file name="status.phtml" hash="a8fb00fa1c6e95c81fdf3363e27e1bae"/><file name="status_summary.phtml" hash="a6aac997828bb258bd0ae3ceb58594a1"/></dir><file name="importLog.phtml" hash="b63130e8b0a3ed3c0cd26a043d1bbf0c"/><dir name="manage"><file name="report.phtml" hash="0afdc7ef9471e9fb6d69fc97d9a429ea"/></dir><file name="manage.phtml" hash="618639a7e5bba02c21d189e0add457c6"/><dir name="system"><dir name="config"><file name="import_unlock.phtml" hash="e51107c43ebb51a02d62a0df7c29b2b8"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mage"><dir name="var"><dir name="Zero1"><dir name="SeoRedirects"><dir name="data"><file name="template.csv" hash="8dcfaf8a9de77b2c479de12f504ce379"/></dir></dir></dir></dir></target></contents>
17
  <compatible/>
18
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
19
  </package>