SafeMage_Plugin - Version 1.0.0

Version Notes

Initial Release

Download this release

Release Info

Developer SafeMage
Extension SafeMage_Plugin
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

app/code/community/SafeMage/Plugin/Block/Adminhtml/System/Plugin.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SafeMage_Plugin_Block_Adminhtml_System_Plugin extends Mage_Adminhtml_Block_System_Config_Form_Fieldset
3
+ {
4
+ protected function _getFooterHtml($element)
5
+ {
6
+ $tooltipsExist = false;
7
+ $html = '</tbody></table>';
8
+ $html .= '<div class="comment" align="right" style="font-size: 15px; width: 660px">' .
9
+ 'Visit ' .
10
+ '<a href="http://www.safemage.com/function-plugins-for-magento-1.html" target="_blank">' .
11
+ 'Function Plugins'.
12
+ '</a> for additional information.'.
13
+ '<br>Powered by ' .
14
+ '<a href="http://www.safemage.com/" target="_blank">' .
15
+ '<img src="http://www.safemage.com/cache/plugin/logo.png" height="17" alt="SafeMage" title=" " />' .
16
+ '</a>' .
17
+ '</div>';
18
+ $html .= '</fieldset>' . $this->_getExtraJs($element, $tooltipsExist);
19
+
20
+ if ($element->getIsNested()) {
21
+ $html .= '</div></td></tr>';
22
+ } else {
23
+ $html .= '</div>';
24
+ }
25
+ return $html;
26
+ }
27
+ }
app/code/community/SafeMage/Plugin/Block/Adminhtml/System/Plugin/List.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SafeMage_Plugin_Block_Adminhtml_System_Plugin_List extends Mage_Adminhtml_Block_System_Config_Form_Field
3
+ {
4
+ public function render(Varien_Data_Form_Element_Abstract $element)
5
+ {
6
+ $id = $element->getHtmlId();
7
+ $html = '<td class="label"><label for="'.$id.'">'.$element->getLabel().'</label></td>';
8
+ $html .= '<td class="value" colspan="3">';
9
+ $html .= $this->_getElementHtml($element);
10
+ $html.= '</td>';
11
+
12
+ return $this->_decorateRowHtml($element, $html);
13
+ }
14
+
15
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
16
+ {
17
+ $source = '';
18
+ switch ($element->getId()) {
19
+ case 'system_plugin_block_plugins':
20
+ $source = 'blocks';
21
+ break;
22
+ case 'system_plugin_helper_plugins':
23
+ $source = 'helpers';
24
+ break;
25
+ case 'system_plugin_model_plugins':
26
+ $source = 'models';
27
+ break;
28
+ }
29
+
30
+ if (!$source) {
31
+ return '';
32
+ }
33
+
34
+ $pluginsList = Mage::helper('safemage_plugin')->getPluginsList($source);
35
+
36
+ if ($pluginsList) {
37
+ $html = '';
38
+ foreach($pluginsList as $class => $methods) {
39
+
40
+ foreach($methods as $method => $types) {
41
+ $html .= '<div style="padding-bottom: 6px">';
42
+ $html .= '<strong>' . $class . '::' . $method . '</strong>';
43
+ $html .= '<table width="365" bordercolor="#D6D6D6" border="1" cellpadding="1" cellspacing="1"'.
44
+ ' style="border-collapse: collapse">';
45
+ $html .= '<tr>';
46
+ $html .= '<td align="center" width="43"><small>' . $this->__('Type') . '</small></td>';
47
+ $html .= '<td align="center" width="27"><small>' . $this->__('Sort') . '</small></td>';
48
+ $html .= '<td align="center"><small>' . $this->__('Name / Run') . '</small></td>';
49
+ $html .= '</tr>';
50
+ foreach($types as $type => $plugins) {
51
+ $html .= '<tr>';
52
+ $html .= '<td align="center" rowspan="' . count($plugins) .
53
+ '" style="vertical-align: middle; font-size: 13px;">' . $type . '</td>';
54
+ foreach($plugins as $index => $data) {
55
+ if ($index > 0) {
56
+ $html .= '<tr>';
57
+ }
58
+ $html .= '<td align="center" style="vertical-align: middle">' .
59
+ $data['sort_order'] . '</td>';
60
+ $html .= '<td class="nowrap" style="padding: 0 2px">' .
61
+ $data['name'] . '<br>' . $data['run'] . '</td>';
62
+
63
+ if ($index > 0) {
64
+ $html .= '</tr>';
65
+ }
66
+ }
67
+ $html .= '</tr>';
68
+ }
69
+
70
+ $html .= '</table>';
71
+ $html .= '</div>';
72
+ }
73
+ }
74
+ } else {
75
+ $html = $this->__('None');
76
+ }
77
+
78
+ return '<div id="' . $element->getHtmlId() . '">'. $html . '</div>';
79
+ }
80
+
81
+ /**
82
+ * Decorate field row html
83
+ *
84
+ * @param Varien_Data_Form_Element_Abstract $element
85
+ * @param string $html
86
+ * @return string
87
+ */
88
+ protected function _decorateRowHtml($element, $html)
89
+ {
90
+ return '<tr id="row_' . $element->getHtmlId() . '">' . $html . '</tr>';
91
+ }
92
+ }
app/code/community/SafeMage/Plugin/Helper/Data.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SafeMage_Plugin_Helper_Data extends Mage_Core_Helper_Abstract
3
+ {
4
+ /**
5
+ * @return bool|int
6
+ */
7
+ public function checkWritablePluginsDir()
8
+ {
9
+ $file = SafeMage_Plugin_File::getDir() . 'test.txt';
10
+ $io = new Varien_Io_File();
11
+ $result = $io->write($file, 'test');
12
+ if ($result) {
13
+ $result = $io->rm($file);
14
+ }
15
+ $io->close();
16
+ return $result;
17
+ }
18
+
19
+ /**
20
+ * @param $source string ('blocks', 'helpers', 'models')
21
+ * @return array
22
+ */
23
+ public function getPluginsList($source)
24
+ {
25
+ if (!$source) {
26
+ return array();
27
+ }
28
+
29
+ $config = Mage::getConfig()->getNode('global/' . $source);
30
+ $pluginsList = array();
31
+
32
+ foreach($config->children() as $module) {
33
+ foreach($module->children() as $section) {
34
+ if ($section->getName() == 'plugin') {
35
+ foreach($section->children() as $class) {
36
+ foreach ($class as $plugin) {
37
+ $data = $plugin->asArray();
38
+ if (isset($data['method']) && $data['method'] &&
39
+ isset($data['type']) &&
40
+ (
41
+ $data['type'] == SafeMage_Plugin::TYPE_BEFORE ||
42
+ $data['type'] == SafeMage_Plugin::TYPE_AROUND ||
43
+ $data['type'] == SafeMage_Plugin::TYPE_AFTER
44
+ ) && isset($data['run']) && $data['run']
45
+ && (!isset($data['disabled']) || !$data['disabled'])
46
+ ) {
47
+ $sortOrder = 0;
48
+ if (isset($data['sort_order'])) {
49
+ $sortOrder = intval($data['sort_order']);
50
+ }
51
+ $pluginsList[$module->getName() . '/' . $class->getName()][$data['method']][$data['type']][] =
52
+ array(
53
+ 'name' => $plugin->getName(),
54
+ 'run' => $data['run'],
55
+ 'sort_order' => $sortOrder
56
+ );
57
+ }
58
+ }
59
+ }
60
+ }
61
+
62
+ }
63
+ }
64
+
65
+ foreach($pluginsList as &$methods) {
66
+ foreach($methods as &$types) {
67
+ uasort($types, array($this, '_sortByType'));
68
+ foreach($types as &$plugins) {
69
+ usort($plugins, array($this, '_sortByOrder'));
70
+ }
71
+ }
72
+ }
73
+
74
+ return $pluginsList;
75
+ }
76
+
77
+ protected function _sortByType($data1, $data2)
78
+ {
79
+ if (isset($data1[SafeMage_Plugin::TYPE_AROUND]) && isset($data2[SafeMage_Plugin::TYPE_BEFORE])) {
80
+ return true;
81
+ }
82
+
83
+ if (isset($data1[SafeMage_Plugin::TYPE_AFTER])
84
+ && (isset($data2[SafeMage_Plugin::TYPE_BEFORE]) || isset($data2[SafeMage_Plugin::TYPE_AROUND]))
85
+ ) {
86
+ return true;
87
+ }
88
+
89
+ return false;
90
+ }
91
+
92
+ protected function _sortByOrder($data1, $data2)
93
+ {
94
+ return ($data1['sort_order'] > $data2['sort_order'] ? true : false);
95
+ }
96
+ }
app/code/community/SafeMage/Plugin/Model/Observer.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SafeMage_Plugin_Model_Observer
3
+ {
4
+ public function adminCacheRefreshType(Varien_Event_Observer $observer)
5
+ {
6
+ $type = $observer->getEvent()->getType();
7
+ if ($type == 'config') {
8
+ $this->_flushPluginCache();
9
+ }
10
+ }
11
+
12
+ public function adminCacheFlushAll(Varien_Event_Observer $observer)
13
+ {
14
+ $this->_flushPluginCache();
15
+ }
16
+
17
+ public function adminCacheFlushSystem(Varien_Event_Observer $observer)
18
+ {
19
+ $this->_flushPluginCache();
20
+ }
21
+
22
+ protected function _flushPluginCache()
23
+ {
24
+ $io = new Varien_Io_File();
25
+ if (!$io->rmdir(SafeMage_Plugin_File::getDir(), true)) {
26
+ $this->_addWriteError();
27
+ }
28
+ }
29
+
30
+ public function checkWritablePluginsDir($observer)
31
+ {
32
+ $request = $observer->getControllerAction()->getRequest();
33
+ $currentSection = $request->getParam('section');
34
+ if ($currentSection == 'system' && !Mage::helper('safemage_plugin')->checkWritablePluginsDir()) {
35
+ $this->_addWriteError();
36
+ }
37
+ }
38
+
39
+ private function _addWriteError()
40
+ {
41
+ Mage::getSingleton('adminhtml/session')->addError(
42
+ Mage::helper('safemage_plugin')->__(
43
+ 'Folder does not have write permissions: %s',
44
+ SafeMage_Plugin_File::getDir()
45
+ )
46
+ );
47
+ }
48
+ }
app/code/community/SafeMage/Plugin/Model/Plugin.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SafeMage_Plugin_Model_Plugin
3
+ {
4
+ /**
5
+ * @param Mage_Core_Model_Layout $object
6
+ * @param array $arguments
7
+ * @return obj
8
+ * @throws Mage_Core_Exception
9
+ */
10
+ public function aroundGetBlockInstance(obj $object, array $arguments)
11
+ {
12
+ list($block, $attributes) = $arguments;
13
+
14
+ if (is_string($block)) {
15
+ if (strpos($block, '/')!==false) {
16
+ if (!$block = Mage::getConfig()->getBlockClassName($block)) {
17
+ Mage::throwException(Mage::helper('core')->__('Invalid block type: %s', $block));
18
+ }
19
+ }
20
+ if (class_exists($block) || mageFindClassFile($block)) {
21
+ $block = new $block($attributes);
22
+ }
23
+ }
24
+ if (!$block instanceof Mage_Core_Block_Abstract) {
25
+ Mage::throwException(Mage::helper('core')->__('Invalid block type: %s', $block));
26
+ }
27
+ return $block;
28
+ }
29
+ }
app/code/community/SafeMage/Plugin/etc/config.xml ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <SafeMage_Plugin>
5
+ <version>1.0.0</version>
6
+ </SafeMage_Plugin>
7
+ </modules>
8
+ <adminhtml>
9
+ <events>
10
+ <adminhtml_cache_refresh_type>
11
+ <observers>
12
+ <safemage_plugin>
13
+ <class>safemage_plugin/observer</class>
14
+ <method>adminCacheRefreshType</method>
15
+ </safemage_plugin>
16
+ </observers>
17
+ </adminhtml_cache_refresh_type>
18
+ <adminhtml_cache_flush_all>
19
+ <observers>
20
+ <safemage_plugin>
21
+ <class>safemage_plugin/observer</class>
22
+ <method>adminCacheFlushAll</method>
23
+ </safemage_plugin>
24
+ </observers>
25
+ </adminhtml_cache_flush_all>
26
+ <adminhtml_cache_flush_system>
27
+ <observers>
28
+ <safemage_plugin>
29
+ <class>safemage_plugin/observer</class>
30
+ <method>adminCacheFlushSystem</method>
31
+ </safemage_plugin>
32
+ </observers>
33
+ </adminhtml_cache_flush_system>
34
+ <controller_action_predispatch_adminhtml_system_config_edit>
35
+ <observers>
36
+ <safemage_plugin>
37
+ <class>safemage_plugin/observer</class>
38
+ <method>checkWritablePluginsDir</method>
39
+ </safemage_plugin>
40
+ </observers>
41
+ </controller_action_predispatch_adminhtml_system_config_edit>
42
+ </events>
43
+ <translate>
44
+ <modules>
45
+ <SafeMage_Plugin>
46
+ <files>
47
+ <default>SafeMage_Plugin.csv</default>
48
+ </files>
49
+ </SafeMage_Plugin>
50
+ </modules>
51
+ </translate>
52
+ </adminhtml>
53
+ <global>
54
+ <blocks>
55
+ <safemage_plugin>
56
+ <class>SafeMage_Plugin_Block</class>
57
+ </safemage_plugin>
58
+ </blocks>
59
+ <helpers>
60
+ <safemage_plugin>
61
+ <class>SafeMage_Plugin_Helper</class>
62
+ </safemage_plugin>
63
+ </helpers>
64
+ <models>
65
+ <safemage_plugin>
66
+ <class>SafeMage_Plugin_Model</class>
67
+ </safemage_plugin>
68
+ <core>
69
+ <plugin>
70
+ <layout>
71
+ <safemage_plugin_set_data_around>
72
+ <type>around</type>
73
+ <method>_getBlockInstance</method>
74
+ <run>safemage_plugin/plugin::aroundGetBlockInstance</run>
75
+ <sort_order>10</sort_order>
76
+ </safemage_plugin_set_data_around>
77
+ </layout>
78
+ </plugin>
79
+ </core>
80
+ </models>
81
+ </global>
82
+ <default>
83
+ <system>
84
+ <plugin>
85
+ <enabled>1</enabled>
86
+ </plugin>
87
+ </system>
88
+ </default>
89
+ </config>
app/code/community/SafeMage/Plugin/etc/system.xml ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <sections>
4
+ <system>
5
+ <groups>
6
+ <plugin translate="label comment">
7
+ <label>Plugins (Interceptors)</label>
8
+ <frontend_type>text</frontend_type>
9
+ <frontend_model>safemage_plugin/adminhtml_system_plugin</frontend_model>
10
+ <sort_order>1000</sort_order>
11
+ <show_in_default>1</show_in_default>
12
+ <show_in_website>0</show_in_website>
13
+ <show_in_store>0</show_in_store>
14
+ <fields>
15
+ <enabled translate="label">
16
+ <label>Enable</label>
17
+ <frontend_type>select</frontend_type>
18
+ <source_model>adminhtml/system_config_source_yesno</source_model>
19
+ <sort_order>10</sort_order>
20
+ <show_in_default>1</show_in_default>
21
+ <show_in_website>0</show_in_website>
22
+ <show_in_store>0</show_in_store>
23
+ </enabled>
24
+ <block_plugins translate="label">
25
+ <label>Block Plugins</label>
26
+ <frontend_type>text</frontend_type>
27
+ <frontend_model>safemage_plugin/adminhtml_system_plugin_list</frontend_model>
28
+ <sort_order>20</sort_order>
29
+ <show_in_default>1</show_in_default>
30
+ <show_in_website>0</show_in_website>
31
+ <show_in_store>0</show_in_store>
32
+ <depends>
33
+ <enabled>1</enabled>
34
+ </depends>
35
+ </block_plugins>
36
+ <helper_plugins translate="label">
37
+ <label>Helper Plugins</label>
38
+ <frontend_type>text</frontend_type>
39
+ <frontend_model>safemage_plugin/adminhtml_system_plugin_list</frontend_model>
40
+ <sort_order>30</sort_order>
41
+ <show_in_default>1</show_in_default>
42
+ <show_in_website>0</show_in_website>
43
+ <show_in_store>0</show_in_store>
44
+ <depends>
45
+ <enabled>1</enabled>
46
+ </depends>
47
+ </helper_plugins>
48
+ <model_plugins translate="label">
49
+ <label>Model Plugins</label>
50
+ <frontend_type>text</frontend_type>
51
+ <frontend_model>safemage_plugin/adminhtml_system_plugin_list</frontend_model>
52
+ <sort_order>40</sort_order>
53
+ <show_in_default>1</show_in_default>
54
+ <show_in_website>0</show_in_website>
55
+ <show_in_store>0</show_in_store>
56
+ <depends>
57
+ <enabled>1</enabled>
58
+ </depends>
59
+ </model_plugins>
60
+ </fields>
61
+ </plugin>
62
+ </groups>
63
+ </system>
64
+ </sections>
65
+ </config>
app/code/local/Mage/Core/Model/Config.php ADDED
@@ -0,0 +1,1698 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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@magento.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.magento.com for more information.
20
+ *
21
+ * @category Mage
22
+ * @package Mage_Core
23
+ * @copyright Copyright (c) 2006-2016 X.commerce, Inc. and affiliates (http://www.magento.com)
24
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25
+ */
26
+
27
+
28
+ /**
29
+ * Core configuration class
30
+ *
31
+ * @category Mage
32
+ * @package Mage_Core
33
+ * @author Magento Core Team <core@magentocommerce.com>
34
+ */
35
+ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
36
+ {
37
+ const CACHE_TAG = 'CONFIG';
38
+
39
+ /**
40
+ * Flag which allow use cache logic
41
+ *
42
+ * @var bool
43
+ */
44
+ protected $_useCache = false;
45
+
46
+ /**
47
+ * Instructions for spitting config cache
48
+ * array(
49
+ * $sectionName => $recursionLevel
50
+ * )
51
+ * Recursion level provide availability cache subnodes separatly
52
+ *
53
+ * @var array
54
+ */
55
+ protected $_cacheSections = array(
56
+ 'admin' => 0,
57
+ 'adminhtml' => 0,
58
+ 'crontab' => 0,
59
+ 'install' => 0,
60
+ 'stores' => 1,
61
+ 'websites' => 0
62
+ );
63
+
64
+ /**
65
+ * Loaded Configuration by cached sections
66
+ *
67
+ * @var array
68
+ */
69
+ protected $_cacheLoadedSections = array();
70
+
71
+ /**
72
+ * Configuration options
73
+ *
74
+ * @var Mage_Core_Model_Config_Options
75
+ */
76
+ protected $_options;
77
+
78
+ /**
79
+ * Storage for generated class names
80
+ *
81
+ * @var array
82
+ */
83
+ protected $_classNameCache = array();
84
+
85
+ /**
86
+ * Storage for generated block class names
87
+ *
88
+ * @var unknown_type
89
+ */
90
+ protected $_blockClassNameCache = array();
91
+
92
+ /**
93
+ * Storage of validated secure urls
94
+ *
95
+ * @var array
96
+ */
97
+ protected $_secureUrlCache = array();
98
+
99
+ /**
100
+ * System environment server variables
101
+ *
102
+ * @var array
103
+ */
104
+ protected $_distroServerVars;
105
+
106
+ /**
107
+ * Array which is using for replace placeholders of server variables
108
+ *
109
+ * @var array
110
+ */
111
+ protected $_substServerVars;
112
+
113
+ /**
114
+ * Resource model
115
+ * Used for operations with DB
116
+ *
117
+ * @var Mage_Core_Model_Mysql4_Config
118
+ */
119
+ protected $_resourceModel;
120
+
121
+ /**
122
+ * Configuration for events by area
123
+ *
124
+ * @var array
125
+ */
126
+ protected $_eventAreas;
127
+
128
+ /**
129
+ * Flag cache for existing or already created directories
130
+ *
131
+ * @var array
132
+ */
133
+ protected $_dirExists = array();
134
+
135
+ /**
136
+ * Flach which allow using cache for config initialization
137
+ *
138
+ * @var bool
139
+ */
140
+ protected $_allowCacheForInit = true;
141
+
142
+ /**
143
+ * Property used during cache save process
144
+ *
145
+ * @var array
146
+ */
147
+ protected $_cachePartsForSave = array();
148
+
149
+ /**
150
+ * Empty configuration object for loading and megring configuration parts
151
+ *
152
+ * @var Mage_Core_Model_Config_Base
153
+ */
154
+ protected $_prototype;
155
+
156
+ /**
157
+ * Flag which identify what local configuration is loaded
158
+ *
159
+ * @var bool
160
+ */
161
+ protected $_isLocalConfigLoaded = false;
162
+
163
+ /**
164
+ * Depricated properties
165
+ *
166
+ * @deprecated
167
+ */
168
+ protected $_baseDirCache = array();
169
+ protected $_customEtcDir = null;
170
+
171
+ /**
172
+ * Flag which allow to use modules from local code pool
173
+ *
174
+ * @var bool
175
+ */
176
+ protected $_canUseLocalModules = null;
177
+
178
+ /**
179
+ * Active modules array per namespace
180
+ * @var array
181
+ */
182
+ private $_moduleNamespaces = null;
183
+
184
+ /**
185
+ * Modules allowed to load
186
+ * If empty - all modules are allowed
187
+ *
188
+ * @var array
189
+ */
190
+ protected $_allowedModules = array();
191
+
192
+ /**
193
+ * Class construct
194
+ *
195
+ * @param mixed $sourceData
196
+ */
197
+ public function __construct($sourceData=null)
198
+ {
199
+ $this->setCacheId('config_global');
200
+ $this->_options = new Mage_Core_Model_Config_Options($sourceData);
201
+ $this->_prototype = new Mage_Core_Model_Config_Base();
202
+ $this->_cacheChecksum = null;
203
+ parent::__construct($sourceData);
204
+ }
205
+
206
+ /**
207
+ * Get config resource model
208
+ *
209
+ * @return Mage_Core_Store_Mysql4_Config
210
+ */
211
+ public function getResourceModel()
212
+ {
213
+ if (is_null($this->_resourceModel)) {
214
+ $this->_resourceModel = Mage::getResourceModel('core/config');
215
+ }
216
+ return $this->_resourceModel;
217
+ }
218
+
219
+ /**
220
+ * Get configuration options object
221
+ *
222
+ * @return Mage_Core_Model_Config_Options
223
+ */
224
+ public function getOptions()
225
+ {
226
+ return $this->_options;
227
+ }
228
+
229
+ /**
230
+ * Set configuration options
231
+ *
232
+ * @param array $options
233
+ * @return Mage_Core_Model_Config
234
+ */
235
+ public function setOptions($options)
236
+ {
237
+ if (is_array($options)) {
238
+ $this->getOptions()->addData($options);
239
+ }
240
+ return $this;
241
+ }
242
+
243
+ /**
244
+ * Initialization of core configuration
245
+ *
246
+ * @return Mage_Core_Model_Config
247
+ */
248
+ public function init($options=array())
249
+ {
250
+ $this->setCacheChecksum(null);
251
+ $this->_cacheLoadedSections = array();
252
+ $this->setOptions($options);
253
+ $this->loadBase();
254
+
255
+ $cacheLoad = $this->loadModulesCache();
256
+ if ($cacheLoad) {
257
+ return $this;
258
+ }
259
+
260
+ $this->_useCache = false;
261
+
262
+ $this->loadModules();
263
+ $this->loadDb();
264
+ $this->saveCache();
265
+ return $this;
266
+ }
267
+
268
+ /**
269
+ * Load base system configuration (config.xml and local.xml files)
270
+ *
271
+ * @return Mage_Core_Model_Config
272
+ */
273
+ public function loadBase()
274
+ {
275
+ $etcDir = $this->getOptions()->getEtcDir();
276
+ $files = glob($etcDir.DS.'*.xml');
277
+ $this->loadFile(current($files));
278
+ while ($file = next($files)) {
279
+ $merge = clone $this->_prototype;
280
+ $merge->loadFile($file);
281
+ $this->extend($merge);
282
+ }
283
+ if (in_array($etcDir.DS.'local.xml', $files)) {
284
+ $this->_isLocalConfigLoaded = true;
285
+ }
286
+ return $this;
287
+ }
288
+
289
+ /**
290
+ * Load cached modules configuration
291
+ *
292
+ * @return bool
293
+ */
294
+ public function loadModulesCache()
295
+ {
296
+ $params = array();
297
+ if (version_compare(Mage::getVersion(), '1.6.1', '>=')) {
298
+ $params = array('etc_dir' => $this->getOptions()->getEtcDir());
299
+ }
300
+ if (Mage::isInstalled($params)) {
301
+ if ($this->_canUseCacheForInit()) {
302
+ Varien_Profiler::start('mage::app::init::config::load_cache');
303
+ $loaded = $this->loadCache();
304
+ Varien_Profiler::stop('mage::app::init::config::load_cache');
305
+ if ($loaded) {
306
+ $this->_useCache = true;
307
+ return true;
308
+ }
309
+ }
310
+ }
311
+ return false;
312
+ }
313
+
314
+ /**
315
+ * Load modules configuration
316
+ *
317
+ * @return Mage_Core_Model_Config
318
+ */
319
+ public function loadModules()
320
+ {
321
+ Varien_Profiler::start('config/load-modules');
322
+ $this->_loadDeclaredModules();
323
+
324
+ $resourceConfig = sprintf('config.%s.xml', $this->_getResourceConnectionModel('core'));
325
+ $this->loadModulesConfiguration(array('config.xml',$resourceConfig), $this);
326
+
327
+ /**
328
+ * Prevent local.xml directives overwriting
329
+ */
330
+ $mergeConfig = clone $this->_prototype;
331
+ $this->_isLocalConfigLoaded = $mergeConfig->loadFile($this->getOptions()->getEtcDir().DS.'local.xml');
332
+ if ($this->_isLocalConfigLoaded) {
333
+ $this->extend($mergeConfig);
334
+ }
335
+
336
+ $this->applyExtends();
337
+ Varien_Profiler::stop('config/load-modules');
338
+ return $this;
339
+ }
340
+
341
+ /**
342
+ * Check if local configuration (DB connection, etc) is loaded
343
+ *
344
+ * @return bool
345
+ */
346
+ public function isLocalConfigLoaded()
347
+ {
348
+ return $this->_isLocalConfigLoaded;
349
+ }
350
+
351
+ /**
352
+ * Load config data from DB
353
+ *
354
+ * @return Mage_Core_Model_Config
355
+ */
356
+ public function loadDb()
357
+ {
358
+ if ($this->_isLocalConfigLoaded && Mage::isInstalled()) {
359
+ Varien_Profiler::start('config/load-db');
360
+ $dbConf = $this->getResourceModel();
361
+ $dbConf->loadToXml($this);
362
+ Varien_Profiler::stop('config/load-db');
363
+ }
364
+ return $this;
365
+ }
366
+
367
+ /**
368
+ * Reinitialize configuration
369
+ *
370
+ * @param array $options
371
+ * @return Mage_Core_Model_Config
372
+ */
373
+ public function reinit($options = array())
374
+ {
375
+ $this->_allowCacheForInit = false;
376
+ $this->_useCache = false;
377
+ return $this->init($options);
378
+ }
379
+
380
+ /**
381
+ * Check local modules enable/disable flag
382
+ * If local modules are disbled remove local modules path from include dirs
383
+ *
384
+ * return true if local modules enabled and false if disabled
385
+ *
386
+ * @return bool
387
+ */
388
+ protected function _canUseLocalModules()
389
+ {
390
+ if ($this->_canUseLocalModules !== null) {
391
+ return $this->_canUseLocalModules;
392
+ }
393
+
394
+ $disableLocalModules = (string)$this->getNode('global/disable_local_modules');
395
+ if (!empty($disableLocalModules)) {
396
+ $disableLocalModules = (('true' === $disableLocalModules) || ('1' === $disableLocalModules));
397
+ } else {
398
+ $disableLocalModules = false;
399
+ }
400
+
401
+ if ($disableLocalModules && !defined('COMPILER_INCLUDE_PATH')) {
402
+ set_include_path(
403
+ // excluded '/app/code/local'
404
+ BP . DS . 'app' . DS . 'code' . DS . 'community' . PS .
405
+ BP . DS . 'app' . DS . 'code' . DS . 'core' . PS .
406
+ BP . DS . 'lib' . PS .
407
+ Mage::registry('original_include_path')
408
+ );
409
+ }
410
+ $this->_canUseLocalModules = !$disableLocalModules;
411
+ return $this->_canUseLocalModules;
412
+ }
413
+
414
+ /**
415
+ * Check if cache can be used for config initialization
416
+ *
417
+ * @return bool
418
+ */
419
+ protected function _canUseCacheForInit()
420
+ {
421
+ return Mage::app()->useCache('config') && $this->_allowCacheForInit
422
+ && !$this->_loadCache($this->_getCacheLockId());
423
+ }
424
+
425
+ /**
426
+ * Retrieve cache object
427
+ *
428
+ * @return Zend_Cache_Frontend_File
429
+ */
430
+ public function getCache()
431
+ {
432
+ return Mage::app()->getCache();
433
+ }
434
+
435
+ /**
436
+ * Get lock flag cache identifier
437
+ *
438
+ * @return string
439
+ */
440
+ protected function _getCacheLockId()
441
+ {
442
+ return $this->getCacheId().'.lock';
443
+ }
444
+
445
+ /**
446
+ * Save configuration cache
447
+ *
448
+ * @param array $tags cache tags
449
+ * @return Mage_Core_Model_Config
450
+ */
451
+ public function saveCache($tags=array())
452
+ {
453
+ if (!Mage::app()->useCache('config')) {
454
+ return $this;
455
+ }
456
+ if (!in_array(self::CACHE_TAG, $tags)) {
457
+ $tags[] = self::CACHE_TAG;
458
+ }
459
+ $cacheLockId = $this->_getCacheLockId();
460
+ if ($this->_loadCache($cacheLockId)) {
461
+ return $this;
462
+ }
463
+
464
+ if (!empty($this->_cacheSections)) {
465
+ $xml = clone $this->_xml;
466
+ foreach ($this->_cacheSections as $sectionName => $level) {
467
+ $this->_saveSectionCache($this->getCacheId(), $sectionName, $xml, $level, $tags);
468
+ unset($xml->$sectionName);
469
+ }
470
+ $this->_cachePartsForSave[$this->getCacheId()] = $xml->asNiceXml('', false);
471
+ } else {
472
+ return parent::saveCache($tags);
473
+ }
474
+
475
+ $this->_saveCache(time(), $cacheLockId, array(), 60);
476
+ $this->removeCache();
477
+ foreach ($this->_cachePartsForSave as $cacheId => $cacheData) {
478
+ $this->_saveCache($cacheData, $cacheId, $tags, $this->getCacheLifetime());
479
+ }
480
+ unset($this->_cachePartsForSave);
481
+ $this->_removeCache($cacheLockId);
482
+ return $this;
483
+ }
484
+
485
+ /**
486
+ * Save cache of specified
487
+ *
488
+ * @param string $idPrefix cache id prefix
489
+ * @param string $sectionName
490
+ * @param Varien_Simplexml_Element $source
491
+ * @param int $recursionLevel
492
+ * @return Mage_Core_Model_Config
493
+ */
494
+ protected function _saveSectionCache($idPrefix, $sectionName, $source, $recursionLevel=0, $tags=array())
495
+ {
496
+ if ($source && $source->$sectionName) {
497
+ $cacheId = $idPrefix . '_' . $sectionName;
498
+ if ($recursionLevel > 0) {
499
+ foreach ($source->$sectionName->children() as $subSectionName => $node) {
500
+ $this->_saveSectionCache(
501
+ $cacheId, $subSectionName, $source->$sectionName, $recursionLevel-1, $tags
502
+ );
503
+ }
504
+ }
505
+ $this->_cachePartsForSave[$cacheId] = $source->$sectionName->asNiceXml('', false);
506
+ }
507
+ return $this;
508
+ }
509
+
510
+ /**
511
+ * Load config section cached data
512
+ *
513
+ * @param string $sectionName
514
+ * @return Varien_Simplexml_Element
515
+ */
516
+ protected function _loadSectionCache($sectionName)
517
+ {
518
+ $cacheId = $this->getCacheId() . '_' . $sectionName;
519
+ $xmlString = $this->_loadCache($cacheId);
520
+
521
+ /**
522
+ * If we can't load section cache (problems with cache storage)
523
+ */
524
+ if (!$xmlString) {
525
+ $this->_useCache = false;
526
+ $this->reinit($this->_options);
527
+ return false;
528
+ } else {
529
+ $xml = simplexml_load_string($xmlString, $this->_elementClass);
530
+ return $xml;
531
+ }
532
+ }
533
+
534
+ /**
535
+ * Load cached data by identifier
536
+ *
537
+ * @param string $id
538
+ * @return string
539
+ */
540
+ protected function _loadCache($id)
541
+ {
542
+ return Mage::app()->loadCache($id);
543
+ }
544
+
545
+ /**
546
+ * Save cache data
547
+ *
548
+ * @param string $data
549
+ * @param string $id
550
+ * @param array $tags
551
+ * @param false|int $lifetime
552
+ * @return Mage_Core_Model_Config
553
+ */
554
+ protected function _saveCache($data, $id, $tags=array(), $lifetime=false)
555
+ {
556
+ return Mage::app()->saveCache($data, $id, $tags, $lifetime);
557
+ }
558
+
559
+ /**
560
+ * Clear cache data by id
561
+ *
562
+ * @param string $id
563
+ * @return Mage_Core_Model_Config
564
+ */
565
+ protected function _removeCache($id)
566
+ {
567
+ return Mage::app()->removeCache($id);
568
+ }
569
+
570
+ /**
571
+ * Remove configuration cache
572
+ *
573
+ * @return Mage_Core_Model_Config
574
+ */
575
+ public function removeCache()
576
+ {
577
+ Mage::app()->cleanCache(array(self::CACHE_TAG));
578
+ return parent::removeCache();
579
+ }
580
+
581
+ /**
582
+ * Configuration cache clean process
583
+ *
584
+ * @return Mage_Core_Model_Config
585
+ */
586
+ public function cleanCache()
587
+ {
588
+ return $this->reinit();
589
+ }
590
+
591
+ /**
592
+ * Getter for section configuration object
593
+ *
594
+ * @param array $path
595
+ * @return Mage_Core_Model_Config_Element
596
+ */
597
+ protected function _getSectionConfig($path)
598
+ {
599
+ $section = $path[0];
600
+ if (!isset($this->_cacheSections[$section])) {
601
+ return false;
602
+ }
603
+ $sectionPath = array_slice($path, 0, $this->_cacheSections[$section]+1);
604
+ $sectionKey = implode('_', $sectionPath);
605
+
606
+ if (!isset($this->_cacheLoadedSections[$sectionKey])) {
607
+ Varien_Profiler::start('init_config_section:' . $sectionKey);
608
+ $this->_cacheLoadedSections[$sectionKey] = $this->_loadSectionCache($sectionKey);
609
+ Varien_Profiler::stop('init_config_section:' . $sectionKey);
610
+ }
611
+
612
+ if ($this->_cacheLoadedSections[$sectionKey] === false) {
613
+ return false;
614
+ }
615
+ return $this->_cacheLoadedSections[$sectionKey];
616
+ }
617
+
618
+ /**
619
+ * Get node value from cached section data
620
+ *
621
+ * @param array $path
622
+ * @return Mage_Core_Model_Config
623
+ */
624
+ public function getSectionNode($path)
625
+ {
626
+ $section = $path[0];
627
+ $config = $this->_getSectionConfig($path);
628
+ $path = array_slice($path, $this->_cacheSections[$section] + 1);
629
+ if ($config) {
630
+ return $config->descend($path);
631
+ }
632
+ return false;
633
+ }
634
+
635
+ /**
636
+ * Returns node found by the $path and scope info
637
+ *
638
+ * @param string $path
639
+ * @param string $scope
640
+ * @param string|int $scopeCode
641
+ * @return Mage_Core_Model_Config_Element
642
+ */
643
+ public function getNode($path=null, $scope='', $scopeCode=null)
644
+ {
645
+ if ($scope !== '') {
646
+ if (('store' === $scope) || ('website' === $scope)) {
647
+ $scope .= 's';
648
+ }
649
+ if (('default' !== $scope) && is_int($scopeCode)) {
650
+ if ('stores' == $scope) {
651
+ $scopeCode = Mage::app()->getStore($scopeCode)->getCode();
652
+ } elseif ('websites' == $scope) {
653
+ $scopeCode = Mage::app()->getWebsite($scopeCode)->getCode();
654
+ } else {
655
+ Mage::throwException(Mage::helper('core')->__('Unknown scope "%s".', $scope));
656
+ }
657
+ }
658
+ $path = $scope . ($scopeCode ? '/' . $scopeCode : '' ) . (empty($path) ? '' : '/' . $path);
659
+ }
660
+
661
+ /**
662
+ * Check path cache loading
663
+ */
664
+ if ($this->_useCache && ($path !== null)) {
665
+ $path = explode('/', $path);
666
+ $section= $path[0];
667
+ if (isset($this->_cacheSections[$section])) {
668
+ $res = $this->getSectionNode($path);
669
+ if ($res !== false) {
670
+ return $res;
671
+ }
672
+ }
673
+ }
674
+ return parent::getNode($path);
675
+ }
676
+
677
+ /**
678
+ * Create node by $path and set its value.
679
+ *
680
+ * @param string $path separated by slashes
681
+ * @param string $value
682
+ * @param bool $overwrite
683
+ * @return Varien_Simplexml_Config
684
+ */
685
+ public function setNode($path, $value, $overwrite = true)
686
+ {
687
+ if ($this->_useCache && ($path !== null)) {
688
+ $sectionPath = explode('/', $path);
689
+ $config = $this->_getSectionConfig($sectionPath);
690
+ if ($config) {
691
+ $sectionPath = array_slice($sectionPath, $this->_cacheSections[$sectionPath[0]]+1);
692
+ $sectionPath = implode('/', $sectionPath);
693
+ $config->setNode($sectionPath, $value, $overwrite);
694
+ }
695
+ }
696
+ return parent::setNode($path, $value, $overwrite);
697
+ }
698
+
699
+
700
+ /**
701
+ * Retrive Declared Module file list
702
+ *
703
+ * @return array
704
+ */
705
+ protected function _getDeclaredModuleFiles()
706
+ {
707
+ $etcDir = $this->getOptions()->getEtcDir();
708
+ $moduleFiles = glob($etcDir . DS . 'modules' . DS . '*.xml');
709
+
710
+ if (!$moduleFiles) {
711
+ return false;
712
+ }
713
+
714
+ $collectModuleFiles = array(
715
+ 'base' => array(),
716
+ 'mage' => array(),
717
+ 'custom' => array()
718
+ );
719
+
720
+ foreach ($moduleFiles as $v) {
721
+ $name = explode(DIRECTORY_SEPARATOR, $v);
722
+ $name = substr($name[count($name) - 1], 0, -4);
723
+
724
+ if ($name == 'Mage_All') {
725
+ $collectModuleFiles['base'][] = $v;
726
+ } else if (substr($name, 0, 5) == 'Mage_') {
727
+ $collectModuleFiles['mage'][] = $v;
728
+ } else {
729
+ $collectModuleFiles['custom'][] = $v;
730
+ }
731
+ }
732
+
733
+ return array_merge(
734
+ $collectModuleFiles['base'],
735
+ $collectModuleFiles['mage'],
736
+ $collectModuleFiles['custom']
737
+ );
738
+ }
739
+
740
+ /**
741
+ * Add module(s) to allowed list
742
+ *
743
+ * @param strung|array $module
744
+ * @return Mage_Core_Model_Config
745
+ */
746
+ public function addAllowedModules($module)
747
+ {
748
+ if (is_array($module)) {
749
+ foreach ($module as $moduleName) {
750
+ $this->addAllowedModules($moduleName);
751
+ }
752
+ } elseif (!in_array($module, $this->_allowedModules)) {
753
+ $this->_allowedModules[] = $module;
754
+ }
755
+
756
+ return $this;
757
+ }
758
+
759
+ /**
760
+ * Define if module is allowed
761
+ *
762
+ * @param string $moduleName
763
+ * @return bool
764
+ */
765
+ protected function _isAllowedModule($moduleName)
766
+ {
767
+ if (empty($this->_allowedModules)) {
768
+ return true;
769
+ } else {
770
+ return in_array($moduleName, $this->_allowedModules);
771
+ }
772
+ }
773
+
774
+ /**
775
+ * Load declared modules configuration
776
+ *
777
+ * @param null $mergeConfig depricated
778
+ * @return Mage_Core_Model_Config
779
+ */
780
+ protected function _loadDeclaredModules($mergeConfig = null)
781
+ {
782
+ $moduleFiles = $this->_getDeclaredModuleFiles();
783
+ if (!$moduleFiles) {
784
+ return ;
785
+ }
786
+
787
+ Varien_Profiler::start('config/load-modules-declaration');
788
+
789
+ $unsortedConfig = new Mage_Core_Model_Config_Base();
790
+ $unsortedConfig->loadString('<config/>');
791
+ $fileConfig = new Mage_Core_Model_Config_Base();
792
+
793
+ // load modules declarations
794
+ foreach ($moduleFiles as $file) {
795
+ $fileConfig->loadFile($file);
796
+ $unsortedConfig->extend($fileConfig);
797
+ }
798
+
799
+ $moduleDepends = array();
800
+ foreach ($unsortedConfig->getNode('modules')->children() as $moduleName => $moduleNode) {
801
+ if (!$this->_isAllowedModule($moduleName)) {
802
+ continue;
803
+ }
804
+
805
+ $depends = array();
806
+ if ($moduleNode->depends) {
807
+ foreach ($moduleNode->depends->children() as $depend) {
808
+ $depends[$depend->getName()] = true;
809
+ }
810
+ }
811
+ $moduleDepends[$moduleName] = array(
812
+ 'module' => $moduleName,
813
+ 'depends' => $depends,
814
+ 'active' => ('true' === (string)$moduleNode->active ? true : false),
815
+ );
816
+ }
817
+
818
+ // check and sort module dependence
819
+ $moduleDepends = $this->_sortModuleDepends($moduleDepends);
820
+
821
+ // create sorted config
822
+ $sortedConfig = new Mage_Core_Model_Config_Base();
823
+ $sortedConfig->loadString('<config><modules/></config>');
824
+
825
+ foreach ($unsortedConfig->getNode()->children() as $nodeName => $node) {
826
+ if ($nodeName != 'modules') {
827
+ $sortedConfig->getNode()->appendChild($node);
828
+ }
829
+ }
830
+
831
+ foreach ($moduleDepends as $moduleProp) {
832
+ $node = $unsortedConfig->getNode('modules/'.$moduleProp['module']);
833
+ $sortedConfig->getNode('modules')->appendChild($node);
834
+ }
835
+
836
+ $this->extend($sortedConfig);
837
+
838
+ Varien_Profiler::stop('config/load-modules-declaration');
839
+ return $this;
840
+ }
841
+
842
+ /**
843
+ * Sort modules and check depends
844
+ *
845
+ * @param array $modules
846
+ * @return array
847
+ */
848
+ protected function _sortModuleDepends($modules)
849
+ {
850
+ foreach ($modules as $moduleName => $moduleProps) {
851
+ $depends = $moduleProps['depends'];
852
+ foreach ($moduleProps['depends'] as $depend => $true) {
853
+ if ($moduleProps['active'] && ((!isset($modules[$depend])) || empty($modules[$depend]['active']))) {
854
+ Mage::throwException(
855
+ Mage::helper('core')->__('Module "%1$s" requires module "%2$s".', $moduleName, $depend)
856
+ );
857
+ }
858
+ $depends = array_merge($depends, $modules[$depend]['depends']);
859
+ }
860
+ $modules[$moduleName]['depends'] = $depends;
861
+ }
862
+ $modules = array_values($modules);
863
+
864
+ $size = count($modules) - 1;
865
+ for ($i = $size; $i >= 0; $i--) {
866
+ for ($j = $size; $i < $j; $j--) {
867
+ if (isset($modules[$i]['depends'][$modules[$j]['module']])) {
868
+ $value = $modules[$i];
869
+ $modules[$i] = $modules[$j];
870
+ $modules[$j] = $value;
871
+ }
872
+ }
873
+ }
874
+
875
+ $definedModules = array();
876
+ foreach ($modules as $moduleProp) {
877
+ foreach ($moduleProp['depends'] as $dependModule => $true) {
878
+ if (!isset($definedModules[$dependModule])) {
879
+ Mage::throwException(
880
+ Mage::helper('core')->__('Module "%1$s" cannot depend on "%2$s".', $moduleProp['module'], $dependModule)
881
+ );
882
+ }
883
+ }
884
+ $definedModules[$moduleProp['module']] = true;
885
+ }
886
+
887
+ return $modules;
888
+ }
889
+
890
+ /**
891
+ * Determine whether provided name begins from any available modules, according to namespaces priority
892
+ * If matched, returns as the matched module "factory" name or a fully qualified module name
893
+ *
894
+ * @param string $name
895
+ * @param bool $asFullModuleName
896
+ * @return string
897
+ */
898
+ public function determineOmittedNamespace($name, $asFullModuleName = false)
899
+ {
900
+ if (null === $this->_moduleNamespaces) {
901
+ $this->_moduleNamespaces = array();
902
+ foreach ($this->_xml->xpath('modules/*') as $m) {
903
+ if ((string)$m->active == 'true') {
904
+ $moduleName = $m->getName();
905
+ $module = strtolower($moduleName);
906
+ $this->_moduleNamespaces[substr($module, 0, strpos($module, '_'))][$module] = $moduleName;
907
+ }
908
+ }
909
+ }
910
+
911
+ $name = explode('_', strtolower($name));
912
+ $partsNum = count($name);
913
+ $defaultNamespaceFlag = false;
914
+ foreach ($this->_moduleNamespaces as $namespaceName => $namespace) {
915
+ // assume the namespace is omitted (default namespace only, which comes first)
916
+ if ($defaultNamespaceFlag === false) {
917
+ $defaultNamespaceFlag = true;
918
+ $defaultNS = $namespaceName . '_' . $name[0];
919
+ if (isset($namespace[$defaultNS])) {
920
+ return $asFullModuleName ? $namespace[$defaultNS] : $name[0]; // return omitted as well
921
+ }
922
+ }
923
+ // assume namespace is qualified
924
+ if(isset($name[1])) {
925
+ $fullNS = $name[0] . '_' . $name[1];
926
+ if (2 <= $partsNum && isset($namespace[$fullNS])) {
927
+ return $asFullModuleName ? $namespace[$fullNS] : $fullNS;
928
+ }
929
+ }
930
+ }
931
+ return '';
932
+ }
933
+
934
+ /**
935
+ * Iterate all active modules "etc" folders and combine data from
936
+ * specidied xml file name to one object
937
+ *
938
+ * @param string $fileName
939
+ * @param null|Mage_Core_Model_Config_Base $mergeToObject
940
+ * @return Mage_Core_Model_Config_Base
941
+ */
942
+ public function loadModulesConfiguration($fileName, $mergeToObject = null, $mergeModel=null)
943
+ {
944
+ $disableLocalModules = !$this->_canUseLocalModules();
945
+
946
+ if ($mergeToObject === null) {
947
+ $mergeToObject = clone $this->_prototype;
948
+ $mergeToObject->loadString('<config/>');
949
+ }
950
+ if ($mergeModel === null) {
951
+ $mergeModel = clone $this->_prototype;
952
+ }
953
+ $modules = $this->getNode('modules')->children();
954
+ foreach ($modules as $modName=>$module) {
955
+ if ($module->is('active')) {
956
+ if ($disableLocalModules && ('local' === (string)$module->codePool)) {
957
+ continue;
958
+ }
959
+ if (!is_array($fileName)) {
960
+ $fileName = array($fileName);
961
+ }
962
+
963
+ foreach ($fileName as $configFile) {
964
+ $configFile = $this->getModuleDir('etc', $modName).DS.$configFile;
965
+ if ($mergeModel->loadFile($configFile)) {
966
+
967
+ $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_GLOBAL, $mergeModel);
968
+ $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_FRONTEND, $mergeModel);
969
+ $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_ADMIN, $mergeModel);
970
+ $this->_makeEventsLowerCase('adminhtml', $mergeModel);
971
+
972
+ $mergeToObject->extend($mergeModel, true);
973
+ }
974
+ }
975
+ }
976
+ }
977
+ return $mergeToObject;
978
+ }
979
+
980
+ /**
981
+ * Retrieve temporary directory path
982
+ *
983
+ * @return string
984
+ */
985
+ public function getTempVarDir()
986
+ {
987
+ return $this->getOptions()->getVarDir();
988
+ }
989
+
990
+ /**
991
+ * Get default server variables values
992
+ *
993
+ * @return array
994
+ */
995
+ public function getDistroServerVars()
996
+ {
997
+ if (!$this->_distroServerVars) {
998
+
999
+ if (isset($_SERVER['SCRIPT_NAME']) && isset($_SERVER['HTTP_HOST'])) {
1000
+ $secure = (!empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off')) || $_SERVER['SERVER_PORT']=='443';
1001
+ $scheme = ($secure ? 'https' : 'http') . '://' ;
1002
+
1003
+ $hostArr = explode(':', $_SERVER['HTTP_HOST']);
1004
+ $host = $hostArr[0];
1005
+ $port = isset(
1006
+ $hostArr[1]) && (!$secure && $hostArr[1]!=80 || $secure && $hostArr[1]!=443
1007
+ ) ? ':'.$hostArr[1] : '';
1008
+ $path = Mage::app()->getRequest()->getBasePath();
1009
+
1010
+ $baseUrl = $scheme.$host.$port.rtrim($path, '/').'/';
1011
+ } else {
1012
+ $baseUrl = 'http://localhost/';
1013
+ }
1014
+
1015
+ $options = $this->getOptions();
1016
+ $this->_distroServerVars = array(
1017
+ 'root_dir' => $options->getBaseDir(),
1018
+ 'app_dir' => $options->getAppDir(),
1019
+ 'var_dir' => $options->getVarDir(),
1020
+ 'base_url' => $baseUrl,
1021
+ );
1022
+
1023
+ foreach ($this->_distroServerVars as $k=>$v) {
1024
+ $this->_substServerVars['{{'.$k.'}}'] = $v;
1025
+ }
1026
+ }
1027
+ return $this->_distroServerVars;
1028
+ }
1029
+
1030
+ public function substDistroServerVars($data)
1031
+ {
1032
+ $this->getDistroServerVars();
1033
+ return str_replace(
1034
+ array_keys($this->_substServerVars),
1035
+ array_values($this->_substServerVars),
1036
+ $data
1037
+ );
1038
+ }
1039
+
1040
+ /**
1041
+ * Get module config node
1042
+ *
1043
+ * @param string $moduleName
1044
+ * @return Varien_Simplexml_Object
1045
+ */
1046
+ function getModuleConfig($moduleName='')
1047
+ {
1048
+ $modules = $this->getNode('modules');
1049
+ if (''===$moduleName) {
1050
+ return $modules;
1051
+ } else {
1052
+ return $modules->$moduleName;
1053
+ }
1054
+ }
1055
+
1056
+ /**
1057
+ * Get module setup class instance.
1058
+ *
1059
+ * Defaults to Mage_Core_Setup
1060
+ *
1061
+ * @param string|Varien_Simplexml_Object $module
1062
+ * @return object
1063
+ */
1064
+ function getModuleSetup($module='')
1065
+ {
1066
+ $className = 'Mage_Core_Setup';
1067
+ if (''!==$module) {
1068
+ if (is_string($module)) {
1069
+ $module = $this->getModuleConfig($module);
1070
+ }
1071
+ if (isset($module->setup)) {
1072
+ $moduleClassName = $module->setup->getClassName();
1073
+ if (!empty($moduleClassName)) {
1074
+ $className = $moduleClassName;
1075
+ }
1076
+ }
1077
+ }
1078
+ return new $className($module);
1079
+ }
1080
+
1081
+ /**
1082
+ * Get base filesystem directory. depends on $type
1083
+ *
1084
+ * If $moduleName is specified retrieves specific value for the module.
1085
+ *
1086
+ * @deprecated in favor of Mage_Core_Model_Config_Options
1087
+ * @todo get global dir config
1088
+ * @param string $type
1089
+ * @return string
1090
+ */
1091
+ public function getBaseDir($type='base')
1092
+ {
1093
+ return $this->getOptions()->getDir($type);
1094
+ }
1095
+
1096
+ /**
1097
+ * Get temporary data directory name
1098
+ *
1099
+ * @param string $path
1100
+ * @param string $type
1101
+ * @return string
1102
+ */
1103
+ public function getVarDir($path=null, $type='var')
1104
+ {
1105
+ $dir = Mage::getBaseDir($type).($path!==null ? DS.$path : '');
1106
+ if (!$this->createDirIfNotExists($dir)) {
1107
+ return false;
1108
+ }
1109
+ return $dir;
1110
+ }
1111
+
1112
+ public function createDirIfNotExists($dir)
1113
+ {
1114
+ return $this->getOptions()->createDirIfNotExists($dir);
1115
+ }
1116
+
1117
+ /**
1118
+ * Get module directory by directory type
1119
+ *
1120
+ * @param string $type
1121
+ * @param string $moduleName
1122
+ * @return string
1123
+ */
1124
+ public function getModuleDir($type, $moduleName)
1125
+ {
1126
+ $codePool = (string)$this->getModuleConfig($moduleName)->codePool;
1127
+ $dir = $this->getOptions()->getCodeDir().DS.$codePool.DS.uc_words($moduleName, DS);
1128
+
1129
+ switch ($type) {
1130
+ case 'etc':
1131
+ $dir .= DS.'etc';
1132
+ break;
1133
+
1134
+ case 'controllers':
1135
+ $dir .= DS.'controllers';
1136
+ break;
1137
+
1138
+ case 'sql':
1139
+ $dir .= DS.'sql';
1140
+ break;
1141
+ case 'data':
1142
+ $dir .= DS.'data';
1143
+ break;
1144
+
1145
+ case 'locale':
1146
+ $dir .= DS.'locale';
1147
+ break;
1148
+ }
1149
+
1150
+ $dir = str_replace('/', DS, $dir);
1151
+ return $dir;
1152
+ }
1153
+
1154
+ /**
1155
+ * Load event observers for an area (front, admin)
1156
+ *
1157
+ * @param string $area
1158
+ * @return boolean
1159
+ */
1160
+ public function loadEventObservers($area)
1161
+ {
1162
+ $events = $this->getNode("$area/events");
1163
+ if ($events) {
1164
+ $events = $events->children();
1165
+ } else {
1166
+ return false;
1167
+ }
1168
+
1169
+ foreach ($events as $event) {
1170
+ $eventName = strtolower($event->getName());
1171
+ $observers = $event->observers->children();
1172
+ foreach ($observers as $observer) {
1173
+ switch ((string)$observer->type) {
1174
+ case 'singleton':
1175
+ $callback = array(
1176
+ Mage::getSingleton((string)$observer->class),
1177
+ (string)$observer->method
1178
+ );
1179
+ break;
1180
+ case 'object':
1181
+ case 'model':
1182
+ $callback = array(
1183
+ Mage::getModel((string)$observer->class),
1184
+ (string)$observer->method
1185
+ );
1186
+ break;
1187
+ default:
1188
+ $callback = array($observer->getClassName(), (string)$observer->method);
1189
+ break;
1190
+ }
1191
+
1192
+ $args = (array)$observer->args;
1193
+ $observerClass = $observer->observer_class ? (string)$observer->observer_class : '';
1194
+ Mage::addObserver($eventName, $callback, $args, $observer->getName(), $observerClass);
1195
+ }
1196
+ }
1197
+ return true;
1198
+ }
1199
+
1200
+ /**
1201
+ * Get standard path variables.
1202
+ *
1203
+ * To be used in blocks, templates, etc.
1204
+ *
1205
+ * @param array|string $args Module name if string
1206
+ * @return array
1207
+ */
1208
+ public function getPathVars($args=null)
1209
+ {
1210
+ $path = array();
1211
+
1212
+ $path['baseUrl'] = Mage::getBaseUrl();
1213
+ $path['baseSecureUrl'] = Mage::getBaseUrl('link', true);
1214
+
1215
+ return $path;
1216
+ }
1217
+
1218
+ /**
1219
+ * Retrieve class name by class group
1220
+ *
1221
+ * @param string $groupType currently supported model, block, helper
1222
+ * @param string $classId slash separated class identifier, ex. group/class
1223
+ * @param string $groupRootNode optional config path for group config
1224
+ * @return string
1225
+ */
1226
+ public function getGroupedClassName($groupType, $classId, $groupRootNode=null)
1227
+ {
1228
+ if (empty($groupRootNode)) {
1229
+ $groupRootNode = 'global/'.$groupType.'s';
1230
+ }
1231
+
1232
+ $classArr = explode('/', trim($classId));
1233
+ $group = $classArr[0];
1234
+ $class = !empty($classArr[1]) ? $classArr[1] : null;
1235
+
1236
+ if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
1237
+ return $this->_classNameCache[$groupRootNode][$group][$class];
1238
+ }
1239
+
1240
+ $config = $this->_xml->global->{$groupType.'s'}->{$group};
1241
+
1242
+ // First - check maybe the entity class was rewritten
1243
+ $className = null;
1244
+ if (isset($config->rewrite->$class)) {
1245
+ $className = (string)$config->rewrite->$class;
1246
+ } else {
1247
+ /**
1248
+ * Backwards compatibility for pre-MMDB extensions.
1249
+ * In MMDB release resource nodes <..._mysql4> were renamed to <..._resource>. So <deprecatedNode> is left
1250
+ * to keep name of previously used nodes, that still may be used by non-updated extensions.
1251
+ */
1252
+ if (isset($config->deprecatedNode)) {
1253
+ $deprecatedNode = $config->deprecatedNode;
1254
+ $configOld = $this->_xml->global->{$groupType.'s'}->$deprecatedNode;
1255
+ if (isset($configOld->rewrite->$class)) {
1256
+ $className = (string) $configOld->rewrite->$class;
1257
+ }
1258
+ }
1259
+ }
1260
+
1261
+ // Second - if entity is not rewritten then use class prefix to form class name
1262
+ if (empty($className)) {
1263
+ if (!empty($config)) {
1264
+ $className = $config->getClassName();
1265
+ }
1266
+ if (empty($className)) {
1267
+ $className = 'mage_'.$group.'_'.$groupType;
1268
+ }
1269
+ if (!empty($class)) {
1270
+ $className .= '_'.$class;
1271
+ }
1272
+ $className = uc_words($className);
1273
+ }
1274
+
1275
+ ##########
1276
+ # Collect plugins and override $className
1277
+ ##########
1278
+ if (intval($this->_xml->default->system->plugin->enabled) &&
1279
+ class_exists('SafeMage_Plugin') &&
1280
+ isset($config->plugin->$class) &&
1281
+ $data = $config->plugin->$class
1282
+ ) {
1283
+ $className = Mage::getSingleton('SafeMage_Plugin')->addPlugins($className, $data);
1284
+ }
1285
+ ###########
1286
+ ###########
1287
+
1288
+ $this->_classNameCache[$groupRootNode][$group][$class] = $className;
1289
+ return $className;
1290
+ }
1291
+
1292
+ /**
1293
+ * Retrieve block class name
1294
+ *
1295
+ * @param string $blockType
1296
+ * @return string
1297
+ */
1298
+ public function getBlockClassName($blockType)
1299
+ {
1300
+ if (strpos($blockType, '/')===false) {
1301
+ return $blockType;
1302
+ }
1303
+ return $this->getGroupedClassName('block', $blockType);
1304
+ }
1305
+
1306
+ /**
1307
+ * Retrieve helper class name
1308
+ *
1309
+ * @param string $name
1310
+ * @return string
1311
+ */
1312
+ public function getHelperClassName($helperName)
1313
+ {
1314
+ if (strpos($helperName, '/') === false) {
1315
+ $helperName .= '/data';
1316
+ }
1317
+ return $this->getGroupedClassName('helper', $helperName);
1318
+ }
1319
+
1320
+ /**
1321
+ * Retreive resource helper instance
1322
+ *
1323
+ * Example:
1324
+ * $config->getResourceHelper('cms')
1325
+ * will instantiate Mage_Cms_Model_Resource_Helper_<db_adapter_name>
1326
+ *
1327
+ * @param string $moduleName
1328
+ * @return Mage_Core_Model_Resource_Helper_Abstract|false
1329
+ */
1330
+ public function getResourceHelper($moduleName)
1331
+ {
1332
+ $connectionModel = $this->_getResourceConnectionModel($moduleName);
1333
+ $helperClass = sprintf('%s/helper_%s', $moduleName, $connectionModel);
1334
+ $helperClassName = $this->_getResourceModelFactoryClassName($helperClass);
1335
+ if ($helperClassName) {
1336
+ return $this->getModelInstance($helperClassName, $moduleName);
1337
+ }
1338
+
1339
+ return false;
1340
+ }
1341
+
1342
+ /**
1343
+ * Retrieve module class name
1344
+ *
1345
+ * @param sting $modelClass
1346
+ * @return string
1347
+ */
1348
+ public function getModelClassName($modelClass)
1349
+ {
1350
+ $modelClass = trim($modelClass);
1351
+ if (strpos($modelClass, '/')===false) {
1352
+ return $modelClass;
1353
+ }
1354
+ return $this->getGroupedClassName('model', $modelClass);
1355
+ }
1356
+
1357
+ /**
1358
+ * Get model class instance.
1359
+ *
1360
+ * Example:
1361
+ * $config->getModelInstance('catalog/product')
1362
+ *
1363
+ * Will instantiate Mage_Catalog_Model_Mysql4_Product
1364
+ *
1365
+ * @param string $modelClass
1366
+ * @param array|object $constructArguments
1367
+ * @return Mage_Core_Model_Abstract|false
1368
+ */
1369
+ public function getModelInstance($modelClass='', $constructArguments=array())
1370
+ {
1371
+ $className = $this->getModelClassName($modelClass);
1372
+ if (class_exists($className)) {
1373
+ Varien_Profiler::start('CORE::create_object_of::'.$className);
1374
+ $obj = new $className($constructArguments);
1375
+ Varien_Profiler::stop('CORE::create_object_of::'.$className);
1376
+ return $obj;
1377
+ } else {
1378
+ return false;
1379
+ }
1380
+ }
1381
+
1382
+ public function getNodeClassInstance($path)
1383
+ {
1384
+ $config = Mage::getConfig()->getNode($path);
1385
+ if (!$config) {
1386
+ return false;
1387
+ } else {
1388
+ $className = $config->getClassName();
1389
+ return new $className();
1390
+ }
1391
+ }
1392
+
1393
+ /**
1394
+ * Get resource model object by alias
1395
+ *
1396
+ * @param string $modelClass
1397
+ * @param array $constructArguments
1398
+ * @return object
1399
+ */
1400
+ public function getResourceModelInstance($modelClass='', $constructArguments=array())
1401
+ {
1402
+ $factoryName = $this->_getResourceModelFactoryClassName($modelClass);
1403
+ if (!$factoryName) {
1404
+ return false;
1405
+ }
1406
+ return $this->getModelInstance($factoryName, $constructArguments);
1407
+ }
1408
+
1409
+ /**
1410
+ * Get resource configuration for resource name
1411
+ *
1412
+ * @param string $name
1413
+ * @return Varien_Simplexml_Object
1414
+ */
1415
+ public function getResourceConfig($name)
1416
+ {
1417
+ return $this->_xml->global->resources->{$name};
1418
+ }
1419
+
1420
+ /**
1421
+ * Get connection configuration
1422
+ *
1423
+ * @param string $name
1424
+ * @return Varien_Simplexml_Element
1425
+ */
1426
+ public function getResourceConnectionConfig($name)
1427
+ {
1428
+ $config = $this->getResourceConfig($name);
1429
+ if ($config) {
1430
+ $conn = $config->connection;
1431
+ if ($conn) {
1432
+ if (!empty($conn->use)) {
1433
+ return $this->getResourceConnectionConfig((string)$conn->use);
1434
+ } else {
1435
+ return $conn;
1436
+ }
1437
+ }
1438
+ }
1439
+ return false;
1440
+ }
1441
+
1442
+ /**
1443
+ * Retrieve resource type configuration for resource name
1444
+ *
1445
+ * @param string $type
1446
+ * @return Varien_Simplexml_Object
1447
+ */
1448
+ public function getResourceTypeConfig($type)
1449
+ {
1450
+ return $this->_xml->global->resource->connection->types->{$type};
1451
+ }
1452
+
1453
+ /**
1454
+ * Retrieve store Ids for $path with checking
1455
+ *
1456
+ * if empty $allowValues then retrieve all stores values
1457
+ *
1458
+ * return array($storeId=>$pathValue)
1459
+ *
1460
+ * @param string $path
1461
+ * @param array $allowValues
1462
+ * @return array
1463
+ */
1464
+ public function getStoresConfigByPath($path, $allowValues = array(), $useAsKey = 'id')
1465
+ {
1466
+ $storeValues = array();
1467
+ $stores = $this->getNode('stores');
1468
+ foreach ($stores->children() as $code => $store) {
1469
+ switch ($useAsKey) {
1470
+ case 'id':
1471
+ $key = (int) $store->descend('system/store/id');
1472
+ break;
1473
+
1474
+ case 'code':
1475
+ $key = $code;
1476
+ break;
1477
+
1478
+ case 'name':
1479
+ $key = (string) $store->descend('system/store/name');
1480
+ }
1481
+ if ($key === false) {
1482
+ continue;
1483
+ }
1484
+
1485
+ $pathValue = (string) $store->descend($path);
1486
+
1487
+ if (empty($allowValues)) {
1488
+ $storeValues[$key] = $pathValue;
1489
+ } else if (in_array($pathValue, $allowValues)) {
1490
+ $storeValues[$key] = $pathValue;
1491
+ }
1492
+ }
1493
+ return $storeValues;
1494
+ }
1495
+
1496
+ /**
1497
+ * Check whether given path should be secure according to configuration security requirements for URL
1498
+ * "Secure" should not be confused with https protocol, it is about web/secure/*_url settings usage only
1499
+ *
1500
+ * @param string $url
1501
+ * @return bool
1502
+ */
1503
+ public function shouldUrlBeSecure($url)
1504
+ {
1505
+ if (!Mage::getStoreConfigFlag(Mage_Core_Model_Store::XML_PATH_SECURE_IN_FRONTEND)) {
1506
+ return false;
1507
+ }
1508
+
1509
+ if (!isset($this->_secureUrlCache[$url])) {
1510
+ $this->_secureUrlCache[$url] = false;
1511
+ $secureUrls = $this->getNode('frontend/secure_url');
1512
+ foreach ($secureUrls->children() as $match) {
1513
+ if (strpos($url, (string)$match) === 0) {
1514
+ $this->_secureUrlCache[$url] = true;
1515
+ break;
1516
+ }
1517
+ }
1518
+ }
1519
+
1520
+ return $this->_secureUrlCache[$url];
1521
+ }
1522
+
1523
+ /**
1524
+ * Get DB table names prefix
1525
+ *
1526
+ * @return string
1527
+ */
1528
+ public function getTablePrefix()
1529
+ {
1530
+ return $this->_xml->global->resources->db->table_prefix;
1531
+ }
1532
+
1533
+ /**
1534
+ * Get events configuration
1535
+ *
1536
+ * @param string $area event area
1537
+ * @param string $eventName event name
1538
+ * @return Mage_Core_Model_Config_Element
1539
+ */
1540
+ public function getEventConfig($area, $eventName)
1541
+ {
1542
+ //return $this->getNode($area)->events->{$eventName};
1543
+ if (!isset($this->_eventAreas[$area])) {
1544
+ $this->_eventAreas[$area] = $this->getNode($area)->events;
1545
+ }
1546
+ return $this->_eventAreas[$area]->{$eventName};
1547
+ }
1548
+
1549
+ /**
1550
+ * Save config value to DB
1551
+ *
1552
+ * @param string $path
1553
+ * @param string $value
1554
+ * @param string $scope
1555
+ * @param int $scopeId
1556
+ * @return Mage_Core_Store_Config
1557
+ */
1558
+ public function saveConfig($path, $value, $scope = 'default', $scopeId = 0)
1559
+ {
1560
+ $resource = $this->getResourceModel();
1561
+ $resource->saveConfig(rtrim($path, '/'), $value, $scope, $scopeId);
1562
+
1563
+ return $this;
1564
+ }
1565
+
1566
+ /**
1567
+ * Delete config value from DB
1568
+ *
1569
+ * @param string $path
1570
+ * @param string $scope
1571
+ * @param int $scopeId
1572
+ * @return Mage_Core_Model_Config
1573
+ */
1574
+ public function deleteConfig($path, $scope = 'default', $scopeId = 0)
1575
+ {
1576
+ $resource = $this->getResourceModel();
1577
+ $resource->deleteConfig(rtrim($path, '/'), $scope, $scopeId);
1578
+
1579
+ return $this;
1580
+ }
1581
+
1582
+ /**
1583
+ * Get fieldset from configuration
1584
+ *
1585
+ * @param string $name fieldset name
1586
+ * @param string $root fieldset area, could be 'admin'
1587
+ * @return null|array
1588
+ */
1589
+ public function getFieldset($name, $root = 'global')
1590
+ {
1591
+ $rootNode = $this->getNode($root.'/fieldsets');
1592
+ if (!$rootNode) {
1593
+ return null;
1594
+ }
1595
+ return $rootNode->$name ? $rootNode->$name->children() : null;
1596
+ }
1597
+
1598
+ /**
1599
+ * Retrieve resource connection model name
1600
+ *
1601
+ * @param string $moduleName
1602
+ * @return string
1603
+ */
1604
+ protected function _getResourceConnectionModel($moduleName = null)
1605
+ {
1606
+ $config = null;
1607
+ if (!is_null($moduleName)) {
1608
+ $setupResource = $moduleName . '_setup';
1609
+ $config = $this->getResourceConnectionConfig($setupResource);
1610
+ }
1611
+ if (!$config) {
1612
+ $config = $this->getResourceConnectionConfig(Mage_Core_Model_Resource::DEFAULT_SETUP_RESOURCE);
1613
+ }
1614
+
1615
+ return (string)$config->model;
1616
+ }
1617
+
1618
+ /**
1619
+ * Get factory class name for a resource
1620
+ *
1621
+ * @param string $modelClass
1622
+ * @return string|false
1623
+ */
1624
+ protected function _getResourceModelFactoryClassName($modelClass)
1625
+ {
1626
+ $classArray = explode('/', $modelClass);
1627
+ if (count($classArray) != 2) {
1628
+ return false;
1629
+ }
1630
+
1631
+ list($module, $model) = $classArray;
1632
+ if (!isset($this->_xml->global->models->{$module})) {
1633
+ return false;
1634
+ }
1635
+
1636
+ $moduleNode = $this->_xml->global->models->{$module};
1637
+ if (!empty($moduleNode->resourceModel)) {
1638
+ $resourceModel = (string)$moduleNode->resourceModel;
1639
+ } else {
1640
+ return false;
1641
+ }
1642
+
1643
+ return $resourceModel . '/' . $model;
1644
+ }
1645
+
1646
+ /**
1647
+ * Get a resource model class name
1648
+ *
1649
+ * @param string $modelClass
1650
+ * @return string|false
1651
+ */
1652
+ public function getResourceModelClassName($modelClass)
1653
+ {
1654
+ $factoryName = $this->_getResourceModelFactoryClassName($modelClass);
1655
+ if ($factoryName) {
1656
+ return $this->getModelClassName($factoryName);
1657
+ }
1658
+ return false;
1659
+ }
1660
+
1661
+ /**
1662
+ * Makes all events to lower-case
1663
+ *
1664
+ * @param string $area
1665
+ * @param Varien_Simplexml_Config $mergeModel
1666
+ */
1667
+ protected function _makeEventsLowerCase($area, Varien_Simplexml_Config $mergeModel)
1668
+ {
1669
+ $events = $mergeModel->getNode($area . "/" . Mage_Core_Model_App_Area::PART_EVENTS);
1670
+ if ($events !== false) {
1671
+ $children = clone $events->children();
1672
+ /** @var Mage_Core_Model_Config_Element $event */
1673
+ foreach ($children as $event) {
1674
+ if ($this->_isNodeNameHasUpperCase($event)) {
1675
+ $oldName = $event->getName();
1676
+ $newEventName = strtolower($oldName);
1677
+ if (!isset($events->$newEventName)) {
1678
+ /** @var Mage_Core_Model_Config_Element $newNode */
1679
+ $newNode = $events->addChild($newEventName, $event);
1680
+ $newNode->extend($event);
1681
+ }
1682
+ unset($events->$oldName);
1683
+ }
1684
+ }
1685
+ }
1686
+ }
1687
+
1688
+ /**
1689
+ * Checks is event name has upper-case letters
1690
+ *
1691
+ * @param Mage_Core_Model_Config_Element $event
1692
+ * @return bool
1693
+ */
1694
+ protected function _isNodeNameHasUpperCase(Mage_Core_Model_Config_Element $event)
1695
+ {
1696
+ return (strtolower($event->getName()) !== (string)$event->getName());
1697
+ }
1698
+ }
app/etc/modules/SafeMage_Plugin.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <SafeMage_Plugin>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <extension_name>Function Plugins (Interceptors)</extension_name>
8
+ <cache_key>plugin</cache_key>
9
+ <url></url>
10
+ </SafeMage_Plugin>
11
+ </modules>
12
+ </config>
app/locale/en_US/SafeMage_Plugin.csv ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ Block Plugins,Block Plugins
2
+ Enable,Enable
3
+ Helper Plugins,Helper Plugins
4
+ Folder does not have write permissions: %s,Folder does not have write permissions: %s
5
+ Model Plugins,Model Plugins
6
+ Name / Run,Name / Run
7
+ Plugins (Interceptors),Plugins (Interceptors)
8
+ Sort,Sort
9
+ Type,Type
lib/SafeMage/Plugin.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class SafeMage_Plugin
4
+ {
5
+ const TYPE_BEFORE = 'before';
6
+ const TYPE_AROUND = 'around';
7
+ const TYPE_AFTER = 'after';
8
+
9
+ public function __construct($arg)
10
+ {
11
+ spl_autoload_register(array(__CLASS__, 'autoload'));
12
+ }
13
+
14
+ /**
15
+ * Attempt to load the given class.
16
+ *
17
+ * @param string $className
18
+ * @return void
19
+ */
20
+ public function autoload($className)
21
+ {
22
+ if ($this->isPluginClass($className)) {
23
+ $inc = SafeMage_Plugin_File::getDir() . $className . '.php';
24
+ return include $inc;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * @param $className string
30
+ * @return bool
31
+ */
32
+ public function isPluginClass($className)
33
+ {
34
+ if (substr($className, -8) == '_Plugged') {
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+
40
+ /**
41
+ * @param $className string
42
+ * @return string
43
+ */
44
+ public function getPluginClassName($className)
45
+ {
46
+ return $className . '_Plugged';
47
+ }
48
+
49
+ /**
50
+ * @param $className string
51
+ * @param $data Mage_Core_Model_Config_Element
52
+ * @return string
53
+ */
54
+ public function addPlugins($className, $data)
55
+ {
56
+ $pluginClassName = $this->getPluginClassName($className);
57
+
58
+ // class file in cache
59
+ if (Mage::app()->useCache('config') && Mage::getSingleton('SafeMage_Plugin_File')->isExist($pluginClassName)) {
60
+ return $pluginClassName;
61
+ }
62
+
63
+ // collect active plugins
64
+ $plugins = array();
65
+ foreach ($data->children() as $plugin) {
66
+ $method = (string)$plugin->method;
67
+ $type = (string)$plugin->type;
68
+ if ($method && $type && (string)$plugin->run && !(int)$plugin->disabled) {
69
+ $plugins[$method][$type][] = $plugin;
70
+ }
71
+ }
72
+
73
+ if (!$plugins) {
74
+ return $className;
75
+ }
76
+
77
+ $pluginRenderer = Mage::getSingleton('SafeMage_Plugin_Renderer');
78
+ $pluginRenderer->init($className);
79
+
80
+ foreach($plugins as $method => $methodPlugins) {
81
+ try {
82
+ $methodPlugins = $this->_sort($methodPlugins);
83
+ $pluginRenderer->addPluginsForMethod($method, $methodPlugins);
84
+ } catch (Exception $e) {
85
+ $this->_log($e->getMessage());
86
+ }
87
+ }
88
+
89
+ try {
90
+ $pluginRenderer->createClass($pluginClassName);
91
+ return $pluginClassName;
92
+ } catch (Exception $e) {
93
+ $this->_log($e->getMessage());
94
+ }
95
+
96
+ return $className;
97
+ }
98
+
99
+ protected function _sort($plugins)
100
+ {
101
+ foreach($plugins as $type => &$pluginsArray) {
102
+ usort($pluginsArray, array($this, '_sortByOrder'));
103
+ }
104
+ return $plugins;
105
+ }
106
+
107
+ protected function _sortByOrder(Mage_Core_Model_Config_Element $plugin1, Mage_Core_Model_Config_Element $plugin2)
108
+ {
109
+ return (intval($plugin1->sort_order) > intval($plugin2->sort_order)) ? true : false;
110
+ }
111
+
112
+ protected function _log($message)
113
+ {
114
+ Mage::log($message, null, 'plugins.log');
115
+ }
116
+ }
lib/SafeMage/Plugin/File.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SafeMage_Plugin_File
3
+ {
4
+ const DIR = 'plugins';
5
+
6
+ /**
7
+ * @return string
8
+ */
9
+ public static function getDir()
10
+ {
11
+ return Mage::getBaseDir('cache') . DS . self::DIR . DS ;
12
+ }
13
+
14
+ /**
15
+ * @param $pluginClassName string
16
+ * @param $code string
17
+ * @throws Exception
18
+ */
19
+ public function create($pluginClassName, $code)
20
+ {
21
+ if (!is_dir(self::getDir())) {
22
+ if (!mkdir(self::getDir())) {
23
+ throw new Exception('Failed to create directory: ' . self::getDir());
24
+ }
25
+
26
+ if (!chmod(self::getDir(), 0777)) {
27
+ throw new Exception('Failed to chmod() directory: ' . self::getDir());
28
+ }
29
+ }
30
+
31
+ $file = self::getDir() . $pluginClassName . '.php';
32
+
33
+ if (!file_put_contents($file, $code)) {
34
+ throw new Exception('Failed to save file: ' . $file);
35
+ }
36
+
37
+ if (!chmod($file, 0777)) {
38
+ throw new Exception('Failed to chmod() file: ' . $file);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * @param $pluginClassName string
44
+ * @return bool
45
+ */
46
+ public function isExist($pluginClassName)
47
+ {
48
+ $file = self::getDir() . $pluginClassName . '.php';
49
+ return file_exists($file);
50
+ }
51
+ }
lib/SafeMage/Plugin/Renderer.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class SafeMage_Plugin_Renderer extends Varien_Object
4
+ {
5
+ protected $_phpCode;
6
+
7
+ /**
8
+ * @param $className string
9
+ */
10
+ public function init($className)
11
+ {
12
+ define('NL', PHP_EOL . ' ');
13
+ define('NL2', PHP_EOL . ' ');
14
+ $this->_phpCode = '';
15
+ $this->setClassName($className);
16
+ }
17
+
18
+ /**
19
+ * @param $method string
20
+ * @param $pluginsData array
21
+ */
22
+ public function addPluginsForMethod($method, $pluginsData)
23
+ {
24
+ $before = array();
25
+ if (isset($pluginsData[SafeMage_Plugin::TYPE_BEFORE])) {
26
+ $beforePlugins = $pluginsData[SafeMage_Plugin::TYPE_BEFORE];
27
+ foreach($beforePlugins as $plugin) {
28
+ $runParts = explode('::', (string)$plugin->run, 2);
29
+ $pluginClass = $runParts[0];
30
+ $pluginMethod = $runParts[1];
31
+ $before[] = 'Mage::getSingleton(\'' . $pluginClass .'\')->'. $pluginMethod . '($this, $arguments);';
32
+ }
33
+ }
34
+
35
+ $around = array();
36
+ if (isset($pluginsData[SafeMage_Plugin::TYPE_AROUND])) {
37
+ $aroundPlugins = $pluginsData[SafeMage_Plugin::TYPE_AROUND];
38
+ foreach($aroundPlugins as $plugin) {
39
+ $runParts = explode('::', (string)$plugin->run, 2);
40
+ $pluginClass = $runParts[0];
41
+ $pluginMethod = $runParts[1];
42
+ $around[] = '$result = Mage::getSingleton(\'' . $pluginClass .'\')->'. $pluginMethod . '($this, $arguments);';
43
+ }
44
+ }
45
+
46
+ $after = array();
47
+ if (isset($pluginsData[SafeMage_Plugin::TYPE_AFTER])) {
48
+ $afterPlugins = $pluginsData[SafeMage_Plugin::TYPE_AFTER];
49
+ foreach($afterPlugins as $plugin) {
50
+ $runParts = explode('::', (string)$plugin->run, 2);
51
+ $pluginClass = $runParts[0];
52
+ $pluginMethod = $runParts[1];
53
+ $after[] = '$result = Mage::getSingleton(\'' . $pluginClass .'\')->'. $pluginMethod . '($this, $result, $arguments);';
54
+ }
55
+ }
56
+
57
+ $this->_phpCode .= $this->_renderMethod($method, $before, $around, $after);
58
+ }
59
+
60
+ /**
61
+ * @param $pluginClassName string
62
+ */
63
+ public function createClass($pluginClassName)
64
+ {
65
+ Mage::getSingleton('SafeMage_Plugin_File')->create($pluginClassName, $this->_renderClass($pluginClassName));
66
+ }
67
+
68
+ /**
69
+ * @param $pluginClassName string
70
+ * @return string
71
+ */
72
+ protected function _renderClass($pluginClassName)
73
+ {
74
+ $className = $this->getClassName();
75
+
76
+ $code = '<?php ' . PHP_EOL;
77
+ $code .= 'class ' . $pluginClassName . ' extends ' . $className;
78
+ $code .= PHP_EOL . '{';
79
+ $code .= $this->_phpCode;
80
+ $code .= PHP_EOL . '}';
81
+
82
+ return $code;
83
+ }
84
+
85
+ protected function _renderMethod($method, $before, $around, $after)
86
+ {
87
+ $className = $this->getClassName();
88
+ $oReflectionClass = new ReflectionClass($className);
89
+ $method = $oReflectionClass->getMethod($method);
90
+
91
+ $this->_validateMethod($method);
92
+
93
+ $sParamsWithDefaults = array();
94
+ $sParams = array();
95
+ foreach($method->getParameters() as $param) {
96
+ $sParams[]= '$' . $param->name;
97
+ $sParamWithDefaults = '$' . $param->name;
98
+ if ( $param->isDefaultValueAvailable() ) {
99
+ $sParamWithDefaults .= ' = ' . $this->_varExport($param->getDefaultValue());
100
+ }
101
+ $sParamsWithDefaults[]= $sParamWithDefaults;
102
+ }
103
+
104
+ $sParamsWithDefaults = implode(', ', $sParamsWithDefaults);
105
+ $sParams = implode(', ', $sParams);
106
+
107
+ $sModifiers = implode(' ', Reflection::getModifierNames($method->getModifiers()));
108
+ $code = NL . $sModifiers . ' function ' . $method->name . '(' . $sParamsWithDefaults . ')';
109
+ $code .= NL . '{';
110
+
111
+ $code .= NL2 . '$arguments = array(' . $sParams . ');' . NL2;
112
+
113
+ if ($before) {
114
+ $code .= NL2 . '// BEFORE';
115
+ $code .= NL2 . implode(NL2, $before) . NL2;
116
+ }
117
+
118
+ $code .= NL2;
119
+ $code .= '// CURRENT METHOD' . NL2;
120
+ $callParent = '$result = parent::' . $method->name . '(' . $sParams . ');';
121
+ if ($around) {
122
+ $callParent = '//' . $callParent . NL2;
123
+ $callParent .= NL2 . '// AROUND';
124
+ $callParent .= NL2 . implode(NL2, $around);
125
+ } elseif($sParams && $before) {
126
+ $code .= 'list(' . $sParams . ') = $arguments;' . NL2;
127
+ }
128
+ $code .= $callParent . NL2;
129
+
130
+ if ($after) {
131
+ $code .= NL2 . '// AFTER';
132
+ $code .= NL2 . implode(NL2, $after) . NL2;
133
+ }
134
+
135
+ $code .= NL2 . 'return $result;';
136
+ $code .= NL . '}';
137
+
138
+ return $code;
139
+ }
140
+
141
+ protected function _varExport($var)
142
+ {
143
+ $var = var_export($var, 1);
144
+ $var = str_replace(array("\r", "\n", ' '), array('', '', ''), $var);
145
+ return $var;
146
+ }
147
+
148
+ protected function _validateMethod(ReflectionMethod $method)
149
+ {
150
+ if ($method->isFinal()) {
151
+ throw new Exception("Cannot override final method");
152
+ }
153
+
154
+ if ($method->isPrivate()) {
155
+ throw new Exception("Cannot override private method");
156
+ }
157
+ }
158
+ }
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>SafeMage_Plugin</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.safemage.com/LICENSE_EULA.txt">SafeMage EULA</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Function Plugins(Interceptors) for Magento&#xAE; 1</summary>
10
+ <description>Plugin is a new solution to override Magento Core functionality instead of rewrites and events</description>
11
+ <notes>Initial Release</notes>
12
+ <authors><author><name>SafeMage</name><user>safemage</user><email>info@safemage.com</email></author></authors>
13
+ <date>2016-12-10</date>
14
+ <time>10:06:20</time>
15
+ <contents><target name="magecommunity"><dir name="SafeMage"><dir name="Plugin"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Plugin"><file name="List.php" hash="e1b2f24ad3b1aaaf41693888e3456411"/></dir><file name="Plugin.php" hash="50608a642601ee1272c297f78fcf3da5"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="d9dd5134b45cbefeae99af0fe1e0bdb2"/></dir><dir name="Model"><file name="Observer.php" hash="4a9d257c61da42f5725b703200c2aafc"/><file name="Plugin.php" hash="669940a7413871e618ac57b8b2609df8"/></dir><dir name="etc"><file name="config.xml" hash="3c713e32ac8227849dcf196769b5e8bb"/><file name="system.xml" hash="6d98f4b7a28475a5c275669d5df4a93e"/></dir></dir></dir></target><target name="magelocal"><dir name="Mage"><dir name="Core"><dir name="Model"><file name="Config.php" hash="0cbadee9995ef197d56acf002f2ba2e1"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="SafeMage_Plugin.xml" hash="47af3f56cc6cbebba8ec582d9668f369"/></dir></target><target name="mage"><dir name="lib"><dir name="SafeMage"><file name="Plugin.php" hash="ac5ef3c93dce3f84aa2e8cf41e6d1d82"/><dir name="Plugin"><file name="File.php" hash="5e980985ea3371c0ce192d16af3e0eb3"/><file name="Renderer.php" hash="bfc2dd6742bef8e6ff44cc7470de7364"/></dir></dir></dir></target><target name="magelocale"><dir name="en_US"><file name="SafeMage_Plugin.csv" hash="3b3f63e7b038395e4742ef198416c3c7"/></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>