Version Notes
Ampersand_Core v0.2.6
Download this release
Release Info
Developer | Ampersand Commerce |
Extension | Ampersand_Core |
Version | 0.2.6 |
Comparing to | |
See all releases |
Code changes from version 0.2.2 to 0.2.6
- app/code/core/Ampersand/Adminhtml/Block/Catalog/Form/Renderer/Fieldset/ConfigurableElement.php +111 -0
- app/code/core/Ampersand/Adminhtml/Block/System/Config/Renderer/ArrayAbstract.php +140 -0
- app/code/core/Ampersand/Adminhtml/Block/System/Config/Renderer/Datetime.php +18 -0
- app/code/core/Ampersand/Adminhtml/Block/System/Config/Renderer/Hidden.php +16 -0
- app/code/core/Ampersand/Adminhtml/Block/Widget/Container.php +108 -0
- app/code/core/Ampersand/Adminhtml/Block/Widget/Grid.php +18 -0
- app/code/core/Ampersand/Adminhtml/Helper/Data.php +16 -1
- app/code/core/Ampersand/Adminhtml/Model/Entity/Attribute/Frontend/Configurable.php +7 -0
- app/code/core/Ampersand/Adminhtml/Model/Entity/Attribute/Frontend/ConfigurableInterface.php +6 -0
- app/code/core/Ampersand/Adminhtml/Model/Mysql4/Search.php +26 -0
- app/code/core/Ampersand/Adminhtml/Model/Mysql4/Search/Item.php +10 -0
- app/code/core/Ampersand/Adminhtml/Model/Mysql4/Search/Item/Collection.php +9 -0
- app/code/core/Ampersand/Adminhtml/Model/Observer.php +111 -0
- app/code/core/Ampersand/Adminhtml/Model/Search.php +122 -0
- app/code/core/Ampersand/Adminhtml/Model/Search/Item.php +224 -0
- app/code/core/Ampersand/Adminhtml/Model/System/Config/Backend/Void.php +12 -0
- app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/Category.php +51 -0
- app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/ProductAttributeSets.php +64 -0
- app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/ProductAttributes.php +2 -1
- app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/ProductSimpleTypes.php +27 -0
- app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/Stock.php +47 -0
- app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/Website.php +32 -0
- app/code/core/Ampersand/Adminhtml/etc/config.xml +44 -2
- app/code/core/Ampersand/Adminhtml/sql/ampersand_adminhtml_setup/mysql4-install-0.0.2.php +40 -0
- app/code/core/Ampersand/Adminhtml/sql/ampersand_adminhtml_setup/mysql4-upgrade-0.0.2-0.0.3.php +15 -0
- app/code/core/Ampersand/Api/Helper/Data.php +4 -0
- app/code/core/Ampersand/Api/Model/Catalog/Category.php +110 -0
- app/code/core/Ampersand/Api/Model/Catalog/Product.php +659 -0
- app/code/core/Ampersand/Api/Model/Catalog/Product/Attribute.php +23 -0
- app/code/core/Ampersand/Api/Model/Customer/Address.php +18 -0
- app/code/core/Ampersand/Api/Model/Rating.php +35 -0
- app/code/core/Ampersand/Api/Model/Review.php +93 -0
- app/code/core/Ampersand/Api/Model/Sales/Order.php +1095 -0
- app/code/core/Ampersand/Api/Model/Sales/Order/Creditmemo.php +44 -0
- app/code/core/Ampersand/Api/Model/Sales/Order/Invoice.php +44 -0
- app/code/core/Ampersand/Api/Model/Sales/Order/Shipment.php +44 -0
- app/code/core/Ampersand/Api/Model/Sales/Quote.php +319 -0
- app/code/core/Ampersand/Api/etc/api.xml +29 -0
- app/code/core/Ampersand/Api/etc/config.xml +20 -0
- app/code/core/Ampersand/Catalog/Helper/Category.php +160 -0
- app/code/core/Ampersand/Catalog/Helper/Product.php +67 -0
- app/code/core/Ampersand/Catalog/Helper/Product/Attribute.php +63 -0
- app/code/core/Ampersand/Catalog/etc/config.xml +15 -0
- app/code/core/Ampersand/Core/Helper/Data.php +129 -1
- app/code/core/Ampersand/Core/Helper/File.php +33 -0
- app/code/core/Ampersand/Core/Helper/Validate.php +46 -0
- app/code/core/Ampersand/Core/Model/Mysql4/Abstract.php +17 -1
- app/code/core/Ampersand/Core/Model/Mysql4/Collection.php +18 -0
- app/code/core/Ampersand/Core/Model/Mysql4/Collection/Abstract.php +43 -3
- app/code/core/Ampersand/Core/Model/Mysql4/Value.php +10 -0
- app/code/core/Ampersand/Core/Model/Resource/Setup.php +38 -0
- app/code/core/Ampersand/Core/Model/SessionObject.php +71 -0
- app/code/core/Ampersand/Core/Model/Value.php +8 -0
- app/code/core/Ampersand/Core/Model/Versioning.php +109 -0
- app/code/core/Ampersand/Core/changelog.txt +6 -0
- app/code/core/Ampersand/Core/etc/config.xml +22 -1
- app/code/core/Ampersand/Core/sql/ampersand_core_setup/mysql4-install-0.2.3.php +15 -0
- app/code/core/Ampersand/Fakepay/Helper/Data.php +5 -0
- app/code/core/Ampersand/Fakepay/Model/Method.php +14 -0
- app/code/core/Ampersand/Fakepay/etc/config.xml +32 -0
- app/code/core/Ampersand/Fakepay/etc/system.xml +53 -0
- app/code/core/Ampersand/PageCache/Model/Container/NoCache.php +50 -0
- app/code/core/Ampersand/Sales/Helper/Quote.php +116 -0
- app/code/core/Ampersand/Sales/Model/AbstractHelper.php +59 -0
- app/code/core/Ampersand/Sales/Model/InvoiceHelper.php +124 -0
- app/code/core/Ampersand/Sales/Model/OrderHelper.php +102 -0
- app/code/core/Ampersand/Sales/Model/Quote/Address/Total/Discount/PercentageAbstract.php +255 -0
- app/code/core/Ampersand/Sales/etc/config.xml +20 -0
- app/code/core/Ampersand/System/Helper/Data.php +55 -0
- app/code/core/Ampersand/System/Helper/Store.php +51 -0
- app/code/core/Ampersand/System/Model/Cache.php +66 -0
- app/code/core/Ampersand/System/Model/Category.php +218 -0
- app/code/core/Ampersand/System/Model/Cms/Block.php +72 -0
- app/code/core/Ampersand/System/Model/Cms/Page.php +75 -0
- app/code/core/Ampersand/System/Model/Config.php +401 -0
- app/code/core/Ampersand/System/Model/Group.php +192 -0
- app/code/core/Ampersand/System/Model/Images.php +305 -0
- app/code/core/Ampersand/System/Model/Index.php +47 -0
- app/code/core/Ampersand/System/Model/Shipping.php +52 -0
- app/code/core/Ampersand/System/Model/Store.php +203 -0
- app/code/core/Ampersand/System/Model/TaxRate.php +129 -0
- app/code/core/Ampersand/System/Model/TaxRule.php +120 -0
- app/code/core/Ampersand/System/Model/Website.php +135 -0
- app/code/core/Ampersand/System/etc/config.xml +27 -0
- app/design/adminhtml/base/default/template/ampersand_adminhtml/catalog/form/renderer/element/use-config.phtml +35 -0
- app/design/adminhtml/base/default/template/ampersand_adminhtml/system/config-form-array-simple.phtml +76 -0
- app/etc/modules/Ampersand_Core.xml +24 -0
- lib/Ampersand.php +126 -57
- lib/Ampersand/BinPack.php +91 -0
- lib/Ampersand/BinPack/Bin.php +179 -0
- lib/Ampersand/BinPack/BinDimension.php +118 -0
- lib/Ampersand/BinPack/Dimension/DimensionInterface.php +29 -0
- lib/Ampersand/BinPack/Dimension/Standard.php +70 -0
- lib/Ampersand/BinPack/Input.php +68 -0
- lib/Ampersand/BinPack/Item.php +85 -0
- lib/Ampersand/BinPack/ItemDimension.php +49 -0
- lib/Ampersand/BinPack/Output.php +84 -0
- lib/Ampersand/BinPack/Packer/FirstFit.php +28 -0
- lib/Ampersand/BinPack/Packer/JoshBestFit.php +49 -0
- lib/Ampersand/BinPack/Packer/PackerAbstract.php +6 -0
- lib/Ampersand/BinPack/Packer/PackerInterface.php +10 -0
- lib/Ampersand/BinPack/State.php +96 -0
- lib/Ampersand/ClassProvider.php +59 -30
- lib/Ampersand/Db/Test/Abstract.php +99 -59
- lib/Ampersand/Db/Test/Adapter.php +65 -45
- lib/Ampersand/Db/Test/Config.php +257 -103
- lib/Ampersand/Db/Test/Connection.php +45 -33
- lib/Ampersand/Db/Test/Exception.php +5 -10
- lib/Ampersand/Db/Test/MageResource.php +15 -17
- lib/Ampersand/Db/Test/Output/Abstract.php +5 -10
- lib/Ampersand/Db/Test/Output/Statement.php +5 -11
- lib/Ampersand/Db/Test/Output/This.php +5 -11
- lib/Ampersand/Db/Test/Statement.php +55 -36
- lib/Ampersand/Deprecate.php +134 -0
- lib/Ampersand/Deprecate/Registry.php +65 -0
- lib/Ampersand/Exception.php +19 -12
- lib/Ampersand/Filter/Compress.php +44 -37
- lib/Ampersand/Filter/Zend/Filter/Compress.php +197 -81
- lib/Ampersand/Filter/Zend/Filter/Compress/Bz2.php +188 -68
- lib/Ampersand/Filter/Zend/Filter/Compress/CompressAbstract.php +89 -38
- lib/Ampersand/Filter/Zend/Filter/Compress/CompressInterface.php +54 -20
- lib/Ampersand/Filter/Zend/Filter/Compress/Gz.php +228 -89
- lib/Ampersand/Filter/Zend/Filter/Compress/Lzf.php +91 -32
- lib/Ampersand/Filter/Zend/Filter/Compress/Rar.php +252 -93
- lib/Ampersand/Filter/Zend/Filter/Compress/Tar.php +245 -106
- lib/Ampersand/Filter/Zend/Filter/Compress/Zip.php +355 -177
- lib/Ampersand/License.php +159 -158
- lib/Ampersand/License/Helper.php +154 -152
- lib/Ampersand/License/Remote.php +222 -223
- lib/Ampersand/License/ResourceRegistry.php +73 -74
- lib/Ampersand/Object.php +246 -123
- lib/Ampersand/Pairs.php +134 -63
- lib/Ampersand/Random.php +189 -0
- lib/Ampersand/Registry.php +119 -49
- lib/Ampersand/Registry/Abstract.php +19 -28
- lib/Ampersand/Registry/Container.php +107 -38
- lib/Ampersand/Registry/Interface.php +51 -0
- lib/Ampersand/Stack.php +105 -0
- lib/Ampersand/Xml.php +411 -228
- lib/Ampersand/Xml/Config.php +31 -26
- lib/Ampersand/Xml/Element.php +1267 -629
- lib/Ampersand/Xml/Resource.php +130 -62
- package.xml +9 -9
app/code/core/Ampersand/Adminhtml/Block/Catalog/Form/Renderer/Fieldset/ConfigurableElement.php
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Block_Catalog_Form_Renderer_Fieldset_ConfigurableElement
|
3 |
+
extends Mage_Adminhtml_Block_Catalog_Form_Renderer_Fieldset_Element
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @return string
|
7 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
8 |
+
*/
|
9 |
+
public function getElementHtml()
|
10 |
+
{
|
11 |
+
if ($this->getShouldUseConfig()) {
|
12 |
+
$this->setValue($this->_getValueFromConfig());
|
13 |
+
}
|
14 |
+
|
15 |
+
return parent::getElementHtml() . $this->getUseConfigHtml();
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @return string
|
20 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
21 |
+
*/
|
22 |
+
public function getUseConfigHtml()
|
23 |
+
{
|
24 |
+
$origTemplate = $this->_template;
|
25 |
+
|
26 |
+
$this->_template = 'ampersand_adminhtml/catalog/form/renderer/element/use-config.phtml';
|
27 |
+
|
28 |
+
$configHtml = $this->renderView();
|
29 |
+
|
30 |
+
$this->_template = $origTemplate;
|
31 |
+
|
32 |
+
return $configHtml;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return string
|
37 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
38 |
+
*/
|
39 |
+
public function getUseConfigInputName()
|
40 |
+
{
|
41 |
+
$elementName = $this->getElement()->getName();
|
42 |
+
$attributeCode = preg_quote($this->getAttributeCode());
|
43 |
+
$useConfigAttributeCode = preg_quote($this->getUseConfigAttributeCode());
|
44 |
+
|
45 |
+
return preg_replace('/(^|\[)' . $attributeCode . '(\]?).*$/', '$1' . $useConfigAttributeCode . '$2', $elementName);
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @return string
|
50 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
51 |
+
*/
|
52 |
+
public function getUseConfigHiddenInputName()
|
53 |
+
{
|
54 |
+
$elementName = $this->getElement()->getName();
|
55 |
+
$attributeCode = preg_quote($this->getAttributeCode());
|
56 |
+
|
57 |
+
return preg_replace('/(^|\[)' . $attributeCode . '(\]?).*$/', '$1ampersand_adminhtml_use_config$2[]', $elementName);
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @return string
|
62 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
63 |
+
*/
|
64 |
+
public function getUseConfigHiddenInputValue()
|
65 |
+
{
|
66 |
+
return $this->getUseConfigAttributeCode();
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @return bool
|
71 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
72 |
+
*/
|
73 |
+
public function getShouldUseConfig()
|
74 |
+
{
|
75 |
+
if (!$this->getDataObject()->getId()) {
|
76 |
+
return true;
|
77 |
+
}
|
78 |
+
|
79 |
+
if ($this->getDataObject()->getDataUsingMethod($this->getUseConfigAttributeCode())) {
|
80 |
+
return true;
|
81 |
+
}
|
82 |
+
|
83 |
+
return false;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* @return string
|
88 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
89 |
+
*/
|
90 |
+
public function getUseConfigAttributeCode()
|
91 |
+
{
|
92 |
+
$elementName = $this->getElement()->getName();
|
93 |
+
|
94 |
+
if (!preg_match('/\[(?P<attribute_code>[^[]+)\](\[\])*$/', $elementName, $matches)) {
|
95 |
+
throw new Exception(sprintf(
|
96 |
+
'Unable to determine attribute code from element name: "%s"', $elementName
|
97 |
+
));
|
98 |
+
}
|
99 |
+
|
100 |
+
return 'use_config_' . $matches['attribute_code'];
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* @return null
|
105 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
106 |
+
*/
|
107 |
+
protected function _getValueFromConfig()
|
108 |
+
{
|
109 |
+
return null;
|
110 |
+
}
|
111 |
+
}
|
app/code/core/Ampersand/Adminhtml/Block/System/Config/Renderer/ArrayAbstract.php
CHANGED
@@ -18,6 +18,23 @@
|
|
18 |
abstract class Ampersand_Adminhtml_Block_System_Config_Renderer_ArrayAbstract
|
19 |
extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
|
20 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
public function render(Varien_Data_Form_Element_Abstract $element)
|
22 |
{
|
23 |
$html = parent::render($element);
|
@@ -30,7 +47,130 @@ abstract class Ampersand_Adminhtml_Block_System_Config_Renderer_ArrayAbstract
|
|
30 |
|
31 |
$html = $xmlObject->getInnerXml();
|
32 |
}
|
|
|
|
|
33 |
|
34 |
return $html;
|
35 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
}
|
18 |
abstract class Ampersand_Adminhtml_Block_System_Config_Renderer_ArrayAbstract
|
19 |
extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
|
20 |
{
|
21 |
+
protected $_columns = array(true); // workaround for 1.4.0.1 ce
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @return void
|
25 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
26 |
+
*/
|
27 |
+
protected function _construct()
|
28 |
+
{
|
29 |
+
array_shift($this->_columns);
|
30 |
+
parent::_construct();
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
35 |
+
* @return string
|
36 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
37 |
+
*/
|
38 |
public function render(Varien_Data_Form_Element_Abstract $element)
|
39 |
{
|
40 |
$html = parent::render($element);
|
47 |
|
48 |
$html = $xmlObject->getInnerXml();
|
49 |
}
|
50 |
+
|
51 |
+
$html .= $this->_getInitSelectValuesJs($element);
|
52 |
|
53 |
return $html;
|
54 |
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Render block HTML
|
58 |
+
*
|
59 |
+
* Included as workaround for 1.4.0.1 ce
|
60 |
+
*
|
61 |
+
* @return string
|
62 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
63 |
+
*/
|
64 |
+
protected function _toHtml()
|
65 |
+
{
|
66 |
+
if (!$this->_isPreparedToRender) {
|
67 |
+
$this->_prepareToRender();
|
68 |
+
$this->_isPreparedToRender = true;
|
69 |
+
}
|
70 |
+
if (empty($this->_columns)) {
|
71 |
+
throw new Exception('At least one column must be defined.');
|
72 |
+
}
|
73 |
+
|
74 |
+
return parent::_toHtml();
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
79 |
+
* @param string $columnName
|
80 |
+
* @param array $options
|
81 |
+
* @return Mage_Core_Block_Html_Select
|
82 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
83 |
+
*/
|
84 |
+
protected function _getSelectRenderer(Varien_Data_Form_Element_Abstract $element, $columnName,
|
85 |
+
array $options
|
86 |
+
) {
|
87 |
+
$renderer = $this->getLayout()->createBlock(
|
88 |
+
'core/html_select', '',
|
89 |
+
array('is_render_to_js_template' => true)
|
90 |
+
);
|
91 |
+
|
92 |
+
$renderer->setOptions($options);
|
93 |
+
$renderer->setName($this->_getElementName($element, '#{_id}', $columnName));
|
94 |
+
|
95 |
+
return $renderer;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
100 |
+
* @param string $rowId
|
101 |
+
* @param string $columnName
|
102 |
+
* @return string
|
103 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
104 |
+
*/
|
105 |
+
protected function _getElementName(Varien_Data_Form_Element_Abstract $element, $rowId, $columnName)
|
106 |
+
{
|
107 |
+
return "{$element->getName()}[$rowId][$columnName]";
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
112 |
+
* @return string
|
113 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
114 |
+
*/
|
115 |
+
protected function _getInitSelectValuesJs(Varien_Data_Form_Element_Abstract $element)
|
116 |
+
{
|
117 |
+
$updateTypeValueJs = "\n<script type=\"text/javascript\">";
|
118 |
+
|
119 |
+
$updateTypeValuesJsLines = array();
|
120 |
+
|
121 |
+
$rows = $this->getArrayRows();
|
122 |
+
|
123 |
+
if (!is_array($rows)) {
|
124 |
+
return '';
|
125 |
+
}
|
126 |
+
|
127 |
+
foreach ($rows as $_rowId => $_rowData) {
|
128 |
+
foreach ($this->_columns as $__columnName => $__column) {
|
129 |
+
if (!$__column['renderer'] instanceof Mage_Core_Block_Html_Select
|
130 |
+
|| !isset($_rowData[$__columnName])
|
131 |
+
) {
|
132 |
+
continue;
|
133 |
+
}
|
134 |
+
|
135 |
+
$__selectName = $this->_getElementName($element, $_rowId, $__columnName);
|
136 |
+
$updateTypeValuesJsLines[] = "$('$_rowId').down('[name=\"$__selectName\"]')"
|
137 |
+
. ".setValue('{$_rowData[$__columnName]}');";
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
$updateTypeValueJs .= implode("\n", $updateTypeValuesJsLines);
|
142 |
+
|
143 |
+
return $updateTypeValueJs . "\n</script>";
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* @return string
|
148 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
149 |
+
*/
|
150 |
+
public function getHtmlId()
|
151 |
+
{
|
152 |
+
$element = $this->getElement();
|
153 |
+
|
154 |
+
if (!$element->hasHtmlId()) {
|
155 |
+
$element->setHtmlId('_' . uniqid());
|
156 |
+
}
|
157 |
+
|
158 |
+
return $element->getData('html_id');
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* @return array
|
163 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
164 |
+
*/
|
165 |
+
public function getArrayRows()
|
166 |
+
{
|
167 |
+
$arrayRows = array();
|
168 |
+
|
169 |
+
foreach (parent::getArrayRows() as $_oldRowId => $_row) {
|
170 |
+
$_rowId = "{$this->getHtmlId()}_row_{$_oldRowId}";
|
171 |
+
$arrayRows[$_rowId] = $_row->setData('_id', $_rowId);
|
172 |
+
}
|
173 |
+
|
174 |
+
return $arrayRows;
|
175 |
+
}
|
176 |
}
|
app/code/core/Ampersand/Adminhtml/Block/System/Config/Renderer/Datetime.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Block_System_Config_Renderer_Datetime
|
3 |
+
extends Mage_Adminhtml_Block_System_Config_Form_Field
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
7 |
+
* @return string
|
8 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
9 |
+
*/
|
10 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
11 |
+
{
|
12 |
+
$element->setFormat('yyyy-MM-dd HH:mm');
|
13 |
+
$element->setTime(true);
|
14 |
+
$element->setImage($this->getSkinUrl('images/grid-cal.gif'));
|
15 |
+
|
16 |
+
return parent::render($element);
|
17 |
+
}
|
18 |
+
}
|
app/code/core/Ampersand/Adminhtml/Block/System/Config/Renderer/Hidden.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Block_System_Config_Renderer_Hidden
|
3 |
+
extends Mage_Adminhtml_Block_System_Config_Form_Field
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
7 |
+
* @return string
|
8 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
9 |
+
*/
|
10 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
11 |
+
{
|
12 |
+
$html = parent::render($element);
|
13 |
+
|
14 |
+
return preg_replace('/^(\<tr id="[^"]+")\>/', '$1 style="display:none">', $html);
|
15 |
+
}
|
16 |
+
}
|
app/code/core/Ampersand/Adminhtml/Block/Widget/Container.php
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Block_Widget_Container extends Mage_Adminhtml_Block_Widget_Container
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @return Ampersand_Adminhtml_Block_Widget_Container
|
6 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
7 |
+
*/
|
8 |
+
public function addSearchScrollButtons($itemName = null)
|
9 |
+
{
|
10 |
+
if (!$searchItem = $this->getSearchItem()) {
|
11 |
+
return $this;
|
12 |
+
}
|
13 |
+
|
14 |
+
$position = $searchItem->getPosition();
|
15 |
+
$searchSize = $searchItem->getSearch()->getSize();
|
16 |
+
|
17 |
+
if ($itemName) {
|
18 |
+
$label = Mage::helper('ampersand_adminhtml')->__(
|
19 |
+
'%s %s of %s', $itemName, $position, $searchSize
|
20 |
+
);
|
21 |
+
} else {
|
22 |
+
$label = Mage::helper('ampersand_adminhtml')->__(
|
23 |
+
'%s of %s', $position, $searchSize
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
$this->_addButton('search_position', array(
|
28 |
+
'label' => $label,
|
29 |
+
'onclick' => 'window.location.reload();',
|
30 |
+
));
|
31 |
+
|
32 |
+
if ($prevUrl = $this->getPrevSearchItemUrl()) {
|
33 |
+
$this->_addButton('search_prev', array(
|
34 |
+
'label' => '«',
|
35 |
+
'onclick' => 'setLocation(\'' . $prevUrl . '\')',
|
36 |
+
));
|
37 |
+
} else {
|
38 |
+
$this->_addButton('search_prev', array(
|
39 |
+
'label' => '«',
|
40 |
+
'disabled' => true,
|
41 |
+
));
|
42 |
+
}
|
43 |
+
|
44 |
+
if ($nextUrl = $this->getNextSearchItemUrl()) {
|
45 |
+
$this->_addButton('search_next', array(
|
46 |
+
'label' => '»',
|
47 |
+
'onclick' => 'setLocation(\'' . $nextUrl . '\')',
|
48 |
+
));
|
49 |
+
} else {
|
50 |
+
$this->_addButton('search_next', array(
|
51 |
+
'label' => '»',
|
52 |
+
'disabled' => true,
|
53 |
+
));
|
54 |
+
}
|
55 |
+
|
56 |
+
return $this;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @return null|string
|
61 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
62 |
+
*/
|
63 |
+
public function getPrevSearchItemUrl()
|
64 |
+
{
|
65 |
+
if (!$prevItem = $this->getSearchItem()->getPrevSearchItem()) {
|
66 |
+
return null;
|
67 |
+
}
|
68 |
+
|
69 |
+
return $this->getSearchItemUrl($prevItem);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* @return null|string
|
74 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
75 |
+
*/
|
76 |
+
public function getNextSearchItemUrl()
|
77 |
+
{
|
78 |
+
if (!$nextItem = $this->getSearchItem()->getNextSearchItem()) {
|
79 |
+
return null;
|
80 |
+
}
|
81 |
+
|
82 |
+
return $this->getSearchItemUrl($nextItem);
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @return null|string
|
87 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
88 |
+
*/
|
89 |
+
public function getSearchItemUrl(Ampersand_Adminhtml_Model_Search_Item $searchItem)
|
90 |
+
{
|
91 |
+
return null;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* @return null|Ampersand_Adminhtml_Model_Search_Item
|
96 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
97 |
+
*/
|
98 |
+
public function getSearchItem()
|
99 |
+
{
|
100 |
+
if (!$this->hasData('search_item')) {
|
101 |
+
$searchItem = Mage::getSingleton('ampersand_adminhtml/search_item')
|
102 |
+
->getCurrentSearchItem();
|
103 |
+
$this->setData('search_item', $searchItem);
|
104 |
+
}
|
105 |
+
|
106 |
+
return $this->getData('search_item');
|
107 |
+
}
|
108 |
+
}
|
app/code/core/Ampersand/Adminhtml/Block/Widget/Grid.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Block_Widget_Grid extends Mage_Adminhtml_Block_Widget_Grid
|
3 |
+
{
|
4 |
+
public function getSearchInstance()
|
5 |
+
{
|
6 |
+
if (is_null($this->_searchInstance)) {
|
7 |
+
$this->_searchInstance = $this->getCollection()->getSearch();
|
8 |
+
}
|
9 |
+
|
10 |
+
return $this->_searchInstance;
|
11 |
+
}
|
12 |
+
|
13 |
+
public function getSearchItemId($collectionItemId)
|
14 |
+
{
|
15 |
+
return $this->getSearchInstance()->getSearchItem($collectionItemId)
|
16 |
+
->getSearchItemId();
|
17 |
+
}
|
18 |
+
}
|
app/code/core/Ampersand/Adminhtml/Helper/Data.php
CHANGED
@@ -17,5 +17,20 @@
|
|
17 |
*/
|
18 |
class Ampersand_Adminhtml_Helper_Data extends Mage_Core_Helper_Abstract
|
19 |
{
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
}
|
17 |
*/
|
18 |
class Ampersand_Adminhtml_Helper_Data extends Mage_Core_Helper_Abstract
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @param string $configPath
|
22 |
+
* @return string
|
23 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
24 |
+
*/
|
25 |
+
public function getConfigUrl($configPath)
|
26 |
+
{
|
27 |
+
$parts = explode('/', $configPath);
|
28 |
+
if (!$section = reset($parts)) {
|
29 |
+
return null;
|
30 |
+
}
|
31 |
+
|
32 |
+
return Mage::helper('adminhtml')->getUrl('adminhtml/system_config/edit', array(
|
33 |
+
'section' => $section,
|
34 |
+
));
|
35 |
+
}
|
36 |
}
|
app/code/core/Ampersand/Adminhtml/Model/Entity/Attribute/Frontend/Configurable.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_Entity_Attribute_Frontend_Configurable
|
3 |
+
extends Mage_Eav_Model_Entity_Attribute_Frontend_Abstract
|
4 |
+
implements Ampersand_Adminhtml_Model_Entity_Attribute_Frontend_ConfigurableInterface
|
5 |
+
{
|
6 |
+
|
7 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/Entity/Attribute/Frontend/ConfigurableInterface.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
interface Ampersand_Adminhtml_Model_Entity_Attribute_Frontend_ConfigurableInterface
|
3 |
+
extends Mage_Eav_Model_Entity_Attribute_Frontend_Interface
|
4 |
+
{
|
5 |
+
|
6 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/Mysql4/Search.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_Mysql4_Search extends Ampersand_Core_Model_Mysql4_Abstract
|
3 |
+
{
|
4 |
+
protected function _construct()
|
5 |
+
{
|
6 |
+
$this->_init('ampersand_adminhtml/search', 'entity_id');
|
7 |
+
}
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @param Mage_Core_Model_Abstract $object
|
11 |
+
* @return Ampersand_Adminhtml_Model_Mysql4_Search
|
12 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
13 |
+
*/
|
14 |
+
protected function _beforeSave(Mage_Core_Model_Abstract $object)
|
15 |
+
{
|
16 |
+
$now = now();
|
17 |
+
if ($object->isObjectNew()) {
|
18 |
+
$object->setCreatedAt($now);
|
19 |
+
}
|
20 |
+
$object->setUpdatedAt($now);
|
21 |
+
|
22 |
+
parent::_beforeSave($object);
|
23 |
+
|
24 |
+
return $this;
|
25 |
+
}
|
26 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/Mysql4/Search/Item.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_Mysql4_Search_Item extends Ampersand_Core_Model_Mysql4_Abstract
|
3 |
+
{
|
4 |
+
protected $_isPkAutoIncrement = false;
|
5 |
+
|
6 |
+
protected function _construct()
|
7 |
+
{
|
8 |
+
$this->_init('ampersand_adminhtml/search_item', 'search_item_id');
|
9 |
+
}
|
10 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/Mysql4/Search/Item/Collection.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_Mysql4_Search_Item_Collection
|
3 |
+
extends Ampersand_Core_Model_Mysql4_Collection_Abstract
|
4 |
+
{
|
5 |
+
protected function _construct()
|
6 |
+
{
|
7 |
+
$this->_init('ampersand_adminhtml/search_item');
|
8 |
+
}
|
9 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/Observer.php
CHANGED
@@ -20,7 +20,80 @@ class Ampersand_Adminhtml_Model_Observer
|
|
20 |
protected $_gridBlocks = array();
|
21 |
protected $_layoutHandles;
|
22 |
protected $_gridUpdateConfigs = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
public function handleNewBlock(Varien_Event_Observer $observer)
|
25 |
{
|
26 |
$block = $observer->getEvent()->getBlock();
|
@@ -36,15 +109,33 @@ class Ampersand_Adminhtml_Model_Observer
|
|
36 |
case 'adminhtml/widget_grid_massaction':
|
37 |
$this->_executeGridUpdateCallbacks($block, 'massaction');
|
38 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
}
|
40 |
}
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
protected function _prepareGrid($gridBlock)
|
44 |
{
|
45 |
|
46 |
}
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
protected function _executeGridUpdateCallbacks($targetBlock, $type)
|
49 |
{
|
50 |
$gridBlock = $this->_getContainingGrid();
|
@@ -58,6 +149,12 @@ class Ampersand_Adminhtml_Model_Observer
|
|
58 |
}
|
59 |
}
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
protected function _getGridUpdateCallbacks($gridBlock, $type)
|
62 |
{
|
63 |
$callbacks = array();
|
@@ -102,6 +199,11 @@ class Ampersand_Adminhtml_Model_Observer
|
|
102 |
return $callbacks;
|
103 |
}
|
104 |
|
|
|
|
|
|
|
|
|
|
|
105 |
protected function _getGridUpdateConfigs($type)
|
106 |
{
|
107 |
if (!array_key_exists($type, $this->_gridUpdateConfigs)) {
|
@@ -112,6 +214,11 @@ class Ampersand_Adminhtml_Model_Observer
|
|
112 |
return $this->_gridUpdateConfigs[$type];
|
113 |
}
|
114 |
|
|
|
|
|
|
|
|
|
|
|
115 |
protected function _isLayoutHandleActive($handle)
|
116 |
{
|
117 |
if (is_null($this->_layoutHandles)) {
|
@@ -121,6 +228,10 @@ class Ampersand_Adminhtml_Model_Observer
|
|
121 |
return in_array($handle, $this->_layoutHandles);
|
122 |
}
|
123 |
|
|
|
|
|
|
|
|
|
124 |
protected function _getContainingGrid()
|
125 |
{
|
126 |
if (1 == count($this->_gridBlocks)) {
|
20 |
protected $_gridBlocks = array();
|
21 |
protected $_layoutHandles;
|
22 |
protected $_gridUpdateConfigs = array();
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Handle adminhtml_catalog_product_edit_prepare_form event
|
26 |
+
*
|
27 |
+
* @param Varien_Event_Observer $observer
|
28 |
+
* @return void
|
29 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
30 |
+
*/
|
31 |
+
public function handleProductEditForm(Varien_Event_Observer $observer)
|
32 |
+
{
|
33 |
+
$form = $observer->getEvent()->getForm();
|
34 |
+
/* @var $form Varien_Data_Form */
|
35 |
+
|
36 |
+
$this->_applyCustomRenderers($form);
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Handle catalog_product_prepare_save event
|
41 |
+
*
|
42 |
+
* @param Varien_Event_Observer $observer
|
43 |
+
* @return void
|
44 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
45 |
+
*/
|
46 |
+
public function prepareProductForSave(Varien_Event_Observer $observer)
|
47 |
+
{
|
48 |
+
$product = $observer->getEvent()->getProduct();
|
49 |
+
/* @var $product Mage_Catalog_Model_Product */
|
50 |
+
|
51 |
+
if ($useConfigValues = $product->getData('ampersand_adminhtml_use_config')) {
|
52 |
+
foreach ($useConfigValues as $_useConfigAttributeCode) {
|
53 |
+
$product->setData($_useConfigAttributeCode, 0);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
$request = $observer->getEvent()->getRequest();
|
58 |
+
/* @var $request = Mage_Core_Controller_Request_Http */
|
59 |
+
|
60 |
+
if ($useDefaults = $request->getPost('use_default')) {
|
61 |
+
foreach ($useDefaults as $_useDefaultAttributeCode) {
|
62 |
+
$_attribute = $product->getResource()->getAttribute($_useDefaultAttributeCode);
|
63 |
+
if ($_attribute && ($_attribute->getFrontend() instanceof Ampersand_Adminhtml_Model_Entity_Attribute_Frontend_ConfigurableInterface)) {
|
64 |
+
$product->setData('use_config_' . $_useDefaultAttributeCode, false);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @param Varien_Data_Form_Abstract $formElement
|
72 |
+
* @return void
|
73 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
74 |
+
*/
|
75 |
+
protected function _applyCustomRenderers(Varien_Data_Form_Abstract $formElement)
|
76 |
+
{
|
77 |
+
if ($attribute = $formElement->getEntityAttribute()) {
|
78 |
+
if ($attribute->getFrontend() instanceof Ampersand_Adminhtml_Model_Entity_Attribute_Frontend_ConfigurableInterface) {
|
79 |
+
$formElement->setRenderer(Mage::app()->getLayout()->createBlock(
|
80 |
+
'ampersand_adminhtml/catalog_form_renderer_fieldset_configurableElement'
|
81 |
+
));
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
foreach ($formElement->getElements() as $_childElement) {
|
86 |
+
$this->_applyCustomRenderers($_childElement);
|
87 |
+
}
|
88 |
+
}
|
89 |
|
90 |
+
/**
|
91 |
+
* Handle core_block_abstract_prepare_layout_after event
|
92 |
+
*
|
93 |
+
* @param Varien_Event_Observer $observer
|
94 |
+
* @return void
|
95 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
96 |
+
*/
|
97 |
public function handleNewBlock(Varien_Event_Observer $observer)
|
98 |
{
|
99 |
$block = $observer->getEvent()->getBlock();
|
109 |
case 'adminhtml/widget_grid_massaction':
|
110 |
$this->_executeGridUpdateCallbacks($block, 'massaction');
|
111 |
break;
|
112 |
+
default:
|
113 |
+
if ($block instanceof Mage_Adminhtml_Block_Widget_Grid_Column) {
|
114 |
+
$this->_executeGridUpdateCallbacks($block, 'column');
|
115 |
+
} else if ($block instanceof Mage_Adminhtml_Block_Widget_Grid_Massaction_Abstract) {
|
116 |
+
$this->_executeGridUpdateCallbacks($block, 'massaction');
|
117 |
+
}
|
118 |
+
break;
|
119 |
}
|
120 |
}
|
121 |
}
|
122 |
|
123 |
+
/**
|
124 |
+
* @param mixed $gridBlock
|
125 |
+
* @return void
|
126 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
127 |
+
*/
|
128 |
protected function _prepareGrid($gridBlock)
|
129 |
{
|
130 |
|
131 |
}
|
132 |
|
133 |
+
/**
|
134 |
+
* @param mixed $targetBlock
|
135 |
+
* @param string $type
|
136 |
+
* @return void
|
137 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
138 |
+
*/
|
139 |
protected function _executeGridUpdateCallbacks($targetBlock, $type)
|
140 |
{
|
141 |
$gridBlock = $this->_getContainingGrid();
|
149 |
}
|
150 |
}
|
151 |
|
152 |
+
/**
|
153 |
+
* @param mixed $gridBlock
|
154 |
+
* @param string $type
|
155 |
+
* @return array
|
156 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
157 |
+
*/
|
158 |
protected function _getGridUpdateCallbacks($gridBlock, $type)
|
159 |
{
|
160 |
$callbacks = array();
|
199 |
return $callbacks;
|
200 |
}
|
201 |
|
202 |
+
/**
|
203 |
+
* @param string $type
|
204 |
+
* @return array
|
205 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
206 |
+
*/
|
207 |
protected function _getGridUpdateConfigs($type)
|
208 |
{
|
209 |
if (!array_key_exists($type, $this->_gridUpdateConfigs)) {
|
214 |
return $this->_gridUpdateConfigs[$type];
|
215 |
}
|
216 |
|
217 |
+
/**
|
218 |
+
* @param string $handle
|
219 |
+
* @return bool
|
220 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
221 |
+
*/
|
222 |
protected function _isLayoutHandleActive($handle)
|
223 |
{
|
224 |
if (is_null($this->_layoutHandles)) {
|
228 |
return in_array($handle, $this->_layoutHandles);
|
229 |
}
|
230 |
|
231 |
+
/**
|
232 |
+
* @return null|Mage_Adminhtml_Block_Widget_Grid
|
233 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
234 |
+
*/
|
235 |
protected function _getContainingGrid()
|
236 |
{
|
237 |
if (1 == count($this->_gridBlocks)) {
|
app/code/core/Ampersand/Adminhtml/Model/Search.php
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_Search extends Ampersand_Core_Model_Abstract
|
3 |
+
{
|
4 |
+
protected function _construct()
|
5 |
+
{
|
6 |
+
$this->_init('ampersand_adminhtml/search');
|
7 |
+
}
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @param Varien_Data_Collection_Db $collection
|
11 |
+
* @param int $collectionSize OPTIONAL Pass the total number of records in the search to prevent
|
12 |
+
* an additional database query
|
13 |
+
* @return Ampersand_Adminhtml_Model_Search
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
15 |
+
*/
|
16 |
+
public function fromCollection(Varien_Data_Collection_Db $collection, $collectionSize = null)
|
17 |
+
{
|
18 |
+
if (is_null($collectionSize)) {
|
19 |
+
$collectionSize = $collection->getSize();
|
20 |
+
}
|
21 |
+
|
22 |
+
$this->setSize($collectionSize);
|
23 |
+
|
24 |
+
$this->setExpiresAt($this->_getExpiresAt());
|
25 |
+
|
26 |
+
$this->setSingleItemSelectSql(
|
27 |
+
$this->_getSingleItemSelect($collection)->assemble()
|
28 |
+
);
|
29 |
+
|
30 |
+
$this->setNeighbourItemsSelectSql(
|
31 |
+
$this->_getNeighbourItemsSelect($collection)->assemble()
|
32 |
+
);
|
33 |
+
|
34 |
+
$orderPart = $collection->getSelect()->getPart(Zend_Db_Select::ORDER);
|
35 |
+
if (!is_array($orderPart)) {
|
36 |
+
$this->setOrderPart($orderPart);
|
37 |
+
}
|
38 |
+
|
39 |
+
$this->setSearchItems($this->_getSearchItems($collection));
|
40 |
+
|
41 |
+
return $this;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @param mixed $collectionItemId
|
46 |
+
* @return null|Ampersand_Adminhtml_Model_Search_Item
|
47 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
48 |
+
*/
|
49 |
+
public function getSearchItem($collectionItemId)
|
50 |
+
{
|
51 |
+
return $this->getData("search_items/$collectionItemId");
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @param Varien_Data_Collection_Db $collection
|
56 |
+
* @return array
|
57 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
58 |
+
*/
|
59 |
+
protected function _getSearchItems(Varien_Data_Collection_Db $collection)
|
60 |
+
{
|
61 |
+
$searchItems = array();
|
62 |
+
|
63 |
+
foreach ($collection as $_collectionItemId => $_collectionItem) {
|
64 |
+
$searchItems[$_collectionItemId] = Mage::getModel('ampersand_adminhtml/search_item')
|
65 |
+
->fromCollectionItem($_collectionItemId, $_collectionItem, $collection);
|
66 |
+
}
|
67 |
+
|
68 |
+
return $searchItems;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* @return string
|
73 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
74 |
+
*/
|
75 |
+
protected function _getExpiresAt()
|
76 |
+
{
|
77 |
+
return date('Y-m-d H:i:s', time() + 30);
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @param Varien_Data_Collection_Db $collection
|
82 |
+
* @return Zend_Db_Select
|
83 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
84 |
+
*/
|
85 |
+
protected function _getSingleItemSelect(Varien_Data_Collection_Db $collection)
|
86 |
+
{
|
87 |
+
$select = clone $collection->getSelect();
|
88 |
+
|
89 |
+
return $select;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* @param Varien_Data_Collection_Db $collection
|
94 |
+
* @return Zend_Db_Select
|
95 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
96 |
+
*/
|
97 |
+
protected function _getNeighbourItemsSelect(Varien_Data_Collection_Db $collection)
|
98 |
+
{
|
99 |
+
$select = clone $collection->getSelect();
|
100 |
+
|
101 |
+
return $select;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @return Ampersand_Adminhtml_Model_Search
|
106 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
107 |
+
*/
|
108 |
+
protected function _afterSave()
|
109 |
+
{
|
110 |
+
if (!$this->getOrigData($this->getIdFieldName())) {
|
111 |
+
foreach ($this->getSearchItems() as $_searchItem) {
|
112 |
+
$_searchItem->setSearchId($this->getId())
|
113 |
+
->setExpiresAt($this->getExpiresAt())
|
114 |
+
->save();
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
parent::_afterSave();
|
119 |
+
|
120 |
+
return $this;
|
121 |
+
}
|
122 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/Search/Item.php
ADDED
@@ -0,0 +1,224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_Search_Item extends Ampersand_Core_Model_Abstract
|
3 |
+
{
|
4 |
+
const DEFAULT_GET_PARAM = 'search_item';
|
5 |
+
|
6 |
+
protected function _construct()
|
7 |
+
{
|
8 |
+
$this->_init('ampersand_adminhtml/search_item');
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @return null|Ampersand_Adminhtml_Model_Search_Item
|
13 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
14 |
+
*/
|
15 |
+
public function getCurrentSearchItem()
|
16 |
+
{
|
17 |
+
$searchItemId = Mage::app()->getFrontController()->getRequest()
|
18 |
+
->getParam(self::DEFAULT_GET_PARAM);
|
19 |
+
|
20 |
+
if (!$searchItemId) {
|
21 |
+
return null;
|
22 |
+
}
|
23 |
+
|
24 |
+
$searchItem = Mage::getModel('ampersand_adminhtml/search_item')
|
25 |
+
->load($searchItemId);
|
26 |
+
|
27 |
+
if (!$searchItem->getId()) {
|
28 |
+
return null;
|
29 |
+
}
|
30 |
+
|
31 |
+
if (!$searchItem->getIsActive()) {
|
32 |
+
$searchItem->refreshData();
|
33 |
+
}
|
34 |
+
|
35 |
+
if (!$searchItem->getIsActive()) {
|
36 |
+
return null;
|
37 |
+
}
|
38 |
+
|
39 |
+
return $searchItem;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @return null|Ampersand_Adminhtml_Model_Search_Item
|
44 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
45 |
+
*/
|
46 |
+
public function getPrevSearchItem()
|
47 |
+
{
|
48 |
+
return $this->getSibling($this->getPrevCollectionItemId());
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @return null|Ampersand_Adminhtml_Model_Search_Item
|
53 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
54 |
+
*/
|
55 |
+
public function getNextSearchItem()
|
56 |
+
{
|
57 |
+
return $this->getSibling($this->getNextCollectionItemId());
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @return null|Ampersand_Adminhtml_Model_Search_Item
|
62 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
63 |
+
*/
|
64 |
+
public function getSibling($collectionItemId)
|
65 |
+
{
|
66 |
+
$item = $this->getSiblingCollection()
|
67 |
+
->addFieldToFilter('collection_item_id', $collectionItemId)
|
68 |
+
->setPageSize(1)
|
69 |
+
->getFirstItem();
|
70 |
+
|
71 |
+
if (!$item->getId()) {
|
72 |
+
return null;
|
73 |
+
}
|
74 |
+
|
75 |
+
return $item;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @return Ampersand_Adminhtml_Model_Mysql4_Search_Item_Collection
|
80 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
81 |
+
*/
|
82 |
+
public function getSiblingCollection()
|
83 |
+
{
|
84 |
+
return $this->getCollection()->addFieldToFilter('search_id', $this->getSearchId());
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* @return bool
|
89 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
90 |
+
*/
|
91 |
+
public function getIsActive()
|
92 |
+
{
|
93 |
+
return true;
|
94 |
+
|
95 |
+
if (!$expiresAt = $this->getExpiresAt()) {
|
96 |
+
return false;
|
97 |
+
}
|
98 |
+
|
99 |
+
$expiresAtObject = new Zend_Date($expiresAt, 'y-MM-dd HH:mm:ss');
|
100 |
+
$currentTimeObject = new Zend_Date();
|
101 |
+
|
102 |
+
return $expiresAtObject->isEarlier($currentTimeObject);
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* @param mixed $collectionItemId
|
107 |
+
* @param object $collectionItem
|
108 |
+
* @param Varien_Data_Collection_Db $collection
|
109 |
+
* @return Ampersand_Adminhtml_Model_Search_Item
|
110 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
111 |
+
*/
|
112 |
+
public function fromCollectionItem($collectionItemId, $collectionItem,
|
113 |
+
Varien_Data_Collection_Db $collection
|
114 |
+
) {
|
115 |
+
$collectionItems = $collection->getItems();
|
116 |
+
$collectionItemIds = array_keys($collectionItems);
|
117 |
+
|
118 |
+
$itemIndex = array_search($collectionItemId, $collectionItemIds);
|
119 |
+
|
120 |
+
$prevCollectionItemId = $this->_getPrevCollectionItemId($itemIndex, $collectionItemIds);
|
121 |
+
$nextCollectionItemId = $this->_getNextCollectionItemId($itemIndex, $collectionItemIds);
|
122 |
+
|
123 |
+
$this->setId($this->_getSearchItemId());
|
124 |
+
$this->setCollectionItemId($collectionItemId);
|
125 |
+
$this->setPrevCollectionItemId($prevCollectionItemId);
|
126 |
+
$this->setNextCollectionItemId($nextCollectionItemId);
|
127 |
+
$this->setPosition(1 + $itemIndex);
|
128 |
+
|
129 |
+
return $this;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @return Ampersand_Adminhtml_Model_Search_Item
|
134 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
135 |
+
*/
|
136 |
+
public function refreshData()
|
137 |
+
{
|
138 |
+
$search = $this->getSearch();
|
139 |
+
$collectionItemId = $this->getCollectionItemId();
|
140 |
+
|
141 |
+
$itemSelectSql = $search->setSingleItemSelectSql();
|
142 |
+
$itemSelectSql = $this->_prepareSingleItemSelectSql($itemSelectSql, $collectionItemId);
|
143 |
+
$collectionItemData = $this->getResource()->getReadConnection()->fetchRow($itemSelectSql);
|
144 |
+
|
145 |
+
return $this;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* @param string $sql
|
150 |
+
* @param mixed $collectionItemId
|
151 |
+
* @return string
|
152 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
153 |
+
*/
|
154 |
+
protected function _prepareSingleItemSelectSql($sql, $collectionItemId)
|
155 |
+
{
|
156 |
+
return $sql;
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* @param string $sql
|
161 |
+
* @param mixed $collectionItemId
|
162 |
+
* @param array $orderValues
|
163 |
+
* @return string
|
164 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
165 |
+
*/
|
166 |
+
protected function _prepareNeighbourItemsSelectSql($sql, $collectionItemId, $orderValues)
|
167 |
+
{
|
168 |
+
return $sql;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* @return Ampersand_Adminhtml_Model_Search
|
173 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
174 |
+
*/
|
175 |
+
public function getSearch()
|
176 |
+
{
|
177 |
+
if (!$this->hasData('search')) {
|
178 |
+
$search = Mage::getModel('ampersand_adminhtml/search')
|
179 |
+
->load($this->getSearchId());
|
180 |
+
$this->setData('search', $search);
|
181 |
+
}
|
182 |
+
|
183 |
+
return $this->getData('search');
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* @param int $itemIndex
|
188 |
+
* @param array $collectionItemIds
|
189 |
+
* @return mixed
|
190 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
191 |
+
*/
|
192 |
+
protected function _getPrevCollectionItemId($itemIndex, array $collectionItemIds)
|
193 |
+
{
|
194 |
+
if (!$itemIndex) {
|
195 |
+
return null;
|
196 |
+
}
|
197 |
+
|
198 |
+
return $collectionItemIds[$itemIndex - 1];
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* @param int $itemIndex
|
203 |
+
* @param array $collectionItemIds
|
204 |
+
* @return mixed
|
205 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
206 |
+
*/
|
207 |
+
protected function _getNextCollectionItemId($itemIndex, array $collectionItemIds)
|
208 |
+
{
|
209 |
+
if (1 + $itemIndex >= count($collectionItemIds)) {
|
210 |
+
return null;
|
211 |
+
}
|
212 |
+
|
213 |
+
return $collectionItemIds[1 + $itemIndex];
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* @return string
|
218 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
219 |
+
*/
|
220 |
+
protected function _getSearchItemId()
|
221 |
+
{
|
222 |
+
return base64_encode(substr(microtime(true), 3) . mt_rand(100, 999));
|
223 |
+
}
|
224 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/System/Config/Backend/Void.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_System_Config_Backend_Void extends Mage_Core_Model_Config_Data
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @return Ampersand_Adminhtml_Model_System_Config_Backend_Obscure
|
6 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
7 |
+
*/
|
8 |
+
public function save()
|
9 |
+
{
|
10 |
+
return $this;
|
11 |
+
}
|
12 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/Category.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Magento Suite
|
4 |
+
*
|
5 |
+
* @category Ampersand_Magento
|
6 |
+
* @package Ampersand_Adminhtml
|
7 |
+
* @subpackage Model
|
8 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
9 |
+
* @license TBC
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @category Ampersand_Magento
|
14 |
+
* @package Ampersand_Adminhtml
|
15 |
+
* @subpackage Model
|
16 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
17 |
+
*/
|
18 |
+
class Ampersand_Adminhtml_Model_System_Config_Source_Category
|
19 |
+
{
|
20 |
+
public function toOptionArray()
|
21 |
+
{
|
22 |
+
$tree = Mage::getResourceSingleton('catalog/category_tree')->load();
|
23 |
+
|
24 |
+
$collection = Mage::getResourceModel('catalog/category_collection')
|
25 |
+
->setStoreId(0)
|
26 |
+
->addAttributeToSelect('name');
|
27 |
+
$tree->addCollectionData($collection, true);
|
28 |
+
|
29 |
+
$rootNode = $tree->getNodeById(1);
|
30 |
+
|
31 |
+
return $this->_nodeToOptionArray($rootNode);
|
32 |
+
}
|
33 |
+
|
34 |
+
protected function _nodeToOptionArray($node, $level = 0)
|
35 |
+
{
|
36 |
+
$options = array();
|
37 |
+
|
38 |
+
foreach ($node->getChildren() as $_childNode) {
|
39 |
+
$options[] = array(
|
40 |
+
'value' => $_childNode->getId(),
|
41 |
+
'label' => str_repeat('..', $level) . ' ' . $_childNode->getName(),
|
42 |
+
);
|
43 |
+
|
44 |
+
if ($_childNode->hasChildren()) {
|
45 |
+
$options = array_merge($options, $this->_nodeToOptionArray($_childNode, $level + 1));
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
return $options;
|
50 |
+
}
|
51 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/ProductAttributeSets.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Magento Suite
|
4 |
+
*
|
5 |
+
* @category Ampersand_Magento
|
6 |
+
* @package Ampersand_Adminhtml
|
7 |
+
* @subpackage Model
|
8 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
9 |
+
* @license TBC
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @category Ampersand_Magento
|
14 |
+
* @package Ampersand_Adminhtml
|
15 |
+
* @subpackage Model
|
16 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
17 |
+
*/
|
18 |
+
class Ampersand_Adminhtml_Model_System_Config_Source_ProductAttributeSets
|
19 |
+
{
|
20 |
+
public function toOptionArray()
|
21 |
+
{
|
22 |
+
$options = array();
|
23 |
+
|
24 |
+
$labels = $this->getPairs();
|
25 |
+
|
26 |
+
foreach ($labels as $_attributeSetId => $_label) {
|
27 |
+
$options[] = array(
|
28 |
+
'value' => $_attributeSetId,
|
29 |
+
'label' => $_label,
|
30 |
+
);
|
31 |
+
}
|
32 |
+
|
33 |
+
return $options;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function getPairs()
|
37 |
+
{
|
38 |
+
$attributeCollection = $this->_getAttributeSetCollection();
|
39 |
+
|
40 |
+
$codes = $attributeCollection->getColumnValues('attribute_set_id');
|
41 |
+
$labels = $attributeCollection->getColumnValues('attribute_set_name');
|
42 |
+
|
43 |
+
$pairs = array();
|
44 |
+
|
45 |
+
foreach (array_combine($codes, $labels) as $_code => $_label) {
|
46 |
+
if (strlen($_code) && strlen($_label)) {
|
47 |
+
$pairs[$_code] = $_label;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
return $pairs;
|
52 |
+
}
|
53 |
+
|
54 |
+
protected function _getAttributeSetCollection()
|
55 |
+
{
|
56 |
+
return Mage::getResourceModel('eav/entity_attribute_set_collection')
|
57 |
+
->setEntityTypeFilter($this->_getProductEntityTypeId());
|
58 |
+
}
|
59 |
+
|
60 |
+
protected function _getProductEntityTypeId()
|
61 |
+
{
|
62 |
+
return Mage::getResourceModel('catalog/product')->getTypeId();
|
63 |
+
}
|
64 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/ProductAttributes.php
CHANGED
@@ -53,6 +53,7 @@ class Ampersand_Adminhtml_Model_System_Config_Source_ProductAttributes
|
|
53 |
|
54 |
protected function _getAttributeCollection()
|
55 |
{
|
56 |
-
return Mage::getResourceModel('catalog/product_attribute_collection')
|
|
|
57 |
}
|
58 |
}
|
53 |
|
54 |
protected function _getAttributeCollection()
|
55 |
{
|
56 |
+
return Mage::getResourceModel('catalog/product_attribute_collection')
|
57 |
+
->setOrder('frontend_label', 'asc');
|
58 |
}
|
59 |
}
|
app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/ProductSimpleTypes.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_System_Config_Source_ProductSimpleTypes
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @return array
|
6 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
7 |
+
*/
|
8 |
+
public function toOptionArray()
|
9 |
+
{
|
10 |
+
$typeLabels = Mage_Catalog_Model_Product_Type::getOptionArray();
|
11 |
+
$compositeTypeIds = Mage_Catalog_Model_Product_Type::getCompositeTypes();
|
12 |
+
asort($typeLabels);
|
13 |
+
|
14 |
+
$options = array();
|
15 |
+
|
16 |
+
foreach ($typeLabels as $_typeId => $_label) {
|
17 |
+
if (!in_array($_typeId, $compositeTypeIds)) {
|
18 |
+
$options[] = array(
|
19 |
+
'value' => $_typeId,
|
20 |
+
'label' => $_label,
|
21 |
+
);
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
return $options;
|
26 |
+
}
|
27 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/Stock.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_System_Config_Source_Stock
|
3 |
+
{
|
4 |
+
/** @var null|array */
|
5 |
+
protected $_optionArray;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @return array
|
9 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
10 |
+
*/
|
11 |
+
public function toOptionArray()
|
12 |
+
{
|
13 |
+
return Mage::getSingleton('ampersand_adminhtml/system_config_source_stock')
|
14 |
+
->getOptionArray();
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @return array
|
19 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
20 |
+
*/
|
21 |
+
public function getOptionArray()
|
22 |
+
{
|
23 |
+
if (is_null($this->_optionArray)) {
|
24 |
+
$this->_optionArray = $this->_getOptionArray();
|
25 |
+
}
|
26 |
+
|
27 |
+
return $this->_optionArray;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @return array
|
32 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
33 |
+
*/
|
34 |
+
protected function _getOptionArray()
|
35 |
+
{
|
36 |
+
$stockResource = Mage::getResourceSingleton('cataloginventory/stock');
|
37 |
+
|
38 |
+
$select = $stockResource->getReadConnection()->select()
|
39 |
+
->from($stockResource->getMainTable(), array(
|
40 |
+
'value' => $stockResource->getIdFieldName(),
|
41 |
+
'label' => 'stock_name',
|
42 |
+
))
|
43 |
+
->order('stock_name', 'asc');
|
44 |
+
|
45 |
+
return $stockResource->getReadConnection()->fetchAll($select);
|
46 |
+
}
|
47 |
+
}
|
app/code/core/Ampersand/Adminhtml/Model/System/Config/Source/Website.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Adminhtml_Model_System_Config_Source_Website
|
3 |
+
{
|
4 |
+
/** @var null|array */
|
5 |
+
protected $_optionArray;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @return array
|
9 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
10 |
+
*/
|
11 |
+
public function toOptionArray()
|
12 |
+
{
|
13 |
+
return Mage::getSingleton('ampersand_adminhtml/system_config_source_website')
|
14 |
+
->getOptionArray();
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @return array
|
19 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
20 |
+
*/
|
21 |
+
public function getOptionArray()
|
22 |
+
{
|
23 |
+
if (is_null($this->_optionArray)) {
|
24 |
+
$this->_optionArray = Mage::getResourceModel('core/website_collection')
|
25 |
+
->setFlag('load_default_website', true)
|
26 |
+
->setOrder('name', 'asc')
|
27 |
+
->toOptionArray();
|
28 |
+
}
|
29 |
+
|
30 |
+
return $this->_optionArray;
|
31 |
+
}
|
32 |
+
}
|
app/code/core/Ampersand/Adminhtml/etc/config.xml
CHANGED
@@ -1,5 +1,10 @@
|
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
<config>
|
|
|
|
|
|
|
|
|
|
|
3 |
<global>
|
4 |
<blocks>
|
5 |
<ampersand_adminhtml>
|
@@ -14,12 +19,31 @@
|
|
14 |
<models>
|
15 |
<ampersand_adminhtml>
|
16 |
<class>Ampersand_Adminhtml_Model</class>
|
|
|
17 |
</ampersand_adminhtml>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
</models>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
</global>
|
20 |
<adminhtml>
|
21 |
<events>
|
22 |
-
<
|
23 |
<observers>
|
24 |
<ampersand_adminhtml>
|
25 |
<type>singleton</type>
|
@@ -27,7 +51,25 @@
|
|
27 |
<method>handleNewBlock</method>
|
28 |
</ampersand_adminhtml>
|
29 |
</observers>
|
30 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
</events>
|
32 |
</adminhtml>
|
33 |
</config>
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
<config>
|
3 |
+
<modules>
|
4 |
+
<Ampersand_Adminhtml>
|
5 |
+
<version>0.0.3</version>
|
6 |
+
</Ampersand_Adminhtml>
|
7 |
+
</modules>
|
8 |
<global>
|
9 |
<blocks>
|
10 |
<ampersand_adminhtml>
|
19 |
<models>
|
20 |
<ampersand_adminhtml>
|
21 |
<class>Ampersand_Adminhtml_Model</class>
|
22 |
+
<resourceModel>ampersand_adminhtml_mysql4</resourceModel>
|
23 |
</ampersand_adminhtml>
|
24 |
+
<ampersand_adminhtml_mysql4>
|
25 |
+
<class>Ampersand_Adminhtml_Model_Mysql4</class>
|
26 |
+
<entities>
|
27 |
+
<search>
|
28 |
+
<table>ampersand_adminhtml_search</table>
|
29 |
+
</search>
|
30 |
+
<search_item>
|
31 |
+
<table>ampersand_adminhtml_search_item</table>
|
32 |
+
</search_item>
|
33 |
+
</entities>
|
34 |
+
</ampersand_adminhtml_mysql4>
|
35 |
</models>
|
36 |
+
<resources>
|
37 |
+
<ampersand_adminhtml_setup>
|
38 |
+
<setup>
|
39 |
+
<module>Ampersand_Adminhtml</module>
|
40 |
+
</setup>
|
41 |
+
</ampersand_adminhtml_setup>
|
42 |
+
</resources>
|
43 |
</global>
|
44 |
<adminhtml>
|
45 |
<events>
|
46 |
+
<core_block_abstract_prepare_layout_after>
|
47 |
<observers>
|
48 |
<ampersand_adminhtml>
|
49 |
<type>singleton</type>
|
51 |
<method>handleNewBlock</method>
|
52 |
</ampersand_adminhtml>
|
53 |
</observers>
|
54 |
+
</core_block_abstract_prepare_layout_after>
|
55 |
+
<adminhtml_catalog_product_edit_prepare_form>
|
56 |
+
<observers>
|
57 |
+
<ampersand_adminhtml>
|
58 |
+
<type>singleton</type>
|
59 |
+
<class>ampersand_adminhtml/observer</class>
|
60 |
+
<method>handleProductEditForm</method>
|
61 |
+
</ampersand_adminhtml>
|
62 |
+
</observers>
|
63 |
+
</adminhtml_catalog_product_edit_prepare_form>
|
64 |
+
<catalog_product_prepare_save>
|
65 |
+
<observers>
|
66 |
+
<ampersand_adminhtml>
|
67 |
+
<type>singleton</type>
|
68 |
+
<class>ampersand_adminhtml/observer</class>
|
69 |
+
<method>prepareProductForSave</method>
|
70 |
+
</ampersand_adminhtml>
|
71 |
+
</observers>
|
72 |
+
</catalog_product_prepare_save>
|
73 |
</events>
|
74 |
</adminhtml>
|
75 |
</config>
|
app/code/core/Ampersand/Adminhtml/sql/ampersand_adminhtml_setup/mysql4-install-0.0.2.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$this->startSetup();
|
4 |
+
|
5 |
+
$this->run("
|
6 |
+
|
7 |
+
CREATE TABLE `{$this->getTable('ampersand_adminhtml/search')}` (
|
8 |
+
`entity_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
9 |
+
`single_item_select_sql` TEXT NOT NULL,
|
10 |
+
`neighbour_items_select_sql` TEXT NOT NULL,
|
11 |
+
`created_at` DATETIME NOT NULL,
|
12 |
+
`expires_at` DATETIME NOT NULL,
|
13 |
+
`order_part` TEXT NOT NULL,
|
14 |
+
`size` INT UNSIGNED NOT NULL,
|
15 |
+
PRIMARY KEY (`entity_id`),
|
16 |
+
KEY (`expires_at`)
|
17 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
18 |
+
|
19 |
+
CREATE TABLE `{$this->getTable('ampersand_adminhtml/search_item')}` (
|
20 |
+
`search_item_id` CHAR(20),
|
21 |
+
`search_id` INT UNSIGNED NOT NULL,
|
22 |
+
`expires_at` DATETIME NOT NULL,
|
23 |
+
`position` INT UNSIGNED NOT NULL,
|
24 |
+
`collection_item_id` VARCHAR(32),
|
25 |
+
`prev_collection_item_id` VARCHAR(32),
|
26 |
+
`next_collection_item_id` VARCHAR(32),
|
27 |
+
PRIMARY KEY (`search_item_id`),
|
28 |
+
KEY (`expires_at`),
|
29 |
+
KEY (`position`),
|
30 |
+
UNIQUE KEY (`search_id`, `collection_item_id`),
|
31 |
+
CONSTRAINT `AMPRSND_ADMNHTML_SRCH_ITM_SRCH_ID_SRCH_ENTTY_ID` FOREIGN KEY (`search_id`)
|
32 |
+
REFERENCES `{$this->getTable('ampersand_adminhtml/search')}` (`entity_id`) ON DELETE CASCADE
|
33 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
34 |
+
|
35 |
+
# select ... from ... join ... where `field` %s ... order by `field` %s ...
|
36 |
+
# select ... from ... join ... where `field` %s ...
|
37 |
+
|
38 |
+
");
|
39 |
+
|
40 |
+
$this->endSetup();
|
app/code/core/Ampersand/Adminhtml/sql/ampersand_adminhtml_setup/mysql4-upgrade-0.0.2-0.0.3.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$this->startSetup();
|
4 |
+
|
5 |
+
$this->run("
|
6 |
+
|
7 |
+
ALTER TABLE `{$this->getTable('ampersand_adminhtml/search')}`
|
8 |
+
ADD COLUMN `size_select_sql` TEXT NOT NULL,
|
9 |
+
ADD COLUMN `neighbour_items_count_select_sql` TEXT NOT NULL,
|
10 |
+
ADD COLUMN `collection_item_id_field` VARCHAR(24) NOT NULL
|
11 |
+
;
|
12 |
+
|
13 |
+
");
|
14 |
+
|
15 |
+
$this->endSetup();
|
app/code/core/Ampersand/Api/Helper/Data.php
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Api_Helper_Data extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
}
|
app/code/core/Ampersand/Api/Model/Catalog/Category.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Api_Model_Catalog_Category
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Fields which can fall back to default setting
|
6 |
+
*
|
7 |
+
* @var array $_userPostDataConfigFields
|
8 |
+
*/
|
9 |
+
protected $_usePostDataConfigFields = array(
|
10 |
+
'default_sort_by',
|
11 |
+
'available_sort_by',
|
12 |
+
);
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Creates a category
|
16 |
+
*
|
17 |
+
* @param array $categoryData
|
18 |
+
* @return Mage_Catalog_Model_Category
|
19 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
20 |
+
*/
|
21 |
+
public function create(array $categoryData)
|
22 |
+
{
|
23 |
+
if (!array_key_exists('parent_id', $categoryData)) {
|
24 |
+
Mage::throwException('parent_id was not specified in category data.');
|
25 |
+
}
|
26 |
+
if (!array_key_exists('store_id', $categoryData)) {
|
27 |
+
Mage::throwException('store_id was not specified in category data.');
|
28 |
+
}
|
29 |
+
|
30 |
+
$parentCategory = Mage::getModel('catalog/category')
|
31 |
+
->setStoreId($categoryData['store_id'])
|
32 |
+
->load($categoryData['parent_id']);
|
33 |
+
|
34 |
+
// some fields are required but by using post data config they will 'use default value'
|
35 |
+
foreach ($this->_usePostDataConfigFields as $_field) {
|
36 |
+
if (!array_key_exists($_field, $categoryData) || empty($categoryData[$_field])) {
|
37 |
+
$categoryData[$_field] = '';
|
38 |
+
$categoryData['use_post_data_config'][] = $_field;
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
$category = Mage::getModel('catalog/category')
|
43 |
+
->setData($categoryData)
|
44 |
+
->setPath(implode('/', $parentCategory->getPathIds()));
|
45 |
+
|
46 |
+
$category->setAttributeSetId($category->getDefaultAttributeSetId());
|
47 |
+
|
48 |
+
if (true !== ($validate = $category->validate())) {
|
49 |
+
foreach ($validate as $code => $error) {
|
50 |
+
if ($error === true) {
|
51 |
+
Mage::throwException("Attribute $code is required.");
|
52 |
+
} else {
|
53 |
+
Mage::throwException($error);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
$category->save();
|
59 |
+
|
60 |
+
return $category;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* recursive method to create a tree like category nodes array into magento.
|
65 |
+
* $tree= Arrary(
|
66 |
+
* 'nodeName' => Array(
|
67 |
+
* '_attributes' => Array(
|
68 |
+
* 'is_active' => true,
|
69 |
+
* 'include_in_menu' => true,
|
70 |
+
* 'otherAttribute' => 'blablabla',
|
71 |
+
* ),
|
72 |
+
* '_children' => Array(
|
73 |
+
* 'childNodeName' => Array( ... )
|
74 |
+
* ),
|
75 |
+
* ),
|
76 |
+
* );
|
77 |
+
*
|
78 |
+
* @param array $tree
|
79 |
+
* @param type $parentId
|
80 |
+
*/
|
81 |
+
public function createFromArray(array $tree, $parentId)
|
82 |
+
{
|
83 |
+
foreach ($tree['_children'] as $key => $value) {
|
84 |
+
$categoryDataArray = $this->_populateCategoryData($key, $value['_attributes']);
|
85 |
+
$categoryDataArray['parent_id']=$parentId;
|
86 |
+
$createdCategory = $this->create($categoryDataArray);
|
87 |
+
|
88 |
+
if (array_key_exists('_children', $value)) {
|
89 |
+
$this->createFromArray($value, $createdCategory->getId());
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
protected function _populateCategoryData($name, $attributes)
|
95 |
+
{
|
96 |
+
$categoryDataArray = Array();
|
97 |
+
|
98 |
+
$categoryDataArray['name'] = $name;
|
99 |
+
$categoryDataArray['is_active'] = true;
|
100 |
+
$categoryDataArray['include_in_menu'] = true;
|
101 |
+
$categoryDataArray['store_id'] = null;
|
102 |
+
$categoryDataArray['parent_id'] = null;
|
103 |
+
$categoryDataArray['url_key'] = null;
|
104 |
+
|
105 |
+
foreach ($attributes as $key => $value) {
|
106 |
+
$categoryDataArray[$key] = $value;
|
107 |
+
}
|
108 |
+
return $categoryDataArray;
|
109 |
+
}
|
110 |
+
}
|
app/code/core/Ampersand/Api/Model/Catalog/Product.php
ADDED
@@ -0,0 +1,659 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @example
|
4 |
+
$productApi = Mage::getSingleton('ampersand_api/catalog_product');
|
5 |
+
|
6 |
+
$productApi->create(array(
|
7 |
+
'sku' => 'Configurable',
|
8 |
+
'name' => 'Configurable Product',
|
9 |
+
'type_id' => Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE,
|
10 |
+
'attribute_set_id' => '4',
|
11 |
+
'status' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED,
|
12 |
+
'configurable_attributes' => array('size', 'color'),
|
13 |
+
'images' => array('Configurable-1.jpg'),
|
14 |
+
));
|
15 |
+
|
16 |
+
$productApi->update(array(
|
17 |
+
'sku' => 'Simple',
|
18 |
+
'name' => 'Simple Product',
|
19 |
+
'type_id' => Mage_Catalog_Model_Product_Type::TYPE_SIMPLE,
|
20 |
+
'attribute_set_id' => '4',
|
21 |
+
'status' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED,
|
22 |
+
'parent_sku' => 'Configurable',
|
23 |
+
'color' => '4',
|
24 |
+
'size' => '6',
|
25 |
+
));
|
26 |
+
*/
|
27 |
+
class Ampersand_Api_Model_Catalog_Product
|
28 |
+
{
|
29 |
+
/**
|
30 |
+
* Flag to store whether we need to save the product or not.
|
31 |
+
*
|
32 |
+
* @var bool $_productHasChanges
|
33 |
+
*/
|
34 |
+
protected $_productHasChanges;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Cache of product attributes by attribute set id.
|
38 |
+
*
|
39 |
+
* @var array $_productAttributes
|
40 |
+
*/
|
41 |
+
protected $_productAttributes = array();
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Required attributes for correct saving of products.
|
45 |
+
*
|
46 |
+
* @var array $_requiredAttributes
|
47 |
+
*/
|
48 |
+
protected $_requiredAttributes = array(
|
49 |
+
'sku',
|
50 |
+
'name',
|
51 |
+
'type_id',
|
52 |
+
'attribute_set_id',
|
53 |
+
'status',
|
54 |
+
);
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Proxy method to update().
|
58 |
+
*
|
59 |
+
* @param array $productData
|
60 |
+
* @return Mage_Catalog_Model_Product
|
61 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
62 |
+
*/
|
63 |
+
public function create(array $productData)
|
64 |
+
{
|
65 |
+
return $this->update($productData);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Create or update products with additional functionality like defining configurable
|
70 |
+
* attributes, assigning simple products to configurables and assinging product images.
|
71 |
+
*
|
72 |
+
* @param array $productData
|
73 |
+
* @return Mage_Catalog_Model_Product
|
74 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
75 |
+
*/
|
76 |
+
public function update(array $productData)
|
77 |
+
{
|
78 |
+
$this->_setProductHasChanges(false);
|
79 |
+
|
80 |
+
if (!array_key_exists('sku', $productData)) {
|
81 |
+
Mage::throwException('Missing SKU');
|
82 |
+
}
|
83 |
+
|
84 |
+
$product = Mage::getModel('catalog/product');
|
85 |
+
if ($productId = $this->_getProductIdBySku($productData['sku'])) {
|
86 |
+
$product->load($productId);
|
87 |
+
}
|
88 |
+
|
89 |
+
$validAttributes = $this->_getProductAttributes($product);
|
90 |
+
foreach ($productData as $_key => $_value) {
|
91 |
+
if (array_key_exists($_key, $validAttributes)
|
92 |
+
&& ($product->getData($_key) != $_value)) {
|
93 |
+
$this->_setProductHasChanges(true);
|
94 |
+
}
|
95 |
+
$product->setData($_key, $_value);
|
96 |
+
}
|
97 |
+
|
98 |
+
if (!$product->getAttributeSetId()) {
|
99 |
+
$product->setAttributeSetId($product->getDefaultAttributeSetId());
|
100 |
+
}
|
101 |
+
|
102 |
+
if (array_key_exists('images', $productData)) {
|
103 |
+
$this->addImages($product, $productData['images']);
|
104 |
+
}
|
105 |
+
|
106 |
+
if (array_key_exists('configurable_attributes', $productData)) {
|
107 |
+
$this->setConfigurableAttributes($product, $productData['configurable_attributes']);
|
108 |
+
}
|
109 |
+
|
110 |
+
$this->_validateRequiredAttributes($product);
|
111 |
+
|
112 |
+
if (!$product->getId() || $this->_getProductHasChanges()) {
|
113 |
+
$product->save();
|
114 |
+
}
|
115 |
+
|
116 |
+
if (array_key_exists('parent_sku', $productData)) {
|
117 |
+
$this->setParentProduct($product->getId(), $productData['parent_sku']);
|
118 |
+
}
|
119 |
+
|
120 |
+
return $product;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Replace any product images with the filenames supplied in the images array.
|
125 |
+
*
|
126 |
+
* @param Mage_Catalog_Model_Product $product
|
127 |
+
* @param array|string $images Array of image filenames or single filename
|
128 |
+
* @return Ampersand_Api_Model_Catalog_Product
|
129 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
130 |
+
*/
|
131 |
+
public function addImages(Mage_Catalog_Model_Product $product, $images)
|
132 |
+
{
|
133 |
+
if (empty($images)) {
|
134 |
+
return $this;
|
135 |
+
}
|
136 |
+
|
137 |
+
if (!is_array($images)) {
|
138 |
+
$images = array($images);
|
139 |
+
}
|
140 |
+
|
141 |
+
$imagesToAdd = array();
|
142 |
+
foreach ($images as $_image) {
|
143 |
+
$_imageFile = $this->_getMediaImportDir() . DS . $_image;
|
144 |
+
if (file_exists($_imageFile)) {
|
145 |
+
$imagesToAdd[] = $_imageFile;
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
if (count($imagesToAdd) > 0) {
|
150 |
+
$setAttributes = $product->getTypeInstance()->getSetAttributes();
|
151 |
+
if (array_key_exists('media_gallery', $setAttributes)) {
|
152 |
+
$gallery = $setAttributes['media_gallery'];
|
153 |
+
$galleryData = $product->getMediaGallery();
|
154 |
+
foreach ($galleryData['images'] as $_imageToDelete) {
|
155 |
+
if ($gallery->getBackend()->getImage($product, $_imageToDelete['file'])) {
|
156 |
+
$gallery->getBackend()->removeImage($product, $_imageToDelete['file']);
|
157 |
+
}
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
foreach ($imagesToAdd as $_imageFile) {
|
162 |
+
$product->addImageToMediaGallery($_imageFile, null, true, false);
|
163 |
+
}
|
164 |
+
|
165 |
+
$galleryData = $product->getMediaGallery();
|
166 |
+
foreach ($galleryData['images'] as $_newImage) {
|
167 |
+
if ($_newImage['removed'] == 1 || $_newImage['disabled'] == 1) {
|
168 |
+
continue;
|
169 |
+
}
|
170 |
+
|
171 |
+
$product->setImage($_newImage['file']);
|
172 |
+
$product->setSmallImage($_newImage['file']);
|
173 |
+
$product->setThumbnail($_newImage['file']);
|
174 |
+
|
175 |
+
break;
|
176 |
+
}
|
177 |
+
|
178 |
+
$this->_setProductHasChanges(true);
|
179 |
+
}
|
180 |
+
|
181 |
+
return $this;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Define which attributes should be configurable for a configurable product.
|
186 |
+
*
|
187 |
+
* @param Mage_Catalog_Model_Product $product
|
188 |
+
* @param array|string $attributes OPTIONAL Array of attribute codes or a single attribute code
|
189 |
+
* as a string
|
190 |
+
* @return Ampersand_Api_Model_Catalog_Product
|
191 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
192 |
+
*/
|
193 |
+
public function setConfigurableAttributes(Mage_Catalog_Model_Product $product,
|
194 |
+
$attributes = array()
|
195 |
+
) {
|
196 |
+
// non configurable products cannot have configurable attributes
|
197 |
+
if (!$product->isConfigurable()) {
|
198 |
+
return;
|
199 |
+
}
|
200 |
+
|
201 |
+
if (!is_array($attributes)) {
|
202 |
+
$attributes = array($attributes);
|
203 |
+
}
|
204 |
+
|
205 |
+
// Get the configurable products already assigned to this product
|
206 |
+
$existingAttributeIds = array();
|
207 |
+
$existingAttributeCollection = $product->getTypeInstance()
|
208 |
+
->getConfigurableAttributeCollection();
|
209 |
+
foreach ($existingAttributeCollection as $_existingAttribute) {
|
210 |
+
$_attributeCode = $_existingAttribute->getProductAttribute()->getAttributeCode();
|
211 |
+
if (!in_array($_attributeCode, $attributes)) {
|
212 |
+
$_existingAttribute->delete();
|
213 |
+
} else {
|
214 |
+
$existingAttributeIds[$_existingAttribute->getAttributeId()] = $_existingAttribute;
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
// Set any required attributes that dont already exist
|
219 |
+
$newAttributes = array();
|
220 |
+
foreach ($attributes as $_position => $_attributeCode) {
|
221 |
+
$_attribute = Mage::getResourceModel('catalog/product')->getAttribute($_attributeCode);
|
222 |
+
if (!$_attribute || !$_attribute->getId() || !$_attribute->getIsConfigurable()) {
|
223 |
+
Mage::throwException("Configurable attribute `{$_attributeCode}` does not exist");
|
224 |
+
}
|
225 |
+
|
226 |
+
if (array_key_exists($_attribute->getId(), $existingAttributeIds)) {
|
227 |
+
$_existingAttribute = $existingAttributeIds[$_attribute->getId()];
|
228 |
+
if ($_existingAttribute->getPosition() != $_position) {
|
229 |
+
$_existingAttribute->setPosition($_position)->save();
|
230 |
+
}
|
231 |
+
} else {
|
232 |
+
$newAttributes[] = array(
|
233 |
+
'id' => null,
|
234 |
+
'label' => $_attribute->getFrontendLabel(),
|
235 |
+
'use_default' => '1',
|
236 |
+
'position' => $_position,
|
237 |
+
'values' => array(),
|
238 |
+
'attribute_id' => $_attribute->getAttributeId(),
|
239 |
+
'attribute_code' => $_attribute->getAttributeCode(),
|
240 |
+
'frontend_label' => $_attribute->getFrontendLabel(),
|
241 |
+
'store_label' => $_attribute->getFrontendLabel(),
|
242 |
+
'html_id' => "configurable__attribute_{$_position}",
|
243 |
+
);
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
if (count($newAttributes) > 0) {
|
248 |
+
$product->setConfigurableAttributesData($newAttributes);
|
249 |
+
$this->_setProductHasChanges(true);
|
250 |
+
}
|
251 |
+
|
252 |
+
return $this;
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Assign a simple product to its parent.
|
257 |
+
*
|
258 |
+
* @param int $productId
|
259 |
+
* @param string $parentSku
|
260 |
+
* @return Ampersand_Api_Model_Catalog_Product
|
261 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
262 |
+
*/
|
263 |
+
public function setParentProduct($productId, $parentSku)
|
264 |
+
{
|
265 |
+
if (!$parentId = $this->_getProductIdBySku($parentSku)) {
|
266 |
+
Mage::throwException("Parent product with SKU `{$parentSku}` does not exist");
|
267 |
+
}
|
268 |
+
|
269 |
+
// Link so simple products appear as configurable product associated products
|
270 |
+
$this->_addRelationship('catalog/product_super_link', array(
|
271 |
+
'parent_id' => $parentId,
|
272 |
+
'product_id' => $productId,
|
273 |
+
));
|
274 |
+
|
275 |
+
// Link so indexing knows these two products are related
|
276 |
+
$this->_addRelationship('catalog/product_relation', array(
|
277 |
+
'parent_id' => $parentId,
|
278 |
+
'child_id' => $productId,
|
279 |
+
));
|
280 |
+
|
281 |
+
return $this;
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Ensure all required attributes have valid values for saving.
|
286 |
+
*
|
287 |
+
* @param Mage_Catalog_Model_Product $product
|
288 |
+
* @return Ampersand_Api_Model_Catalog_Product
|
289 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
290 |
+
*/
|
291 |
+
protected function _validateRequiredAttributes(Mage_Catalog_Model_Product $product)
|
292 |
+
{
|
293 |
+
foreach ($this->_requiredAttributes as $_attribute) {
|
294 |
+
$_value = $product->getData($_attribute);
|
295 |
+
if (is_null($_value) || $_value == '') {
|
296 |
+
Mage::throwException("Missing `{$_attribute}`");
|
297 |
+
}
|
298 |
+
}
|
299 |
+
|
300 |
+
return $this;
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
* Update product relationship fields in the database.
|
305 |
+
*
|
306 |
+
* @param string $tableAlias
|
307 |
+
* @param array $data
|
308 |
+
* @return Ampersand_Api_Model_Catalog_Product
|
309 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
310 |
+
*/
|
311 |
+
protected function _addRelationship($tableAlias, array $data)
|
312 |
+
{
|
313 |
+
if (!$data) {
|
314 |
+
return $this;
|
315 |
+
}
|
316 |
+
|
317 |
+
$resource = Mage::getSingleton('core/resource');
|
318 |
+
$connection = $resource->getConnection('core_write');
|
319 |
+
$select = $connection->select();
|
320 |
+
|
321 |
+
$select->from($resource->getTableName($tableAlias), key($data));
|
322 |
+
foreach ($data as $_field => $_value) {
|
323 |
+
$select->where("{$_field}=?", $_value);
|
324 |
+
}
|
325 |
+
|
326 |
+
if (!count($connection->fetchCol($select))) {
|
327 |
+
$connection->insertMultiple($resource->getTableName($tableAlias), array($data));
|
328 |
+
}
|
329 |
+
|
330 |
+
return $this;
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Proxy method for retrieving a product ID by sku.
|
335 |
+
*
|
336 |
+
* @param string $sku
|
337 |
+
* @return int
|
338 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
339 |
+
*/
|
340 |
+
protected function _getProductIdBySku($sku)
|
341 |
+
{
|
342 |
+
return Mage::getResourceModel('catalog/product')->getIdBySku($sku);
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Location of product image files.
|
347 |
+
*
|
348 |
+
* @return string
|
349 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
350 |
+
*/
|
351 |
+
public function getMediaImportDir()
|
352 |
+
{
|
353 |
+
return $this->_getMediaImportDir();
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Location of product image files.
|
358 |
+
*
|
359 |
+
* @return string
|
360 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
361 |
+
*/
|
362 |
+
protected function _getMediaImportDir()
|
363 |
+
{
|
364 |
+
return Mage::getBaseDir('media') . DS . 'import' . DS;
|
365 |
+
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Retrieve the flag to determine whether a product needs to be saved.
|
369 |
+
*
|
370 |
+
* @return bool
|
371 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
372 |
+
*/
|
373 |
+
protected function _getProductHasChanges()
|
374 |
+
{
|
375 |
+
return $this->_productHasChanges;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Update the flag to determine whether a product needs to be saved.
|
380 |
+
*
|
381 |
+
* @param bool $value
|
382 |
+
* @return Ampersand_Api_Model_Catalog_Product
|
383 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
384 |
+
*/
|
385 |
+
protected function _setProductHasChanges($value)
|
386 |
+
{
|
387 |
+
$this->_productHasChanges = $value;
|
388 |
+
|
389 |
+
return $this;
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Retrieve valid product attributes.
|
394 |
+
*
|
395 |
+
* @param Mage_Catalog_Model_Product $product
|
396 |
+
* @return array
|
397 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
398 |
+
*/
|
399 |
+
protected function _getProductAttributes(Mage_Catalog_Model_Product $product)
|
400 |
+
{
|
401 |
+
$attributeSetId = $product->getAttributeSetId();
|
402 |
+
|
403 |
+
if (array_key_exists($attributeSetId, $this->_productAttributes)) {
|
404 |
+
return $this->_productAttributes[$attributeSetId];
|
405 |
+
}
|
406 |
+
|
407 |
+
$entityType = Mage::getModel('eav/entity_type')->loadByCode('catalog_product');
|
408 |
+
|
409 |
+
$attributeCollection = Mage::getResourceModel('eav/entity_attribute_collection')
|
410 |
+
->setEntityTypeFilter($entityType)
|
411 |
+
->setAttributeSetFilter($product->getAttributeSetId());
|
412 |
+
|
413 |
+
$attributes = array();
|
414 |
+
foreach ($attributeCollection as $_attribute) {
|
415 |
+
$attributes[$_attribute->getAttributeCode()] = $_attribute;
|
416 |
+
}
|
417 |
+
|
418 |
+
$this->_productAttributes[$attributeSetId] = $attributes;
|
419 |
+
|
420 |
+
return $attributes;
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* @param string $productSku
|
425 |
+
* @param string $storeCode
|
426 |
+
* @return array
|
427 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
428 |
+
*/
|
429 |
+
public function info($productSku, $storeCode)
|
430 |
+
{
|
431 |
+
$this->_setStore($storeCode);
|
432 |
+
$product = Mage::getModel('catalog/product');
|
433 |
+
$product->load($product->getIdBySkU($productSku));
|
434 |
+
if (!$product->getId()) {
|
435 |
+
return;
|
436 |
+
}
|
437 |
+
|
438 |
+
if ($product->getStatus() != Mage_Catalog_Model_Product_Status::STATUS_ENABLED
|
439 |
+
|| !$product->isVisibleInSiteVisibility()
|
440 |
+
|| !$product->isSaleable()
|
441 |
+
) {
|
442 |
+
return;
|
443 |
+
}
|
444 |
+
|
445 |
+
return $this->_prepareProductArray($product);
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* @param string $storeCode
|
450 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
451 |
+
*/
|
452 |
+
protected function _setStore($storeCode)
|
453 |
+
{
|
454 |
+
$stores = Mage::app()->getStores(false, true);
|
455 |
+
|
456 |
+
if (!array_key_exists($storeCode, $stores)) {
|
457 |
+
return;
|
458 |
+
}
|
459 |
+
|
460 |
+
Mage::app()->setCurrentStore($storeCode);
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* @param Mage_Catalog_Model_Product $product
|
465 |
+
* @return array
|
466 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
467 |
+
*/
|
468 |
+
protected function _prepareProductArray(Mage_Catalog_Model_Product $product)
|
469 |
+
{
|
470 |
+
$productData = array();
|
471 |
+
|
472 |
+
$productData['id'] = $product->getId();
|
473 |
+
$productData['name'] = $product->getName();
|
474 |
+
$productData['sku'] = $product->getSku();
|
475 |
+
$productData['price'] = $product->getPrice();
|
476 |
+
$productData['type'] = $product->getTypeId();
|
477 |
+
$productData['default_qty'] = $this->_getProductDefaultQty($product);
|
478 |
+
$productData['url'] = $product->getProductUrl();
|
479 |
+
$productData['image'] = $product->getImage();
|
480 |
+
$productData['add_to_cart_url'] = $this->_getAddToCartUrl($product);
|
481 |
+
$productData['query_string_add_to_cart_url'] = $this->_getQueryStringAddToCartUrl($product);
|
482 |
+
$productData['redirect_to_cart'] = $this->_isAddingAProductRedirectsToCart();
|
483 |
+
$productData['attributes'] = $this->_getProductOptions($product);
|
484 |
+
|
485 |
+
return $productData;
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Get default qty - either as preconfigured, or as 1.
|
490 |
+
* Also restricts it by minimal qty.
|
491 |
+
*
|
492 |
+
* @param null|Mage_Catalog_Model_Product
|
493 |
+
*
|
494 |
+
* @return int|float
|
495 |
+
*/
|
496 |
+
protected function _getProductDefaultQty($product)
|
497 |
+
{
|
498 |
+
$qty = $this->_getMinimalQty($product);
|
499 |
+
$config = $product->getPreconfiguredValues();
|
500 |
+
$configQty = $config->getQty();
|
501 |
+
if ($configQty > $qty) {
|
502 |
+
$qty = $configQty;
|
503 |
+
}
|
504 |
+
|
505 |
+
return $qty;
|
506 |
+
}
|
507 |
+
|
508 |
+
/**
|
509 |
+
* @param Mage_Catalog_Model_Product $product
|
510 |
+
* @return Ambigous <number, NULL>|NULL
|
511 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
512 |
+
*/
|
513 |
+
protected function _getMinimalQty($product)
|
514 |
+
{
|
515 |
+
if (($stockItem = $product->getStockItem())) {
|
516 |
+
return ($stockItem->getMinSaleQty() && $stockItem->getMinSaleQty() > 0
|
517 |
+
? $stockItem->getMinSaleQty() * 1
|
518 |
+
: null);
|
519 |
+
}
|
520 |
+
|
521 |
+
return null;
|
522 |
+
}
|
523 |
+
|
524 |
+
/**
|
525 |
+
* @param Mage_Catalog_Model_Product $product
|
526 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
527 |
+
*/
|
528 |
+
protected function _getConfigurableAttributes($product)
|
529 |
+
{
|
530 |
+
return $product->getTypeInstance(true)
|
531 |
+
->getConfigurableAttributes($product);
|
532 |
+
}
|
533 |
+
|
534 |
+
/**
|
535 |
+
* @param Mage_Catalog_Model_Product $product
|
536 |
+
* @return array
|
537 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
538 |
+
*/
|
539 |
+
protected function _getAllowProducts($product)
|
540 |
+
{
|
541 |
+
$products = array();
|
542 |
+
$allProducts = $product->getTypeInstance(true)
|
543 |
+
->getUsedProducts(null, $product);
|
544 |
+
foreach ($allProducts as $allowedProduct) {
|
545 |
+
if ($allowedProduct->isSaleable()) {
|
546 |
+
$products[] = $allowedProduct;
|
547 |
+
}
|
548 |
+
}
|
549 |
+
|
550 |
+
return $products;
|
551 |
+
}
|
552 |
+
|
553 |
+
/**
|
554 |
+
* @param Mage_Catalog_Model_Product $_product
|
555 |
+
* @return array
|
556 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
557 |
+
*/
|
558 |
+
protected function _getProductOptions($_product)
|
559 |
+
{
|
560 |
+
if (!$_product->isConfigurable()) {
|
561 |
+
return array();
|
562 |
+
}
|
563 |
+
|
564 |
+
$options = array();
|
565 |
+
$info = array();
|
566 |
+
$currentProduct = $_product;
|
567 |
+
|
568 |
+
foreach ($this->_getAllowProducts($currentProduct) as $product) {
|
569 |
+
$productId = $product->getId();
|
570 |
+
foreach ($this->_getConfigurableAttributes($currentProduct) as $attribute) {
|
571 |
+
$productAttribute = $attribute->getProductAttribute();
|
572 |
+
$productAttributeId = $productAttribute->getId();
|
573 |
+
$attributeValue = $product->getData($productAttribute->getAttributeCode());
|
574 |
+
if (!isset($options[$productAttributeId])) {
|
575 |
+
$options[$productAttributeId] = array();
|
576 |
+
}
|
577 |
+
|
578 |
+
if (!isset($options[$productAttributeId][$attributeValue])) {
|
579 |
+
$options[$productAttributeId][$attributeValue] = array();
|
580 |
+
}
|
581 |
+
$options[$productAttributeId][$attributeValue][] = $productId;
|
582 |
+
}
|
583 |
+
}
|
584 |
+
|
585 |
+
foreach ($this->_getConfigurableAttributes($currentProduct) as $attribute) {
|
586 |
+
$productAttribute = $attribute->getProductAttribute();
|
587 |
+
$attributeId = $productAttribute->getId();
|
588 |
+
$info[$attributeId] = array(
|
589 |
+
'code' => $productAttribute->getAttributeCode(),
|
590 |
+
'label' => $attribute->getLabel(),
|
591 |
+
'options' => array()
|
592 |
+
);
|
593 |
+
|
594 |
+
$prices = $attribute->getPrices();
|
595 |
+
if (is_array($prices)) {
|
596 |
+
foreach ($prices as $value) {
|
597 |
+
if(!$this->_validateAttributeValue($attributeId, $value, $options)) {
|
598 |
+
continue;
|
599 |
+
}
|
600 |
+
|
601 |
+
$info[$attributeId]['options'][] = array(
|
602 |
+
'id' => $value['value_index'],
|
603 |
+
'label' => $value['label'],
|
604 |
+
);
|
605 |
+
}
|
606 |
+
}
|
607 |
+
}
|
608 |
+
|
609 |
+
return $info;
|
610 |
+
}
|
611 |
+
|
612 |
+
/**
|
613 |
+
* Validating of super product option value
|
614 |
+
*
|
615 |
+
* @param array $attributeId
|
616 |
+
* @param array $value
|
617 |
+
* @param array $options
|
618 |
+
* @return boolean
|
619 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
620 |
+
*/
|
621 |
+
protected function _validateAttributeValue($attributeId, &$value, &$options)
|
622 |
+
{
|
623 |
+
if(isset($options[$attributeId][$value['value_index']])) {
|
624 |
+
return true;
|
625 |
+
}
|
626 |
+
|
627 |
+
return false;
|
628 |
+
}
|
629 |
+
|
630 |
+
/**
|
631 |
+
* @param Mage_Catalog_Model_Product $product
|
632 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
633 |
+
*/
|
634 |
+
protected function _getAddToCartUrl($product)
|
635 |
+
{
|
636 |
+
return Mage::helper('checkout/cart')->getAddUrl($product, array());
|
637 |
+
}
|
638 |
+
|
639 |
+
/**
|
640 |
+
* @param Mage_Catalog_Model_Product $product
|
641 |
+
* @return string
|
642 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
643 |
+
*/
|
644 |
+
protected function _getQueryStringAddToCartUrl($product)
|
645 |
+
{
|
646 |
+
return Mage::getUrl('checkout/cart/add', array('product' => $product->getId()));
|
647 |
+
}
|
648 |
+
|
649 |
+
/**
|
650 |
+
* Config 'checkout/cart/redirect_to_cart
|
651 |
+
*
|
652 |
+
* @return boolean
|
653 |
+
* @author Aditya Godara (aditya.godara@ampersandcommerce.com)
|
654 |
+
*/
|
655 |
+
protected function _isAddingAProductRedirectsToCart()
|
656 |
+
{
|
657 |
+
return (boolean) Mage::getStoreConfig('checkout/cart/redirect_to_cart');
|
658 |
+
}
|
659 |
+
}
|
app/code/core/Ampersand/Api/Model/Catalog/Product/Attribute.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Api_Model_Catalog_Product_Attribute
|
3 |
+
{
|
4 |
+
public function getAttributeSet($code)
|
5 |
+
{
|
6 |
+
$attributeSet = Mage::getResourceModel('eav/entity_attribute_set_collection')
|
7 |
+
->setEntityTypeFilter($this->getEntityTypeId('catalog_product'))
|
8 |
+
->addFieldToFilter('attribute_set_name', $code)
|
9 |
+
->getFirstItem();
|
10 |
+
|
11 |
+
return $attributeSet;
|
12 |
+
}
|
13 |
+
|
14 |
+
public function getEntityTypeId($code)
|
15 |
+
{
|
16 |
+
return Mage::getModel('eav/entity_type')->loadByCode($code)->getId();
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* These methods remain here for backwards compatability,
|
21 |
+
* however they are more suited to Ampersand_Catalog_Helper_Product_Attribute.
|
22 |
+
*/
|
23 |
+
}
|
app/code/core/Ampersand/Api/Model/Customer/Address.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Api_Model_Customer_Address extends Mage_Customer_Model_Address_Api
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @param Mage_Customer_Model_Address_Abstract $address
|
6 |
+
* @param array $filter
|
7 |
+
* @return string
|
8 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
9 |
+
*/
|
10 |
+
public function getAllowedAttributes($address, array $filter = null)
|
11 |
+
{
|
12 |
+
$attributes = parent::getAllowedAttributes($address, $filter);
|
13 |
+
|
14 |
+
$attributes['should_ignore_validation'] = null;
|
15 |
+
|
16 |
+
return $attributes;
|
17 |
+
}
|
18 |
+
}
|
app/code/core/Ampersand/Api/Model/Rating.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Api_Model_Rating
|
3 |
+
{
|
4 |
+
public function create($ratingCode, $storeIds = array())
|
5 |
+
{
|
6 |
+
$rating = Mage::getModel('rating/rating')->load($ratingCode, 'rating_code');
|
7 |
+
if ($rating->getId()) {
|
8 |
+
return;
|
9 |
+
}
|
10 |
+
|
11 |
+
$stores = array(0);
|
12 |
+
foreach ($storeIds as $_storeId) {
|
13 |
+
$stores[] = Mage::app()->getStore($_storeId)->getId();
|
14 |
+
}
|
15 |
+
|
16 |
+
$entityId = $rating->getEntityIdByCode(Mage_Review_Model_Review::ENTITY_PRODUCT_CODE);
|
17 |
+
|
18 |
+
$rating
|
19 |
+
->setRatingCode($ratingCode)
|
20 |
+
->setStores($stores)
|
21 |
+
->setEntityId($entityId);
|
22 |
+
|
23 |
+
$rating->save();
|
24 |
+
|
25 |
+
$options = array(1,2,3,4,5);
|
26 |
+
foreach ($options as $_optionValue) {
|
27 |
+
Mage::getModel('rating/rating_option')
|
28 |
+
->setCode($_optionValue)
|
29 |
+
->setValue($_optionValue)
|
30 |
+
->setRatingId($rating->getId())
|
31 |
+
->setPosition($_optionValue)
|
32 |
+
->save();
|
33 |
+
}
|
34 |
+
}
|
35 |
+
}
|
app/code/core/Ampersand/Api/Model/Review.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Ampersand_Api_Model_Review
|
4 |
+
{
|
5 |
+
/*
|
6 |
+
$reviewApi->create('JRMTEST2', array(
|
7 |
+
'nickname' => 'review nickname', // required
|
8 |
+
'title' => 'review title', // required
|
9 |
+
'detail' => 'review detail', // required
|
10 |
+
'status_id' => Mage_Review_Model_Review::STATUS_PENDING, // optional (default: Mage_Review_Model_Review::STATUS_APPROVED)
|
11 |
+
'customer_id' => 18, // optional (default: guest) // Use either customer_id
|
12 |
+
'customer_email' => '1322135044@ampersandcommerce.com', // OR customer_email
|
13 |
+
'created_at' => 123123123, //optional (default: current time) // optional
|
14 |
+
'rating_id' => 4, // optional
|
15 |
+
), 1, array(
|
16 |
+
'Price' => '4',
|
17 |
+
'Value' => '5',
|
18 |
+
'Quality' => '3',
|
19 |
+
)
|
20 |
+
);
|
21 |
+
*/
|
22 |
+
|
23 |
+
public function create($sku, $reviewData, $storeId = null, $ratings = null)
|
24 |
+
{
|
25 |
+
$store = Mage::app()->getStore($storeId);
|
26 |
+
|
27 |
+
if (!array_key_exists('customer_id', $reviewData)) {
|
28 |
+
if (array_key_exists('customer_email', $reviewData)) {
|
29 |
+
$customer = Mage::getModel('customer/customer')
|
30 |
+
->setWebsiteId(Mage::app()->getStore($store)->getWebsiteId())
|
31 |
+
->loadByEmail($reviewData['customer_email']);
|
32 |
+
|
33 |
+
$reviewData['customer_id'] = $customer->getId();
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
$product = Mage::getModel('catalog/product')->setStoreId($store->getId());
|
38 |
+
$product->load($product->getIdBySku($sku));
|
39 |
+
|
40 |
+
$review = Mage::getModel('review/review');
|
41 |
+
$entityId = $review->getEntityIdByCode(Mage_Review_Model_Review::ENTITY_PRODUCT_CODE);
|
42 |
+
$review
|
43 |
+
->setEntityId($entityId)
|
44 |
+
->setEntityPkValue($product->getId())
|
45 |
+
->setStatusId(Mage_Review_Model_Review::STATUS_APPROVED)
|
46 |
+
->setStoreId($store->getId())
|
47 |
+
->setStores(array($store->getId()))
|
48 |
+
->addData($reviewData);
|
49 |
+
|
50 |
+
$review->save();
|
51 |
+
|
52 |
+
// slight hack to set created_at
|
53 |
+
if (array_key_exists('created_at', $reviewData)) {
|
54 |
+
$review->setCreatedAt($reviewData['created_at']);
|
55 |
+
$review->save();
|
56 |
+
}
|
57 |
+
if (is_array($ratings) && count($ratings) > 0) {
|
58 |
+
foreach ($ratings as $ratingCode => $ratingValue) {
|
59 |
+
$rating = Mage::getModel('rating/rating')->load($ratingCode, 'rating_code');
|
60 |
+
if ($rating->getId()) {
|
61 |
+
$ratingOptions = $rating->getOptions();
|
62 |
+
foreach ($ratingOptions as $_ratingOption) {
|
63 |
+
if ($ratingValue == $_ratingOption->getValue()) {
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Mage_Rating_Model_Mysql4_Rating_Option::addVote() checks the action
|
67 |
+
* type as an additional security feature in PE, so we need to fudge it
|
68 |
+
*/
|
69 |
+
$currentAction = Mage::app()->getFrontController()->getAction();
|
70 |
+
$tempAction = new Mage_Adminhtml_Controller_Action(
|
71 |
+
new Zend_Controller_Request_Http,
|
72 |
+
new Zend_Controller_Response_Http,
|
73 |
+
array()
|
74 |
+
);
|
75 |
+
Mage::app()->getFrontController()->setAction($tempAction);
|
76 |
+
|
77 |
+
$rating
|
78 |
+
->setRatingId($rating->getId())
|
79 |
+
->setReviewId($review->getId())
|
80 |
+
->addOptionVote($_ratingOption->getId(), $product->getId());
|
81 |
+
|
82 |
+
// reset the frontcontroller action back how it was
|
83 |
+
Mage::app()->getFrontController()->setAction($currentAction);
|
84 |
+
break;
|
85 |
+
}
|
86 |
+
}
|
87 |
+
}
|
88 |
+
}
|
89 |
+
}
|
90 |
+
$review->aggregate();
|
91 |
+
}
|
92 |
+
|
93 |
+
}
|
app/code/core/Ampersand/Api/Model/Sales/Order.php
ADDED
@@ -0,0 +1,1095 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand Magento Suite
|
4 |
+
*
|
5 |
+
* @category Ampersand_Magento
|
6 |
+
* @package Ampersand_Api
|
7 |
+
* @subpackage Model
|
8 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandcommerce.com)
|
9 |
+
* @license TBC
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @category Ampersand_Magento
|
14 |
+
* @package Ampersand_Api
|
15 |
+
* @subpackage Model
|
16 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
17 |
+
*/
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @todo
|
21 |
+
* - Currency handling and conversion
|
22 |
+
* - If increment id exists (on second check) the order has already been created
|
23 |
+
* - If invoice or shipment fails, the order has already been created
|
24 |
+
* - Items can be shipped even if they have not been invoiced
|
25 |
+
* - implement SOAP aspects of this module
|
26 |
+
*/
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @example
|
30 |
+
$orderData = array(
|
31 |
+
'store_id' => 'default', // required
|
32 |
+
'grand_total' => '520.00', // required
|
33 |
+
'shipping_incl_tax' => '20.00', // required
|
34 |
+
'tax_amount' => '100.00', // required
|
35 |
+
'shipping_tax_amount' => '0', // required
|
36 |
+
'order_currency_code' => 'GBP', // required
|
37 |
+
'shipping_method' => 'flatrate_flatrate', // required
|
38 |
+
'payment_method' => 'checkmo', // required
|
39 |
+
'customer_email' => time() . '@ampersandcommerce.com', // optional
|
40 |
+
'customer_firstname' => 'Joseph', // optional
|
41 |
+
'customer_lastname' => 'McDermott', // optional
|
42 |
+
'ext_order_id' => '123-12415-12312', // optional
|
43 |
+
'ext_customer_id' => '876123', // optional
|
44 |
+
'reserved_order_id' => '', // optional
|
45 |
+
'created_at' => 1322134810, // optional
|
46 |
+
'items' => array(
|
47 |
+
array(
|
48 |
+
'sku' => 'JRMTEST', // required
|
49 |
+
'price_incl_tax' => '100.00', // required
|
50 |
+
'tax_amount' => '20.00', // required
|
51 |
+
'qty_ordered' => '5', // required
|
52 |
+
'qty_invoiced' => '5', // optional
|
53 |
+
'qty_shipped' => '0', // optional
|
54 |
+
'ext_order_item_id' => 'asd6a987asd', // optional
|
55 |
+
),
|
56 |
+
array(
|
57 |
+
'sku' => 'Configurable_Test',
|
58 |
+
'price_incl_tax' => '9.99',
|
59 |
+
'tax_amount' => '0.00',
|
60 |
+
'qty_ordered' => '1',
|
61 |
+
'options' => array(
|
62 |
+
'colour' => 'red', // options must exist
|
63 |
+
'size' => 'small', // options must exist
|
64 |
+
),
|
65 |
+
),
|
66 |
+
),
|
67 |
+
'shipping_address' => array( // optional
|
68 |
+
'firstname' => 'Joseph',
|
69 |
+
'lastname' => 'McDermott',
|
70 |
+
'street' => 'address line 1' . PHP_EOL . 'address line 2',
|
71 |
+
'city' => 'Manchester',
|
72 |
+
'region_id' => 'Lancs',
|
73 |
+
'country_id' => 'UK',
|
74 |
+
'postcode' => 'AB11AB',
|
75 |
+
'telephone' => '0123456789',
|
76 |
+
'fax' => '0123456789',
|
77 |
+
),
|
78 |
+
'billing_address' => array( // optional
|
79 |
+
'firstname' => 'Joseph',
|
80 |
+
'lastname' => 'McDermott',
|
81 |
+
'street' => 'address line 1' . PHP_EOL . 'address line 2',
|
82 |
+
'city' => 'Manchester',
|
83 |
+
'region_id' => 'Lancs',
|
84 |
+
'country_id' => 'UK',
|
85 |
+
'postcode' => 'AB11AB',
|
86 |
+
'telephone' => '0123456789',
|
87 |
+
'fax' => '0123456789',
|
88 |
+
),
|
89 |
+
);
|
90 |
+
Mage::getModel('ampersand_api/sales_order')->create($orderData, true, array(
|
91 |
+
*
|
92 |
+
* ));
|
93 |
+
*/
|
94 |
+
class Ampersand_Api_Model_Sales_Order extends Mage_Sales_Model_Order_Api
|
95 |
+
{
|
96 |
+
/**
|
97 |
+
* Quote object for preparing order.
|
98 |
+
*
|
99 |
+
* @var Mage_Sales_Model_Quote $_quote
|
100 |
+
*/
|
101 |
+
protected $_quote;
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Order object once created.
|
105 |
+
*
|
106 |
+
* @var Mage_Sales_Model_Order $_order
|
107 |
+
*/
|
108 |
+
protected $_order;
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Active store to save orders in.
|
112 |
+
*
|
113 |
+
* @var Mage_Core_Model_Store $_store
|
114 |
+
*/
|
115 |
+
protected $_store;
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Our supplied data in a nested Ampersand Object format.
|
119 |
+
*
|
120 |
+
* @var Ampersand_Object $_dataObject
|
121 |
+
*/
|
122 |
+
protected $_dataObject;
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Flag for whether stores have been initialised.
|
126 |
+
*
|
127 |
+
* @var bool $_storesInitialised
|
128 |
+
*/
|
129 |
+
protected $_storesInitialised = false;
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Additional data to be added to an order instance
|
133 |
+
*
|
134 |
+
* @var array
|
135 |
+
*/
|
136 |
+
protected $_additionalData = array();
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Create a Magento order from a nested array of data, and return the
|
140 |
+
* increment id of the newly created order.
|
141 |
+
*
|
142 |
+
* @param array $orderData
|
143 |
+
* @param bool $processRelatedObjects
|
144 |
+
* @param array $additionalData
|
145 |
+
* @return string
|
146 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
147 |
+
*/
|
148 |
+
public function create($orderData, $processRelatedObjects = false, $additionalData = array())
|
149 |
+
{
|
150 |
+
try {
|
151 |
+
$this->prepareDataObject($orderData);
|
152 |
+
$this->_additionalData = $additionalData;
|
153 |
+
|
154 |
+
$this->_validateDataObject();
|
155 |
+
$this->_checkIncrementId(false);
|
156 |
+
$this->_initQuote();
|
157 |
+
$this->_assignCustomer();
|
158 |
+
$this->_assignProducts();
|
159 |
+
$this->_assignShippingMethod();
|
160 |
+
$this->_assignPaymentMethod();
|
161 |
+
$this->_convertQuoteToOrder();
|
162 |
+
|
163 |
+
if ($processRelatedObjects) {
|
164 |
+
$this->_invoiceOrder();
|
165 |
+
$this->_dispatchOrder();
|
166 |
+
$this->_refundOrder();
|
167 |
+
}
|
168 |
+
} catch (Mage_Api_Exception $e) {
|
169 |
+
$this->_fault($e->getMessage(), $e->getCustomMessage());
|
170 |
+
} catch (Exception $e) {
|
171 |
+
$this->_fault('order_not_created', $e->getMessage());
|
172 |
+
}
|
173 |
+
|
174 |
+
return $this->_order->getIncrementId();
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* @todo Not actually fully working yet...
|
179 |
+
*/
|
180 |
+
public function createFromOrder($order, $paymentData = array(), $productDatas = array())
|
181 |
+
{
|
182 |
+
// load the order create model
|
183 |
+
$orderCreate = Mage::getModel('adminhtml/sales_order_create');
|
184 |
+
$orderCreate->getSession()->getOrder()->reset();
|
185 |
+
|
186 |
+
// use the same shipping method as the provided order
|
187 |
+
$orderCreate->getSession()->setUseOldShippingMethod(true);
|
188 |
+
|
189 |
+
// initialize a new order based on the one provided
|
190 |
+
Mage::unregister('rule_data');
|
191 |
+
$orderCreate->initFromOrder($order);
|
192 |
+
|
193 |
+
// modify the payment data to be used for this transaction
|
194 |
+
$orderCreate->getQuote()->getPayment()->unsMethodInstance();
|
195 |
+
if (!empty($paymentData)) {
|
196 |
+
$orderCreate->setPaymentData($paymentData);
|
197 |
+
}
|
198 |
+
|
199 |
+
// modify the products to be included in the order
|
200 |
+
if (count($productDatas)) {
|
201 |
+
$qtyUpdateData = array();
|
202 |
+
foreach ($orderCreate->getQuote()->getItemsCollection() as $_item) {
|
203 |
+
$newQty = in_array($_item->getProductId(), $productDatas)
|
204 |
+
? $productDatas[$_item->getProductId()]
|
205 |
+
: 0;
|
206 |
+
$_item
|
207 |
+
->setQty($newQty)
|
208 |
+
->setQtyToAdd($newQty);
|
209 |
+
}
|
210 |
+
}
|
211 |
+
|
212 |
+
// we dont want the new order linked to the old one
|
213 |
+
$orderCreate->getSession()->getOrder()->setId(null);
|
214 |
+
|
215 |
+
// recollect the cart
|
216 |
+
$orderCreate->getCustomerCart()
|
217 |
+
->collectTotals()
|
218 |
+
->save();
|
219 |
+
$orderCreate->setRecollect(true);
|
220 |
+
|
221 |
+
// give an opportunity for any changes before creating the order
|
222 |
+
Mage::dispatchEvent(
|
223 |
+
'ampersand_api_sales_order_createfromorder_before',
|
224 |
+
array(
|
225 |
+
'order' => $order,
|
226 |
+
'order_create_model' => $orderCreate,
|
227 |
+
)
|
228 |
+
);
|
229 |
+
|
230 |
+
// create the order
|
231 |
+
return $orderCreate->createOrder();
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Convert the provided nested array to a nested Ampersand Object
|
236 |
+
* and perform any bootstrapping and validation as required.
|
237 |
+
*
|
238 |
+
* @param array $orderData
|
239 |
+
* @return Ampersand_Object
|
240 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
241 |
+
*/
|
242 |
+
public function prepareDataObject($orderData)
|
243 |
+
{
|
244 |
+
$this->_dataObject = Ampersand_Object::arrayToObject($orderData);
|
245 |
+
|
246 |
+
$this->_prepareCustomer();
|
247 |
+
$this->_prepareProducts();
|
248 |
+
|
249 |
+
return $this->_dataObject;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Populate shipping with billing details and vicaversa if missing.
|
254 |
+
* Also set guest checkout if no customer email or address information.
|
255 |
+
*
|
256 |
+
* @return Ampersand_Api_Model_Sales_Order
|
257 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
258 |
+
*/
|
259 |
+
protected function _prepareCustomer()
|
260 |
+
{
|
261 |
+
if (!$this->_dataObject->getShippingAddress()) {
|
262 |
+
$this->_dataObject->setShippingAddress(new Ampersand_Object(array()));
|
263 |
+
}
|
264 |
+
|
265 |
+
if (!$this->_dataObject->getBillingAddress()) {
|
266 |
+
$this->_dataObject->setBillingAddress(new Ampersand_Object(array()));
|
267 |
+
}
|
268 |
+
|
269 |
+
if (!$this->_dataObject->getCustomerEmail()) {
|
270 |
+
$this->_dataObject->setCustomerIsGuest(true);
|
271 |
+
return $this;
|
272 |
+
}
|
273 |
+
|
274 |
+
$shippingAddressData = $this->_dataObject->getShippingAddress()->getData();
|
275 |
+
$billingAddressData = $this->_dataObject->getBillingAddress()->getData();
|
276 |
+
|
277 |
+
$primaryAddressData = array();
|
278 |
+
if ($shippingAddressData) {
|
279 |
+
$primaryAddressData = $shippingAddressData;
|
280 |
+
} elseif ($billingAddressData) {
|
281 |
+
$primaryAddressData = $billingAddressData;
|
282 |
+
} else {
|
283 |
+
$this->_dataObject->setCustomerIsGuest(true);
|
284 |
+
return $this;
|
285 |
+
}
|
286 |
+
|
287 |
+
if (!$shippingAddressData) {
|
288 |
+
$shippingAddressData = $primaryAddressData;
|
289 |
+
}
|
290 |
+
|
291 |
+
if (!$billingAddressData) {
|
292 |
+
$billingAddressData = $primaryAddressData;
|
293 |
+
}
|
294 |
+
|
295 |
+
$this->_dataObject->getShippingAddress()->setData($shippingAddressData);
|
296 |
+
$this->_dataObject->getBillingAddress()->setData($billingAddressData);
|
297 |
+
|
298 |
+
$customerFieldsToPopulate = array(
|
299 |
+
'customer_firstname' => 'firstname',
|
300 |
+
'customer_lastname' => 'lastname',
|
301 |
+
);
|
302 |
+
$primaryAddressObject = new Ampersand_Object($primaryAddressData);
|
303 |
+
foreach ($customerFieldsToPopulate as $_customerField => $_addressField) {
|
304 |
+
if (!$this->_dataObject->getData($_customerField)) {
|
305 |
+
$this->_dataObject->setData(
|
306 |
+
$_customerField, $primaryAddressObject->getData($_addressField));
|
307 |
+
}
|
308 |
+
}
|
309 |
+
|
310 |
+
return $this;
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Create sku to itemData mapping and auto-populate product fields.
|
315 |
+
*
|
316 |
+
* @return Ampersand_Api_Model_Sales_Order
|
317 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
318 |
+
*/
|
319 |
+
protected function _prepareProducts()
|
320 |
+
{
|
321 |
+
$skuToItemData = array();
|
322 |
+
foreach ($this->_dataObject->getItems()->getData() as $_skuItem) {
|
323 |
+
$skuToItemData[$_skuItem->getSku()] = $_skuItem;
|
324 |
+
}
|
325 |
+
$this->_dataObject->setSkuToItemData($skuToItemData);
|
326 |
+
|
327 |
+
return $this;
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Ensure our data object contains all the information we require.
|
332 |
+
*
|
333 |
+
* @return Ampersand_Api_Model_Sales_Order
|
334 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
335 |
+
*/
|
336 |
+
protected function _validateDataObject()
|
337 |
+
{
|
338 |
+
$this->_validateStore();
|
339 |
+
$this->_validateAddresses();
|
340 |
+
$this->_validateProducts();
|
341 |
+
$this->_validateOrderData();
|
342 |
+
$this->_validateShippingMethod();
|
343 |
+
$this->_validatePaymentMethod();
|
344 |
+
|
345 |
+
return $this;
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* Ensure a valid store has been selected.
|
350 |
+
*
|
351 |
+
* @return Ampersand_Api_Model_Sales_Order
|
352 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
353 |
+
*/
|
354 |
+
protected function _validateStore()
|
355 |
+
{
|
356 |
+
$this->_setStore($this->_dataObject->getStoreId());
|
357 |
+
$this->_getStore();
|
358 |
+
|
359 |
+
return $this;
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Ensure valid address data has been provided.
|
364 |
+
*
|
365 |
+
* @return Ampersand_Api_Model_Sales_Order
|
366 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
367 |
+
*/
|
368 |
+
protected function _validateAddresses()
|
369 |
+
{
|
370 |
+
if (!$this->_dataObject->getCustomerIsGuest()) {
|
371 |
+
$this->_validateAddress($this->_dataObject->getShippingAddress()->getData());
|
372 |
+
$this->_validateAddress($this->_dataObject->getBillingAddress()->getData());
|
373 |
+
}
|
374 |
+
|
375 |
+
return $this;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Ensure all required address fields exist in the provided address data.
|
380 |
+
*
|
381 |
+
* @param array $addressData
|
382 |
+
* @return Ampersand_Api_Model_Sales_Order
|
383 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
384 |
+
*/
|
385 |
+
protected function _validateAddress($addressData)
|
386 |
+
{
|
387 |
+
$requiredFields = array(
|
388 |
+
'firstname',
|
389 |
+
'lastname',
|
390 |
+
'street',
|
391 |
+
'city',
|
392 |
+
'region_id',
|
393 |
+
'country_id',
|
394 |
+
'postcode',
|
395 |
+
'telephone',
|
396 |
+
'fax',
|
397 |
+
);
|
398 |
+
|
399 |
+
foreach ($requiredFields as $_field) {
|
400 |
+
if (!array_key_exists($_field, $addressData)) {
|
401 |
+
$this->_fault('invalid_data',
|
402 |
+
'Address information missing.' . PHP_EOL
|
403 |
+
. 'Required: ' . implode(' / ', $requiredFields) . PHP_EOL
|
404 |
+
. 'Provided: ' . implode(' / ', array_keys($addressData)));
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
return $this;
|
409 |
+
}
|
410 |
+
|
411 |
+
/**
|
412 |
+
* Ensure valid product data has been provided.
|
413 |
+
*
|
414 |
+
* @return Ampersand_Api_Model_Sales_Order
|
415 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
416 |
+
*/
|
417 |
+
protected function _validateProducts()
|
418 |
+
{
|
419 |
+
foreach ($this->_dataObject->getSkuToItemData() as $_sku => $_item) {
|
420 |
+
$productId = Mage::getSingleton('catalog/product')->getIdBySku($_item->getSku());
|
421 |
+
if (!$productId) {
|
422 |
+
$this->_fault('product_not_exists', "Product with Sku {$_item->getSku()} does not exist");
|
423 |
+
}
|
424 |
+
|
425 |
+
$requiredFields = array(
|
426 |
+
'sku',
|
427 |
+
'price_incl_tax',
|
428 |
+
'tax_amount',
|
429 |
+
'qty_ordered',
|
430 |
+
);
|
431 |
+
|
432 |
+
foreach ($requiredFields as $_field) {
|
433 |
+
if (is_null($_item->getData($_field))) {
|
434 |
+
$this->_fault('product_not_added', "Insufficient data for {$_item->getSku()}");
|
435 |
+
}
|
436 |
+
}
|
437 |
+
}
|
438 |
+
|
439 |
+
return $this;
|
440 |
+
}
|
441 |
+
|
442 |
+
/**
|
443 |
+
* Ensure valid order data has been provided.
|
444 |
+
*
|
445 |
+
* @return Ampersand_Api_Model_Sales_Order
|
446 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
447 |
+
*/
|
448 |
+
protected function _validateOrderData()
|
449 |
+
{
|
450 |
+
$requiredFields = array(
|
451 |
+
'store_id',
|
452 |
+
'grand_total',
|
453 |
+
'shipping_incl_tax',
|
454 |
+
'tax_amount',
|
455 |
+
'shipping_tax_amount',
|
456 |
+
'order_currency_code',
|
457 |
+
'shipping_method',
|
458 |
+
'payment_method',
|
459 |
+
);
|
460 |
+
|
461 |
+
foreach ($requiredFields as $_field) {
|
462 |
+
if (is_null($this->_dataObject->getData($_field))) {
|
463 |
+
$this->_fault('order_not_created', 'Insufficient data for order');
|
464 |
+
}
|
465 |
+
}
|
466 |
+
|
467 |
+
$currencyCode = $this->_dataObject->getOrderCurrencyCode();
|
468 |
+
if (!in_array($currencyCode, $this->_getStore()->getAvailableCurrencyCodes())) {
|
469 |
+
$this->_fault('currency_code_invalid', "Currency code {$currencyCode} is invalid");
|
470 |
+
}
|
471 |
+
|
472 |
+
return $this;
|
473 |
+
}
|
474 |
+
|
475 |
+
/**
|
476 |
+
* Ensure a valid shipping method has been provided.
|
477 |
+
*
|
478 |
+
* @return Ampersand_Api_Model_Sales_Order
|
479 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
480 |
+
*/
|
481 |
+
protected function _validateShippingMethod()
|
482 |
+
{
|
483 |
+
$shippingMethod = $this->_dataObject->getShippingMethod();
|
484 |
+
$shippingMethodParts = explode('_', $shippingMethod);
|
485 |
+
if (count($shippingMethodParts) != 2) {
|
486 |
+
$this->_fault('shipping_code_not_exists', "Shipping code {$shippingMethod} does not exist");
|
487 |
+
}
|
488 |
+
|
489 |
+
$carrierCode = $shippingMethodParts[0];
|
490 |
+
$method = $shippingMethodParts[1];
|
491 |
+
$carrier = Mage::getModel('shipping/config')
|
492 |
+
->getCarrierInstance($carrierCode, $this->_getStore());
|
493 |
+
|
494 |
+
if (!$carrier || !array_key_exists($method, $carrier->getAllowedMethods())) {
|
495 |
+
$this->_fault('shipping_code_not_exists', "Shipping code {$shippingMethod} does not exist");
|
496 |
+
}
|
497 |
+
|
498 |
+
return $this;
|
499 |
+
}
|
500 |
+
|
501 |
+
/**
|
502 |
+
* Ensure a valid payment method has been provided.
|
503 |
+
*
|
504 |
+
* @return Ampersand_Api_Model_Sales_Order
|
505 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
506 |
+
*/
|
507 |
+
protected function _validatePaymentMethod()
|
508 |
+
{
|
509 |
+
$method = $this->_dataObject->getPaymentMethod();
|
510 |
+
$methods = Mage::getModel('payment/config')
|
511 |
+
->getActiveMethods($this->_getStore());
|
512 |
+
|
513 |
+
if (!array_key_exists($method, $methods)) {
|
514 |
+
$this->_fault('payment_method_not_exists', "Payment method {$method} does not exist");
|
515 |
+
}
|
516 |
+
|
517 |
+
return $this;
|
518 |
+
}
|
519 |
+
|
520 |
+
/**
|
521 |
+
* Ensure the order increment id does not already exist.
|
522 |
+
*
|
523 |
+
* @param string $incrementId
|
524 |
+
* @param bool $allowOne
|
525 |
+
* @return Ampersand_Integration_Helper_Handler_Order
|
526 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
527 |
+
*/
|
528 |
+
protected function _checkIncrementId($checkAfterCreated = false)
|
529 |
+
{
|
530 |
+
$incrementId = $checkAfterCreated
|
531 |
+
? $this->_order->getIncrementId()
|
532 |
+
: $this->_dataObject->getReservedOrderId();
|
533 |
+
|
534 |
+
if ($incrementId) {
|
535 |
+
$size = Mage::getResourceModel('sales/order_collection')
|
536 |
+
->addAttributeToFilter('increment_id', $incrementId)
|
537 |
+
->getSize();
|
538 |
+
|
539 |
+
/**
|
540 |
+
* @todo this will error as expected, however the order is already created...
|
541 |
+
*/
|
542 |
+
if ($size > (int)$checkAfterCreated) {
|
543 |
+
$this->_fault('duplicate_order_id',
|
544 |
+
"The order was created but with a duplicate increment id {$incrementId}");
|
545 |
+
}
|
546 |
+
}
|
547 |
+
|
548 |
+
return $this;
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Initialise quote object.
|
553 |
+
*
|
554 |
+
* @return Ampersand_Api_Model_Sales_Order
|
555 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
556 |
+
*/
|
557 |
+
protected function _initQuote()
|
558 |
+
{
|
559 |
+
$this->_quote = Mage::getModel('sales/quote');
|
560 |
+
|
561 |
+
$reservedOrderId = $this->_dataObject->getReservedOrderId();
|
562 |
+
$this->_quote->setReservedOrderId($reservedOrderId);
|
563 |
+
|
564 |
+
return $this;
|
565 |
+
}
|
566 |
+
|
567 |
+
/**
|
568 |
+
* If a customer already exists with the provided email address, we use
|
569 |
+
* that customer, otherwise a new customer must be created from scratch.
|
570 |
+
*
|
571 |
+
* @return Ampersand_Api_Model_Sales_Order
|
572 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
573 |
+
*/
|
574 |
+
protected function _assignCustomer()
|
575 |
+
{
|
576 |
+
if ($this->_dataObject->getCustomerIsGuest()) {
|
577 |
+
$this->_quote->setCustomerIsGuest(true);
|
578 |
+
return $this;
|
579 |
+
}
|
580 |
+
|
581 |
+
$customer = Mage::getResourceModel('customer/customer_collection')
|
582 |
+
->addAttributeToFilter('email', $this->_dataObject->getCustomerEmail())
|
583 |
+
->getFirstItem();
|
584 |
+
|
585 |
+
if (!$customer || (!$customerId = $customer->getId())) {
|
586 |
+
$newCustomerId = $this->_createCustomer();
|
587 |
+
$customer = Mage::getModel('customer/customer')->load($newCustomerId);
|
588 |
+
if (!$customer->getId()) {
|
589 |
+
$this->_fault('customer_not_exists', 'Unable to create a new customer');
|
590 |
+
}
|
591 |
+
}
|
592 |
+
|
593 |
+
$this->_quote->setCustomer($customer);
|
594 |
+
|
595 |
+
return $this;
|
596 |
+
}
|
597 |
+
|
598 |
+
/**
|
599 |
+
* Create a new customer using the Magento Api.
|
600 |
+
*
|
601 |
+
* @return int
|
602 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
603 |
+
*/
|
604 |
+
protected function _createCustomer()
|
605 |
+
{
|
606 |
+
if (!$this->_dataObject->getCustomerEmail()) {
|
607 |
+
$this->_fault('customer_not_exists', 'Customer email address was not provided.');
|
608 |
+
}
|
609 |
+
|
610 |
+
$newCustomer = array(
|
611 |
+
'firstname' => $this->_dataObject->getCustomerFirstname(),
|
612 |
+
'lastname' => $this->_dataObject->getCustomerLastname(),
|
613 |
+
'email' => $this->_dataObject->getCustomerEmail(),
|
614 |
+
'website_id' => $this->_getWebsite()->getId(),
|
615 |
+
'store_id' => $this->_getStore()->getId(),
|
616 |
+
);
|
617 |
+
$customerId = Mage::getModel('customer/customer_api')
|
618 |
+
->create($newCustomer);
|
619 |
+
|
620 |
+
$this->_createCustomerAddress($customerId);
|
621 |
+
|
622 |
+
return $customerId;
|
623 |
+
}
|
624 |
+
|
625 |
+
/**
|
626 |
+
* Create a new address and assign to the customer id provided.
|
627 |
+
*
|
628 |
+
* @param int $customerId
|
629 |
+
* @return int
|
630 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
631 |
+
*/
|
632 |
+
protected function _createCustomerAddress($customerId)
|
633 |
+
{
|
634 |
+
$additionalFields = array(
|
635 |
+
'is_default_shipping' => '1',
|
636 |
+
'is_default_billing' => '1',
|
637 |
+
);
|
638 |
+
$newCustomerAddress = array_merge(
|
639 |
+
$this->_dataObject->getShippingAddress()->getData(),
|
640 |
+
$additionalFields);
|
641 |
+
|
642 |
+
$addressId = Mage::getModel('ampersand_api/customer_address')
|
643 |
+
->create($customerId, $newCustomerAddress);
|
644 |
+
|
645 |
+
return $addressId;
|
646 |
+
}
|
647 |
+
|
648 |
+
/**
|
649 |
+
* create records in Credit Memos
|
650 |
+
*
|
651 |
+
* @return Ampersand_Api_Model_Sales_Order
|
652 |
+
* @author Wenjiang Xu <wenjiang.xu@ampersandcommerce.com>
|
653 |
+
*/
|
654 |
+
protected function _refundOrder()
|
655 |
+
{
|
656 |
+
try {
|
657 |
+
$okToRefund = false;
|
658 |
+
$itemQtyData = $this->_getItemQtyData('refunded');
|
659 |
+
foreach ($itemQtyData as $_itemQty) {
|
660 |
+
if ($_itemQty > 0) {
|
661 |
+
$okToRefund = true;
|
662 |
+
break;
|
663 |
+
}
|
664 |
+
}
|
665 |
+
|
666 |
+
if ($okToRefund) {
|
667 |
+
$refund = Mage::getModel('sales/order_creditmemo_api');
|
668 |
+
$refund->create($this->_order->getIncrementId(),$itemQtyData);
|
669 |
+
}
|
670 |
+
} catch (Mage_Api_Exception $e) {
|
671 |
+
$this->_fault($e->getMessage(), $e->getCustomMessage());
|
672 |
+
} catch (Exception $e) {
|
673 |
+
$this->_fault('creditmemo_not_created', $e->getMessage());
|
674 |
+
}
|
675 |
+
return $this;
|
676 |
+
}
|
677 |
+
|
678 |
+
/**
|
679 |
+
* Add products to the quote which will later be converted to an order.
|
680 |
+
*
|
681 |
+
* @return Ampersand_Api_Model_Sales_Order
|
682 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
683 |
+
*/
|
684 |
+
protected function _assignProducts()
|
685 |
+
{
|
686 |
+
foreach ($this->_dataObject->getItems()->getData() as $_item) {
|
687 |
+
$productId = Mage::getSingleton('catalog/product')->getIdBySku($_item->getSku());
|
688 |
+
$_product = Mage::getModel('catalog/product')->load($productId);
|
689 |
+
if (!$_product->getId()) {
|
690 |
+
$this->_fault('product_not_exists',
|
691 |
+
"Product with sku '{$_item->getSku()}' could not be found");
|
692 |
+
}
|
693 |
+
$this->_quote->addProduct($_product, $this->_prepareRequest($_product, $_item));
|
694 |
+
}
|
695 |
+
|
696 |
+
if (!count($this->_quote->getAllItems())) {
|
697 |
+
$this->_fault('no_items_added', 'No products were added to the order.');
|
698 |
+
}
|
699 |
+
|
700 |
+
return $this;
|
701 |
+
}
|
702 |
+
|
703 |
+
/**
|
704 |
+
* Emulates request from user based on quantity and selected attributes
|
705 |
+
*
|
706 |
+
* @author Matthew Haworth <matthew.haworth@ampersandcommerce.com>
|
707 |
+
* @param Mage_Catalog_Model_Product $product
|
708 |
+
* @param array $item
|
709 |
+
* @return \Varien_Object
|
710 |
+
*/
|
711 |
+
protected function _prepareRequest($product, $item) {
|
712 |
+
$request = new Varien_Object();
|
713 |
+
$request->setQty($item->getQtyOrdered());
|
714 |
+
if ($item->getOptions()) {
|
715 |
+
$options = $item->getOptions()->getData();
|
716 |
+
foreach (array_keys($options) as $_attributeKey) {
|
717 |
+
$attribute = Mage::getModel('catalog/product')
|
718 |
+
->getResource()
|
719 |
+
->getAttribute($_attributeKey);
|
720 |
+
|
721 |
+
if (!$attribute) {
|
722 |
+
$this->_fault('attribute_not_found', 'Could not find attribute from code');
|
723 |
+
}
|
724 |
+
|
725 |
+
// Replace value
|
726 |
+
$newValue = $attribute->getSource()->getOptionId($options[$_attributeKey]);
|
727 |
+
if (!$newValue) {
|
728 |
+
$this->_fault('attribute_value_not_found', 'Could not find attribute value from code');
|
729 |
+
}
|
730 |
+
|
731 |
+
$options[$_attributeKey] = $newValue;
|
732 |
+
|
733 |
+
// Replace key
|
734 |
+
$options[$attribute->getId()] = $options[$_attributeKey];
|
735 |
+
unset($options[$_attributeKey]);
|
736 |
+
}
|
737 |
+
|
738 |
+
$childProduct = Mage::getSingleton('catalog/product_type_configurable')
|
739 |
+
->getProductByAttributes($options, $product);
|
740 |
+
|
741 |
+
if (!$childProduct) {
|
742 |
+
$this->_fault('child_product_not_found', 'Could not find child product from options');
|
743 |
+
}
|
744 |
+
|
745 |
+
$skuToItemData = $this->_dataObject->getSkuToItemData();
|
746 |
+
$skuToItemData[$childProduct->getSku()] = $skuToItemData[$product->getSku()];
|
747 |
+
unset($skuToItemData[$product->getSku()]);
|
748 |
+
$this->_dataObject->setSkuToItemData($skuToItemData);
|
749 |
+
|
750 |
+
$request->setSuperAttribute($options);
|
751 |
+
}
|
752 |
+
|
753 |
+
return $request;
|
754 |
+
}
|
755 |
+
|
756 |
+
/**
|
757 |
+
* Assign shipping method. If a price provided or no method defined, use flat
|
758 |
+
* rate and override the value to match the value we have received.
|
759 |
+
*
|
760 |
+
* @return Ampersand_Api_Model_Sales_Order
|
761 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
762 |
+
*/
|
763 |
+
protected function _assignShippingMethod()
|
764 |
+
{
|
765 |
+
$storeCode = $this->_getStore()->getCode();
|
766 |
+
$config = Mage::getConfig()->getNode("stores/$storeCode/carriers/flatrate");
|
767 |
+
$config->setNode('price', $this->_dataObject->getShippingInclTax())
|
768 |
+
->setNode('type', 'O')
|
769 |
+
->setNode('handling_fee', '0');
|
770 |
+
|
771 |
+
$this->_quote->getShippingAddress()
|
772 |
+
->addData($this->_dataObject->getShippingAddress()->getData())
|
773 |
+
->setShippingMethod($this->_dataObject->getShippingMethod())
|
774 |
+
->setShippingDescription($this->_dataObject->getShippingMethod())
|
775 |
+
->setCollectShippingRates(true);
|
776 |
+
|
777 |
+
return $this;
|
778 |
+
}
|
779 |
+
|
780 |
+
/**
|
781 |
+
* Configure billing and payment information.
|
782 |
+
*
|
783 |
+
* @return Ampersand_Api_Model_Sales_Order
|
784 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
785 |
+
*/
|
786 |
+
protected function _assignPaymentMethod()
|
787 |
+
{
|
788 |
+
$this->_quote->getBillingAddress()
|
789 |
+
->addData($this->_dataObject->getBillingAddress()->getData());
|
790 |
+
|
791 |
+
$payment = $this->_quote->getPayment();
|
792 |
+
if ($paymentDataObject = $this->_dataObject->getPayment()) {
|
793 |
+
$paymentDataObject->getDataSetDefault(
|
794 |
+
'method', $this->_dataObject->getPaymentMethod()
|
795 |
+
);
|
796 |
+
|
797 |
+
// remove this first so we dont create the 'additional_information' node as an object
|
798 |
+
$additionalInformation = $paymentDataObject->getAdditionalInformation();
|
799 |
+
$paymentDataObject->unsetData('additional_information');
|
800 |
+
|
801 |
+
$payment->importData($paymentDataObject->getData());
|
802 |
+
|
803 |
+
if ($additionalInformation instanceof Ampersand_Object) {
|
804 |
+
foreach ($additionalInformation->getData() as $_key => $_value) {
|
805 |
+
$payment->setAdditionalInformation($_key, $_value);
|
806 |
+
}
|
807 |
+
}
|
808 |
+
} else {
|
809 |
+
$payment->setMethod($this->_dataObject->getPaymentMethod());
|
810 |
+
}
|
811 |
+
|
812 |
+
return $this;
|
813 |
+
}
|
814 |
+
|
815 |
+
/**
|
816 |
+
* Convert quote to order.
|
817 |
+
*
|
818 |
+
* @return Ampersand_Api_Model_Sales_Order
|
819 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
820 |
+
*/
|
821 |
+
protected function _convertQuoteToOrder()
|
822 |
+
{
|
823 |
+
$this->_quote->collectTotals()->save();
|
824 |
+
$convertQuote = Mage::getModel('sales/convert_quote');
|
825 |
+
$this->_order = $convertQuote->addressToOrder($this->_quote->getShippingAddress())
|
826 |
+
->setBillingAddress($convertQuote->addressToOrderAddress($this->_quote->getBillingAddress()))
|
827 |
+
->setShippingAddress($convertQuote->addressToOrderAddress($this->_quote->getShippingAddress()));
|
828 |
+
// Mage_Sales_Model_Order->setPayment() returns payment instance, not order!
|
829 |
+
$this->_assignPaymentMethod();
|
830 |
+
$this->_order->setPayment($convertQuote->paymentToOrderPayment($this->_quote->getPayment()));
|
831 |
+
|
832 |
+
$skuToItemData = $this->_dataObject->getSkuToItemData();
|
833 |
+
foreach ($this->_quote->getAllItems() as $_item) {
|
834 |
+
$_orderItem = $convertQuote->itemToOrderItem($_item);
|
835 |
+
|
836 |
+
if ($_item->getParentItem()) {
|
837 |
+
$_orderItem->setParentItem($this->_order->getItemByQuoteItemId($_item->getParentItem()->getId()));
|
838 |
+
}
|
839 |
+
|
840 |
+
$itemQty = $skuToItemData[$_item->getSku()]->getQtyOrdered();
|
841 |
+
$itemTaxAmount = $skuToItemData[$_item->getSku()]->getTaxAmount();
|
842 |
+
$itemPriceInclTax = $skuToItemData[$_item->getSku()]->getPriceInclTax();
|
843 |
+
$itemPriceExclTax = $itemPriceInclTax - $itemTaxAmount;
|
844 |
+
|
845 |
+
$linePriceExclTax = $itemPriceExclTax * $itemQty;
|
846 |
+
$linePriceInclTax = $itemPriceInclTax * $itemQty;
|
847 |
+
|
848 |
+
$taxPercent = ($itemTaxAmount / $itemPriceInclTax) * 100;
|
849 |
+
$lineTaxAmount = $itemTaxAmount * $itemQty;
|
850 |
+
|
851 |
+
$_orderItem->addData(array(
|
852 |
+
'price' => $itemPriceExclTax,
|
853 |
+
'base_price' => $itemPriceExclTax,
|
854 |
+
'converted_price' => $itemPriceExclTax,
|
855 |
+
'calculation_price' => $itemPriceExclTax,
|
856 |
+
'base_calculation_price' => $itemPriceExclTax,
|
857 |
+
'original_price' => $itemPriceExclTax,
|
858 |
+
'base_original_price' => $itemPriceExclTax,
|
859 |
+
'price_incl_tax' => $itemPriceInclTax,
|
860 |
+
'base_price_incl_tax' => $itemPriceInclTax,
|
861 |
+
'row_total' => $linePriceExclTax,
|
862 |
+
'base_row_total' => $linePriceExclTax,
|
863 |
+
'taxable_amount' => $linePriceExclTax,
|
864 |
+
'base_taxable_amount' => $linePriceExclTax,
|
865 |
+
'row_total_incl_tax' => $linePriceInclTax,
|
866 |
+
'base_row_total_incl_tax' => $linePriceInclTax,
|
867 |
+
'tax_percent' => $taxPercent,
|
868 |
+
'tax_amount' => $itemTaxAmount,
|
869 |
+
'base_tax_amount' => $itemTaxAmount,
|
870 |
+
'ext_order_item_id' => $skuToItemData[$_item->getSku()]->getExtOrderItemId(),
|
871 |
+
));
|
872 |
+
$this->_order->addItem($_orderItem);
|
873 |
+
}
|
874 |
+
|
875 |
+
$subtotalInclTax = $this->_dataObject->getGrandTotal() - $this->_dataObject->getShippingInclTax();
|
876 |
+
$subtotalTaxMultiplier = 1 - ($this->_dataObject->getTaxAmount() / $subtotalInclTax);
|
877 |
+
$subtotalExclTax = $subtotalInclTax * $subtotalTaxMultiplier;
|
878 |
+
|
879 |
+
$shippingInclTax = $this->_dataObject->getShippingInclTax();
|
880 |
+
if ($shippingTaxAmount = $this->_dataObject->getShippingTaxAmount()) {
|
881 |
+
$shippingTaxMultiplier = 1 - ($shippingTaxAmount / $shippingInclTax);
|
882 |
+
$shippingExclTax = $shippingInclTax * $shippingTaxMultiplier;
|
883 |
+
} else {
|
884 |
+
$shippingExclTax = $shippingInclTax;
|
885 |
+
}
|
886 |
+
|
887 |
+
$this->_order->addData(array(
|
888 |
+
'store_id' => $this->_getStore()->getId(),
|
889 |
+
'quote_base_grand_total' => $this->_dataObject->getGrandTotal(),
|
890 |
+
'subtotal' => $subtotalExclTax,
|
891 |
+
'base_subtotal' => $subtotalExclTax,
|
892 |
+
'subtotal_incl_tax' => $subtotalInclTax,
|
893 |
+
'base_subtotal_incl_tax' => $subtotalInclTax,
|
894 |
+
'shipping_amount' => $shippingExclTax,
|
895 |
+
'base_shipping_amount' => $shippingExclTax,
|
896 |
+
'shipping_incl_tax' => $shippingInclTax,
|
897 |
+
'base_shipping_incl_tax' => $shippingInclTax,
|
898 |
+
'shipping_tax_amount' => $shippingTaxAmount,
|
899 |
+
'base_shipping_tax_amount' => $shippingTaxAmount,
|
900 |
+
'tax_amount' => $this->_dataObject->getTaxAmount(),
|
901 |
+
'base_tax_amount' => $this->_dataObject->getTaxAmount(),
|
902 |
+
'grand_total' => $this->_dataObject->getGrandTotal(),
|
903 |
+
'base_grand_total' => $this->_dataObject->getGrandTotal(),
|
904 |
+
'ext_order_id' => $this->_dataObject->getExtOrderId(),
|
905 |
+
'ext_customer_id' => $this->_dataObject->getExtCustomerId(),
|
906 |
+
'order_currency_code' => $this->_dataObject->getOrderCurrencyCode(),
|
907 |
+
'created_at' => $this->_dataObject->getCreatedAt(),
|
908 |
+
));
|
909 |
+
|
910 |
+
$this->_order->addData($this->_additionalData);
|
911 |
+
|
912 |
+
$observer = new Varien_Event_Observer();
|
913 |
+
$observer->setEvent(new Varien_Event(array (
|
914 |
+
'quote' => $this->_quote,
|
915 |
+
)));
|
916 |
+
|
917 |
+
Mage::getSingleton('cataloginventory/observer')->subtractQuoteInventory($observer);
|
918 |
+
|
919 |
+
try {
|
920 |
+
$this->_order->place()->save();
|
921 |
+
|
922 |
+
Mage::getSingleton('cataloginventory/observer')->reindexQuoteInventory($observer);
|
923 |
+
} catch (Exception $e) {
|
924 |
+
Mage::getSingleton('cataloginventory/observer')->revertQuoteInventory($observer);
|
925 |
+
|
926 |
+
throw $e;
|
927 |
+
}
|
928 |
+
|
929 |
+
$this->_checkIncrementId(true);
|
930 |
+
|
931 |
+
return $this;
|
932 |
+
}
|
933 |
+
|
934 |
+
/**
|
935 |
+
* Invoice the order using Magento Api.
|
936 |
+
*
|
937 |
+
* @return Ampersand_Api_Model_Sales_Order
|
938 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
939 |
+
*/
|
940 |
+
protected function _invoiceOrder()
|
941 |
+
{
|
942 |
+
try {
|
943 |
+
$okToInvoice = false;
|
944 |
+
$itemQtyData = $this->_getItemQtyData('invoiced');
|
945 |
+
foreach ($itemQtyData as $_itemQty) {
|
946 |
+
if ($_itemQty > 0) {
|
947 |
+
$okToInvoice = true;
|
948 |
+
break;
|
949 |
+
}
|
950 |
+
}
|
951 |
+
|
952 |
+
if ($okToInvoice) {
|
953 |
+
Mage::getModel('sales/order_invoice_api')
|
954 |
+
->create($this->_order->getIncrementId(), $itemQtyData);
|
955 |
+
}
|
956 |
+
} catch (Mage_Api_Exception $e) {
|
957 |
+
$this->_fault($e->getMessage(), $e->getCustomMessage());
|
958 |
+
} catch (Exception $e) {
|
959 |
+
$this->_fault('invoice_not_created', $e->getMessage());
|
960 |
+
}
|
961 |
+
|
962 |
+
return $this;
|
963 |
+
}
|
964 |
+
|
965 |
+
/**
|
966 |
+
* Dispatch the order using the Magento Api.
|
967 |
+
*
|
968 |
+
* @return Ampersand_Api_Model_Sales_Order
|
969 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
970 |
+
*/
|
971 |
+
protected function _dispatchOrder()
|
972 |
+
{
|
973 |
+
try {
|
974 |
+
$okToDispatch = false;
|
975 |
+
$itemQtyData = $this->_getItemQtyData('shipped');
|
976 |
+
foreach ($itemQtyData as $_itemQty) {
|
977 |
+
if ($_itemQty > 0) {
|
978 |
+
$okToDispatch = true;
|
979 |
+
break;
|
980 |
+
}
|
981 |
+
}
|
982 |
+
|
983 |
+
if ($okToDispatch) {
|
984 |
+
Mage::getModel('sales/order_shipment_api')
|
985 |
+
->create($this->_order->getIncrementId(), $itemQtyData);
|
986 |
+
}
|
987 |
+
} catch (Mage_Api_Exception $e) {
|
988 |
+
$this->_fault($e->getMessage(), $e->getCustomMessage());
|
989 |
+
} catch (Exception $e) {
|
990 |
+
$this->_fault('shipment_not_created', $e->getMessage());
|
991 |
+
}
|
992 |
+
|
993 |
+
return $this;
|
994 |
+
}
|
995 |
+
|
996 |
+
/**
|
997 |
+
* Retrieve an array of orderItemId => quantity for shipping or invoicing.
|
998 |
+
*
|
999 |
+
* @param string $type
|
1000 |
+
* @return array
|
1001 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
1002 |
+
*/
|
1003 |
+
protected function _getItemQtyData($type)
|
1004 |
+
{
|
1005 |
+
$skuToItemData = $this->_dataObject->getSkuToItemData();
|
1006 |
+
|
1007 |
+
$qtyData = array();
|
1008 |
+
foreach ($this->_order->getAllItems() as $_orderItem) {
|
1009 |
+
$itemQty = $skuToItemData[$_orderItem->getSku()]->getData("qty_{$type}");
|
1010 |
+
$qtyOrdered = $skuToItemData[$_orderItem->getSku()]->getData('qty_ordered');
|
1011 |
+
if ($itemQty > $qtyOrdered) {
|
1012 |
+
$this->_fault("qty_{$type}_exceeds_qty_ordered");
|
1013 |
+
}
|
1014 |
+
|
1015 |
+
if ($itemQty < 0) {
|
1016 |
+
$this->_fault("qty_{$type}_cannot_be_negative");
|
1017 |
+
}
|
1018 |
+
|
1019 |
+
$qtyData[$_orderItem->getId()] = $itemQty;
|
1020 |
+
}
|
1021 |
+
|
1022 |
+
return $qtyData;
|
1023 |
+
}
|
1024 |
+
|
1025 |
+
/**
|
1026 |
+
* Specify which store to save orders in.
|
1027 |
+
*
|
1028 |
+
* @param mixed $storeId
|
1029 |
+
* @return Ampersand_Api_Model_Sales_Order
|
1030 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
1031 |
+
*/
|
1032 |
+
protected function _setStore($storeId)
|
1033 |
+
{
|
1034 |
+
if (!$storeId) {
|
1035 |
+
return $this;
|
1036 |
+
}
|
1037 |
+
|
1038 |
+
$this->_reinitStores();
|
1039 |
+
|
1040 |
+
try {
|
1041 |
+
$store = Mage::app()->getStore($storeId);
|
1042 |
+
} catch (Exception $e) {
|
1043 |
+
$this->_fault('no_store_selected', 'Magento store id invalid');
|
1044 |
+
}
|
1045 |
+
|
1046 |
+
if ($store->getId()) {
|
1047 |
+
$this->_store = $store;
|
1048 |
+
}
|
1049 |
+
|
1050 |
+
return $this;
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
/**
|
1054 |
+
* Retrieve the active store.
|
1055 |
+
*
|
1056 |
+
* @return Mage_Core_Model_Store
|
1057 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
1058 |
+
*/
|
1059 |
+
protected function _getStore()
|
1060 |
+
{
|
1061 |
+
if (!$this->_store || !$this->_store->getId()) {
|
1062 |
+
$this->_fault('no_store_selected', 'Magento store not specified');
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
return $this->_store;
|
1066 |
+
}
|
1067 |
+
|
1068 |
+
/**
|
1069 |
+
* Some scripts run before Magento has a change to initialise stores,
|
1070 |
+
* and so requests for specific stores or websites may not be available.
|
1071 |
+
*
|
1072 |
+
* @return Ampersand_Api_Model_Sales_Order
|
1073 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
1074 |
+
*/
|
1075 |
+
protected function _reinitStores()
|
1076 |
+
{
|
1077 |
+
if (!$this->_storesInitialised) {
|
1078 |
+
Mage::app()->reinitStores();
|
1079 |
+
$this->_storesInitialised = true;
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
return $this;
|
1083 |
+
}
|
1084 |
+
|
1085 |
+
/**
|
1086 |
+
* Retrieve the current website from the active store.
|
1087 |
+
*
|
1088 |
+
* @return Mage_Core_Model_Website
|
1089 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
1090 |
+
*/
|
1091 |
+
protected function _getWebsite()
|
1092 |
+
{
|
1093 |
+
return $this->_getStore()->getWebsite();
|
1094 |
+
}
|
1095 |
+
}
|
app/code/core/Ampersand/Api/Model/Sales/Order/Creditmemo.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* example data
|
4 |
+
* $shipmentData = array(
|
5 |
+
* 'items' => array(
|
6 |
+
* array(
|
7 |
+
* 'sku' => 'test-product-1',
|
8 |
+
* 'qty' => 3,
|
9 |
+
* ),
|
10 |
+
* array(
|
11 |
+
* 'sku' => 'test-product-2',
|
12 |
+
* 'qty' => 5,
|
13 |
+
* ),
|
14 |
+
* ),
|
15 |
+
* 'created_at' => '2011-12-14 10:35:12',
|
16 |
+
* );
|
17 |
+
*/
|
18 |
+
class Ampersand_Api_Model_Sales_Order_Creditmemo
|
19 |
+
{
|
20 |
+
public function create($orderIncrementId, array $creditMemo) {
|
21 |
+
$creditmemoApi = Mage::getModel('sales/order_creditmemo_api');
|
22 |
+
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
|
23 |
+
|
24 |
+
$qtys = array();
|
25 |
+
foreach($creditMemo['items'] as $_itemData) {
|
26 |
+
$orderItem = $order
|
27 |
+
->getItemsCollection()
|
28 |
+
->addFieldToFilter('sku', $_itemData['sku'])
|
29 |
+
->getFirstItem();
|
30 |
+
|
31 |
+
$qtys[$orderItem->getId()] = $_itemData['qty'];
|
32 |
+
}
|
33 |
+
|
34 |
+
$creditmemoIncrementId = $creditmemoApi->create($orderIncrementId, $qtys);
|
35 |
+
|
36 |
+
if (array_key_exists('created_at', $creditMemo)) {
|
37 |
+
$creditmemo = Mage::getModel('sales/order_creditmemo')->load($creditmemoIncrementId, 'increment_id');
|
38 |
+
$creditmemo->setCreatedAt($creditMemo['created_at']);
|
39 |
+
$creditmemo->save();
|
40 |
+
}
|
41 |
+
|
42 |
+
return $creditmemoIncrementId;
|
43 |
+
}
|
44 |
+
}
|
app/code/core/Ampersand/Api/Model/Sales/Order/Invoice.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* example data
|
4 |
+
* $invoiceData = array(
|
5 |
+
* 'items' => array(
|
6 |
+
* array(
|
7 |
+
* 'sku' => 'test-product-1',
|
8 |
+
* 'qty' => 3,
|
9 |
+
* ),
|
10 |
+
* array(
|
11 |
+
* 'sku' => 'test-product-2',
|
12 |
+
* 'qty' => 5,
|
13 |
+
* ),
|
14 |
+
* ),
|
15 |
+
* 'created_at' => '2011-12-14 10:35:12',
|
16 |
+
* );
|
17 |
+
*/
|
18 |
+
class Ampersand_Api_Model_Sales_Order_Invoice
|
19 |
+
{
|
20 |
+
public function create($orderIncrementId, array $invoiceData) {
|
21 |
+
$invoiceApi = Mage::getModel('sales/order_invoice_api');
|
22 |
+
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
|
23 |
+
|
24 |
+
$qtys = array();
|
25 |
+
foreach($invoiceData['items'] as $_itemData) {
|
26 |
+
$orderItem = $order
|
27 |
+
->getItemsCollection()
|
28 |
+
->addFieldToFilter('sku', $_itemData['sku'])
|
29 |
+
->getFirstItem();
|
30 |
+
|
31 |
+
$qtys[$orderItem->getId()] = $_itemData['qty'];
|
32 |
+
}
|
33 |
+
|
34 |
+
$invoiceIncrementId = $invoiceApi->create($orderIncrementId, $qtys);
|
35 |
+
|
36 |
+
if (array_key_exists('created_at', $invoiceData)) {
|
37 |
+
$invoice = Mage::getModel('sales/order_invoice')->loadByIncrementId($invoiceIncrementId);
|
38 |
+
$invoice->setCreatedAt($invoiceData['created_at']);
|
39 |
+
$invoice->save();
|
40 |
+
}
|
41 |
+
|
42 |
+
return $invoiceIncrementId;
|
43 |
+
}
|
44 |
+
}
|
app/code/core/Ampersand/Api/Model/Sales/Order/Shipment.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* example data
|
4 |
+
* $shipmentData = array(
|
5 |
+
* 'items' => array(
|
6 |
+
* array(
|
7 |
+
* 'sku' => 'test-product-1',
|
8 |
+
* 'qty' => 3,
|
9 |
+
* ),
|
10 |
+
* array(
|
11 |
+
* 'sku' => 'test-product-2',
|
12 |
+
* 'qty' => 5,
|
13 |
+
* ),
|
14 |
+
* ),
|
15 |
+
* 'created_at' => '2011-12-14 10:35:12',
|
16 |
+
* );
|
17 |
+
*/
|
18 |
+
class Ampersand_Api_Model_Sales_Order_Shipment
|
19 |
+
{
|
20 |
+
public function create($orderIncrementId, array $shipmentData) {
|
21 |
+
$shipmentApi = Mage::getModel('sales/order_shipment_api');
|
22 |
+
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
|
23 |
+
|
24 |
+
$qtys = array();
|
25 |
+
foreach($shipmentData['items'] as $_itemData) {
|
26 |
+
$orderItem = $order
|
27 |
+
->getItemsCollection()
|
28 |
+
->addFieldToFilter('sku', $_itemData['sku'])
|
29 |
+
->getFirstItem();
|
30 |
+
|
31 |
+
$qtys[$orderItem->getId()] = $_itemData['qty'];
|
32 |
+
}
|
33 |
+
|
34 |
+
$shipmentIncrementId = $shipmentApi->create($orderIncrementId, $qtys);
|
35 |
+
|
36 |
+
if (array_key_exists('created_at', $shipmentData)) {
|
37 |
+
$shipment = Mage::getModel('sales/order_shipment')->loadByIncrementId($shipmentIncrementId);
|
38 |
+
$shipment->setCreatedAt($shipmentData['created_at']);
|
39 |
+
$shipment->save();
|
40 |
+
}
|
41 |
+
|
42 |
+
return $shipmentIncrementId;
|
43 |
+
}
|
44 |
+
}
|
app/code/core/Ampersand/Api/Model/Sales/Quote.php
ADDED
@@ -0,0 +1,319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Api_Model_Sales_Quote extends Mage_Sales_Model_Order_Api
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Create a quote.
|
6 |
+
*
|
7 |
+
* @param array $quoteData
|
8 |
+
* $quoteData = array(
|
9 |
+
* 'store_id' => '1',
|
10 |
+
* 'customer_id' => '5',
|
11 |
+
* 'shipping_method' => 'flatrate_flatrate',
|
12 |
+
* ... etc ...
|
13 |
+
* );
|
14 |
+
*
|
15 |
+
* @param array $productDatas
|
16 |
+
* $productDatas = array(
|
17 |
+
* array(
|
18 |
+
* // either product id or sku (required)
|
19 |
+
* 'product_id' => '123',
|
20 |
+
* 'sku' => 'some_sku',
|
21 |
+
*
|
22 |
+
* // either child product id or child sku (optional)
|
23 |
+
* 'child_product_id' => '123',
|
24 |
+
* 'child_sku' => 'some_simple_sku',
|
25 |
+
*
|
26 |
+
* // configurable attribute values if no child sku or product id provided (optional)
|
27 |
+
* 'configurable_attributes' => array(
|
28 |
+
* 'attribute_code' => 'attribute_label',
|
29 |
+
* ),
|
30 |
+
*
|
31 |
+
* // quantity to add (optional)
|
32 |
+
* 'qty' => '5',
|
33 |
+
* ... etc ...
|
34 |
+
* ),
|
35 |
+
* );
|
36 |
+
*
|
37 |
+
* @param array $addressDatas
|
38 |
+
* $addressDatas = array(
|
39 |
+
* 'billing' => array(
|
40 |
+
* 'firstname' => 'John',
|
41 |
+
* 'lastname' => 'Smith',
|
42 |
+
* ... etc ...
|
43 |
+
* ),
|
44 |
+
* 'shipping' => array(
|
45 |
+
* 'firstname' => 'John',
|
46 |
+
* 'lastname' => 'Smith',
|
47 |
+
* ... etc ...
|
48 |
+
* ),
|
49 |
+
* );
|
50 |
+
*
|
51 |
+
* @return int
|
52 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
53 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
54 |
+
*/
|
55 |
+
public function create(array $quoteData, array $productDatas, array $addressDatas)
|
56 |
+
{
|
57 |
+
try {
|
58 |
+
// initialize quote data object
|
59 |
+
$quoteDataObject = new Varien_Object();
|
60 |
+
$quoteDataObject->addData($quoteData);
|
61 |
+
|
62 |
+
// create a quote instance and add provided data
|
63 |
+
$quote = Mage::getModel('sales/quote')->addData($quoteDataObject->getData());
|
64 |
+
|
65 |
+
// set the quote to inactive so it does not interfere with the customers frontend quotes
|
66 |
+
$quote->setIsActive('0');
|
67 |
+
if (array_key_exists('is_active', $quoteData)) {
|
68 |
+
$quote->setIsActive($quoteData['is_active']);
|
69 |
+
}
|
70 |
+
|
71 |
+
// assign customer to quote, if provided
|
72 |
+
$customer = Mage::getModel('customer/customer')->load($quoteDataObject->getCustomerId());
|
73 |
+
if ($customer->getId()) {
|
74 |
+
$quote->setCustomer($customer);
|
75 |
+
}
|
76 |
+
|
77 |
+
// add products to quote
|
78 |
+
$productSingleton = Mage::getSingleton('catalog/product');
|
79 |
+
foreach ($productDatas as $_productData) {
|
80 |
+
// initialize product data object
|
81 |
+
$_productDataObject = new Ampersand_Object($_productData);
|
82 |
+
|
83 |
+
// retrieve the product
|
84 |
+
$_productId = $_productDataObject->getProductId();
|
85 |
+
if (!$_productId) {
|
86 |
+
$_sku = $_productDataObject->getSku();
|
87 |
+
$_productId = $productSingleton->getIdBySku($_sku);
|
88 |
+
}
|
89 |
+
$_product = Mage::getModel('catalog/product')->load($_productId);
|
90 |
+
$_sku = $_product->getSku();
|
91 |
+
if (!$_sku || !$_product->getId()) {
|
92 |
+
$this->_fault(
|
93 |
+
'product_not_exists',
|
94 |
+
Mage::helper('ampersand_api')
|
95 |
+
->__("Product with SKU '$_sku' could not be found.")
|
96 |
+
);
|
97 |
+
}
|
98 |
+
|
99 |
+
// retrieve the child product id if provided
|
100 |
+
$_childProductId = $_productDataObject->getChildProductId();
|
101 |
+
if (!$_childProductId) {
|
102 |
+
$_childSku = $_productDataObject->getChildSku();
|
103 |
+
$_childProductId = $productSingleton->getIdBySku($_childSku);
|
104 |
+
}
|
105 |
+
if (!$_childProductId) {
|
106 |
+
$_childProductId = null;
|
107 |
+
}
|
108 |
+
|
109 |
+
// add the product to the quote
|
110 |
+
try {
|
111 |
+
$_request = Mage::helper('ampersand_sales/quote')->prepareProductRequest(
|
112 |
+
$_product,
|
113 |
+
$_productData,
|
114 |
+
$_childProductId,
|
115 |
+
$_productDataObject->getConfigurableAttributes()
|
116 |
+
);
|
117 |
+
$_item = $quote->addProduct($_product, $_request);
|
118 |
+
if (is_string($_item)) {
|
119 |
+
throw new Exception($_item);
|
120 |
+
}
|
121 |
+
} catch (Exception $e) {
|
122 |
+
$this->_fault(
|
123 |
+
'order_not_created',
|
124 |
+
Mage::helper('ampersand_api')->__(
|
125 |
+
"Product with SKU '$_sku' exists but could not be added to order. "
|
126 |
+
. PHP_EOL . $e->getMessage()
|
127 |
+
)
|
128 |
+
);
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
// ensure we have at least one item in the quote
|
133 |
+
if (count($quote->getAllItems()) < 1) {
|
134 |
+
$this->_fault('no_items_added');
|
135 |
+
}
|
136 |
+
|
137 |
+
// initialize address data types
|
138 |
+
if (!array_key_exists('billing', $addressDatas)) {
|
139 |
+
$addressDatas['billing'] = array();
|
140 |
+
}
|
141 |
+
if (!array_key_exists('shipping', $addressDatas)) {
|
142 |
+
$addressDatas['shipping'] = $addressDatas['billing'];
|
143 |
+
}
|
144 |
+
$addressDatas['shipping']['shipping_method'] = $quoteDataObject->getShippingMethod();
|
145 |
+
|
146 |
+
// add the billing address data to the quote
|
147 |
+
$quote->getBillingAddress()
|
148 |
+
->addData($addressDatas['billing']);
|
149 |
+
|
150 |
+
// add the shipping address data to the quote
|
151 |
+
$quote->getShippingAddress()
|
152 |
+
->addData($addressDatas['shipping'])
|
153 |
+
->setCollectShippingRates(true);
|
154 |
+
|
155 |
+
// set the payment information if provided
|
156 |
+
$paymentData = $quoteDataObject->getPayment();
|
157 |
+
if (!empty($paymentData)) {
|
158 |
+
$quote->getPayment()->importData($paymentData);
|
159 |
+
}
|
160 |
+
|
161 |
+
// collect totals and save quote instance to database
|
162 |
+
$quote->setTotalsCollectedFlag(false)->collectTotals()->save();
|
163 |
+
} catch (Mage_Api_Exception $e) {
|
164 |
+
throw $e;
|
165 |
+
} catch (Exception $e) {
|
166 |
+
$this->_fault('quote_not_created', $e->getMessage());
|
167 |
+
}
|
168 |
+
|
169 |
+
return $quote->getId();
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Create a quote based on an order.
|
174 |
+
*
|
175 |
+
* @param int $orderId
|
176 |
+
* @return int
|
177 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
178 |
+
*/
|
179 |
+
public function createFromOrder($orderId)
|
180 |
+
{
|
181 |
+
// retrieve the order
|
182 |
+
$order = Mage::getModel('sales/order')->load($orderId);
|
183 |
+
if (!$order->getId()) {
|
184 |
+
$this->_fault('order_not_exists');
|
185 |
+
}
|
186 |
+
|
187 |
+
// prepare quote data
|
188 |
+
$quoteData = array(
|
189 |
+
'store_id' => $order->getStoreId(),
|
190 |
+
'customer_id' => $order->getCustomerId(),
|
191 |
+
'shipping_method' => $order->getShippingMethod(),
|
192 |
+
);
|
193 |
+
|
194 |
+
// prepare product data
|
195 |
+
$orderItemIdMap = array();
|
196 |
+
foreach ($order->getAllItems() as $_item) {
|
197 |
+
$orderItemIdMap[$_item->getId()] = $_item;
|
198 |
+
}
|
199 |
+
$itemDatas = array();
|
200 |
+
foreach ($order->getAllItems() as $_item) {
|
201 |
+
$_itemProductOptions = $this->_getOrderItemProductOptions($_item);
|
202 |
+
if ($_item->getParentItemId()) {
|
203 |
+
$itemDatas[] = array_merge($_itemProductOptions, array(
|
204 |
+
'child_product_id' => $_item->getProductId(),
|
205 |
+
'product_id' => $orderItemIdMap[$_item->getParentItemId()]->getProductId(),
|
206 |
+
'qty' => $_item->getQtyOrdered(),
|
207 |
+
));
|
208 |
+
} elseif (!$_item->getHasChildren()) {
|
209 |
+
$itemDatas[] = array_merge($_itemProductOptions, array(
|
210 |
+
'product_id' => $_item->getProductId(),
|
211 |
+
'qty' => $_item->getQtyOrdered(),
|
212 |
+
));
|
213 |
+
}
|
214 |
+
}
|
215 |
+
|
216 |
+
// prepare address data
|
217 |
+
$addressAttributes = array(
|
218 |
+
'customer_id',
|
219 |
+
'customer_address_id',
|
220 |
+
'company',
|
221 |
+
'prefix',
|
222 |
+
'firstname',
|
223 |
+
'middlename',
|
224 |
+
'lastname',
|
225 |
+
'suffix',
|
226 |
+
'street',
|
227 |
+
'city',
|
228 |
+
'country_id',
|
229 |
+
'region',
|
230 |
+
'region_id',
|
231 |
+
'postcode',
|
232 |
+
'email',
|
233 |
+
'telephone',
|
234 |
+
'fax',
|
235 |
+
);
|
236 |
+
$billingAddress = $order->getBillingAddress();
|
237 |
+
$shippingAddress = $order->getShippingAddress();
|
238 |
+
foreach ($addressAttributes as $_attribute) {
|
239 |
+
$addressDatas['billing'][$_attribute] = $billingAddress->getData($_attribute);
|
240 |
+
$addressDatas['shipping'][$_attribute] = $shippingAddress->getData($_attribute);
|
241 |
+
}
|
242 |
+
|
243 |
+
// create the order and return the order id
|
244 |
+
return $this->create($quoteData, $itemDatas, $addressDatas);
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Retrieve any additional order item data required for certain product types.
|
249 |
+
*
|
250 |
+
* @param Mage_Sales_Model_Order_Item $_item
|
251 |
+
* @return array
|
252 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
253 |
+
*/
|
254 |
+
protected function _getOrderItemProductOptions($_item)
|
255 |
+
{
|
256 |
+
$options = array();
|
257 |
+
|
258 |
+
switch ($_item->getProductType()) {
|
259 |
+
case Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE:
|
260 |
+
$itemProductOptions = $_item->getProductOptions();
|
261 |
+
$options['links'] = array_key_exists('links', $itemProductOptions)
|
262 |
+
? $itemProductOptions['links'] : array();
|
263 |
+
break;
|
264 |
+
|
265 |
+
default:
|
266 |
+
break;
|
267 |
+
}
|
268 |
+
|
269 |
+
return $options;
|
270 |
+
}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* Convert a quote to an order.
|
274 |
+
*
|
275 |
+
* @param int $quoteId
|
276 |
+
* @param array $orderData
|
277 |
+
* @param array $paymentData
|
278 |
+
* @return int
|
279 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
280 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
281 |
+
*/
|
282 |
+
public function convertToOrder($quoteId, $orderData = array(), $paymentData = array())
|
283 |
+
{
|
284 |
+
try {
|
285 |
+
// retrieve the quote
|
286 |
+
$quote = Mage::getModel('sales/quote');
|
287 |
+
if (method_exists($quote, 'loadByIdWithoutStore')) {
|
288 |
+
$quote->loadByIdWithoutStore($quoteId);
|
289 |
+
} else {
|
290 |
+
$quote->load($quoteId);
|
291 |
+
}
|
292 |
+
|
293 |
+
if (!$quote->getId()) {
|
294 |
+
$this->_fault('quote_not_exists');
|
295 |
+
}
|
296 |
+
|
297 |
+
// set the payment information if provided
|
298 |
+
if (!empty($paymentData)) {
|
299 |
+
$quote->getPayment()->importData($paymentData);
|
300 |
+
}
|
301 |
+
|
302 |
+
// collect totals and save quote instance to database
|
303 |
+
$quote->setTotalsCollectedFlag(false)->collectTotals();
|
304 |
+
|
305 |
+
// initialise service with order data, if provided
|
306 |
+
$service = Mage::getModel('sales/service_quote', $quote);
|
307 |
+
$service->setOrderData($orderData);
|
308 |
+
|
309 |
+
// convert to order
|
310 |
+
$order = $service->submit();
|
311 |
+
} catch (Mage_Api_Exception $e) {
|
312 |
+
throw $e;
|
313 |
+
} catch (Exception $e) {
|
314 |
+
$this->_fault('order_not_created', $e->getMessage());
|
315 |
+
}
|
316 |
+
|
317 |
+
return $order->getId();
|
318 |
+
}
|
319 |
+
}
|
app/code/core/Ampersand/Api/etc/api.xml
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<api>
|
4 |
+
<resources>
|
5 |
+
<ampersand_api translate="title" module="ampersand_api">
|
6 |
+
<model>ampersand_api/catalog_product</model>
|
7 |
+
<title>Ampersand Api</title>
|
8 |
+
<acl>ampersand_api</acl>
|
9 |
+
<methods>
|
10 |
+
<info translate="title" module="ampersand_api">
|
11 |
+
<title>Retrive Product Info</title>
|
12 |
+
<method>info</method>
|
13 |
+
<acl>ampersand_api/info</acl>
|
14 |
+
</info>
|
15 |
+
</methods>
|
16 |
+
</ampersand_api>
|
17 |
+
</resources>
|
18 |
+
<acl>
|
19 |
+
<resources>
|
20 |
+
<ampersand_api translate="title" module="ampersand_api">
|
21 |
+
<title>Ampersand Api</title>
|
22 |
+
<info translate="title" module="ampersand_api">
|
23 |
+
<title>Retrive Product Info</title>
|
24 |
+
</info>
|
25 |
+
</ampersand_api>
|
26 |
+
</resources>
|
27 |
+
</acl>
|
28 |
+
</api>
|
29 |
+
</config>
|
app/code/core/Ampersand/Api/etc/config.xml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Ampersand_Api>
|
5 |
+
<version>0.1.0</version>
|
6 |
+
</Ampersand_Api>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<models>
|
10 |
+
<ampersand_api>
|
11 |
+
<class>Ampersand_Api_Model</class>
|
12 |
+
</ampersand_api>
|
13 |
+
</models>
|
14 |
+
<helpers>
|
15 |
+
<ampersand_api>
|
16 |
+
<class>Ampersand_Api_Helper</class>
|
17 |
+
</ampersand_api>
|
18 |
+
</helpers>
|
19 |
+
</global>
|
20 |
+
</config>
|
app/code/core/Ampersand/Catalog/Helper/Category.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Catalog_Helper_Category extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Top category level.
|
6 |
+
*/
|
7 |
+
const TOP_CATEGORY_LEVEL = 2;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Cache of categories by url key.
|
11 |
+
* We store like this just in case there are restrictions over array keys.
|
12 |
+
*
|
13 |
+
* @var array $_category
|
14 |
+
*/
|
15 |
+
protected $_categoryUrlKeys = array();
|
16 |
+
protected $_categoriesByUrlKey = array();
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Cache of root categories.
|
20 |
+
*
|
21 |
+
* @var array $_rootCategories
|
22 |
+
*/
|
23 |
+
protected $_rootCategories = array();
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Retreive the URL for a category by url key(s) and store.
|
27 |
+
*
|
28 |
+
* @param string $urlKey
|
29 |
+
* @param mixed $store
|
30 |
+
* @return string
|
31 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
32 |
+
*/
|
33 |
+
public function getUrlByUrlKeys($urlKeys, $store = null)
|
34 |
+
{
|
35 |
+
return $this->getCategoryByUrlKeys($urlKeys, $store)->getUrl();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Retrieve a category by url key(s) and store.
|
40 |
+
*
|
41 |
+
* @param string $urlKeys
|
42 |
+
* @param mixed $store
|
43 |
+
* @param bool $useCache
|
44 |
+
* @return Mage_Catalog_Model_Category
|
45 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
46 |
+
*/
|
47 |
+
public function getCategoryByUrlKeys($urlKeys, $store = null, $useCache = true)
|
48 |
+
{
|
49 |
+
$store = Mage::app()->getStore($store);
|
50 |
+
$storeId = $store->getId();
|
51 |
+
|
52 |
+
if ($useCache && array_key_exists($storeId, $this->_categoryUrlKeys)
|
53 |
+
&& (($key = array_search($urlKeys, $this->_categoryUrlKeys[$storeId])) !== FALSE)) {
|
54 |
+
return $this->_categoriesByUrlKey[$storeId][$key];
|
55 |
+
}
|
56 |
+
|
57 |
+
$this->_categoryUrlKeys[$storeId][] = $urlKeys;
|
58 |
+
$key = array_search($urlKeys, $this->_categoryUrlKeys[$storeId]);
|
59 |
+
$this->_categoriesByUrlKey[$storeId][$key] = null;
|
60 |
+
|
61 |
+
$parentId = null;
|
62 |
+
$urlKeyParts = explode('/', $urlKeys);
|
63 |
+
foreach ($urlKeyParts as $_urlKey) {
|
64 |
+
$_urlKey = trim($_urlKey);
|
65 |
+
if (empty($_urlKey)) {
|
66 |
+
continue;
|
67 |
+
}
|
68 |
+
|
69 |
+
$filters = array(
|
70 |
+
'url_key' => $_urlKey,
|
71 |
+
);
|
72 |
+
|
73 |
+
if (is_null($parentId)) {
|
74 |
+
$filters['level'] = self::TOP_CATEGORY_LEVEL;
|
75 |
+
} else {
|
76 |
+
$filters['parent_id'] = $parentId;
|
77 |
+
}
|
78 |
+
|
79 |
+
$category = $this->getCategoryByFilters($filters, $store);
|
80 |
+
if ($category->getId()) {
|
81 |
+
$parentId = $category->getId();
|
82 |
+
} else {
|
83 |
+
// unable to find the category
|
84 |
+
return null;
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
$this->_categoriesByUrlKey[$storeId][$key] = $category
|
89 |
+
->setStoreId($storeId)
|
90 |
+
->load($category->getId());
|
91 |
+
|
92 |
+
return $this->_categoriesByUrlKey[$storeId][$key];
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Retreive a category by attribute filters.
|
97 |
+
*
|
98 |
+
* @param array $filters
|
99 |
+
* @return Mage_Catalog_Model_Category
|
100 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
101 |
+
*/
|
102 |
+
public function getCategoryByFilters(array $filters, $store = null)
|
103 |
+
{
|
104 |
+
$store = Mage::app()->getStore($store);
|
105 |
+
|
106 |
+
$rootCategory = $this->getRootCategory($store);
|
107 |
+
$collection = Mage::getResourceModel('catalog/category_collection')
|
108 |
+
->addAttributeToFilter('path', array('like' => "{$rootCategory->getPath()}%"));
|
109 |
+
|
110 |
+
foreach ($filters as $_key => $_value) {
|
111 |
+
$collection->addAttributeToFilter($_key, $_value);
|
112 |
+
}
|
113 |
+
|
114 |
+
return $collection->getFirstItem();
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Retrieve the root category for a store.
|
119 |
+
*
|
120 |
+
* @param mixed $store
|
121 |
+
* @return Mage_Catalog_Model_Category
|
122 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
123 |
+
*/
|
124 |
+
public function getRootCategory($store = null)
|
125 |
+
{
|
126 |
+
$store = Mage::app()->getStore($store);
|
127 |
+
$storeId = $store->getId();
|
128 |
+
|
129 |
+
if (!array_key_exists($storeId, $this->_rootCategories)) {
|
130 |
+
$this->_rootCategories[$storeId] = Mage::getModel('catalog/category')
|
131 |
+
->setStoreId($store->getId())
|
132 |
+
->load($store->getRootCategoryId());
|
133 |
+
}
|
134 |
+
|
135 |
+
return $this->_rootCategories[$storeId];
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Clear category cache.
|
140 |
+
*
|
141 |
+
* @param mixed $store
|
142 |
+
* @return Ampersand_Catalog_Helper_Category
|
143 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
144 |
+
*/
|
145 |
+
public function clearCache($store = null)
|
146 |
+
{
|
147 |
+
if (is_null($store)) {
|
148 |
+
$this->_categoryUrlKeys = array();
|
149 |
+
$this->_categoriesByUrlKey = array();
|
150 |
+
$this->_rootCategories = array();
|
151 |
+
} else {
|
152 |
+
$storeId = Mage::app()->getStore($store)->getId();
|
153 |
+
$this->_categoryUrlKeys[$storeId] = array();
|
154 |
+
$this->_categoriesByUrlKey[$storeId] = array();
|
155 |
+
$this->_rootCategories[$storeId] = array();
|
156 |
+
}
|
157 |
+
|
158 |
+
return $this;
|
159 |
+
}
|
160 |
+
}
|
app/code/core/Ampersand/Catalog/Helper/Product.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Catalog_Helper_Product extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Cache of products by SKU.
|
6 |
+
*
|
7 |
+
* @var array $_product
|
8 |
+
*/
|
9 |
+
protected $_productsBySku = array();
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Retreive the URL for a product by SKU and store.
|
13 |
+
*
|
14 |
+
* @param string $sku
|
15 |
+
* @param mixed $store
|
16 |
+
* @return string
|
17 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
18 |
+
*/
|
19 |
+
public function getUrlBySku($sku, $store = null)
|
20 |
+
{
|
21 |
+
return $this->getProductBySku($sku, $store)->getProductUrl();
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Retreive a product by SKU and store.
|
26 |
+
*
|
27 |
+
* @param string $sku
|
28 |
+
* @param mixed $store
|
29 |
+
* @return Mage_Catalog_Model_Product
|
30 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
31 |
+
*/
|
32 |
+
public function getProductBySku($sku, $store = null)
|
33 |
+
{
|
34 |
+
$store = Mage::app()->getStore($store);
|
35 |
+
|
36 |
+
$storeId = $store->getId();
|
37 |
+
$productId = Mage::getSingleton('catalog/product')->getIdBySku($sku);
|
38 |
+
|
39 |
+
if (!array_key_exists($storeId, $this->_productsBySku)
|
40 |
+
|| !array_key_exists($productId, $this->_productsBySku[$storeId])) {
|
41 |
+
$this->_productsBySku[$storeId][$productId] = Mage::getModel('catalog/product')
|
42 |
+
->setStoreId($storeId)
|
43 |
+
->load($productId);
|
44 |
+
}
|
45 |
+
|
46 |
+
return $this->_productsBySku[$storeId][$productId];
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Clear product cache.
|
51 |
+
*
|
52 |
+
* @param mixed $store
|
53 |
+
* @return Ampersand_Catalog_Helper_Product
|
54 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
55 |
+
*/
|
56 |
+
public function clearCache($store = null)
|
57 |
+
{
|
58 |
+
if (is_null($store)) {
|
59 |
+
$this->_productsBySku = array();
|
60 |
+
} else {
|
61 |
+
$storeId = Mage::app()->getStore($store)->getId();
|
62 |
+
$this->_productsBySku[$storeId] = array();
|
63 |
+
}
|
64 |
+
|
65 |
+
return $this;
|
66 |
+
}
|
67 |
+
}
|
app/code/core/Ampersand/Catalog/Helper/Product/Attribute.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Catalog_Helper_Product_Attribute extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Retrieve attribute by code.
|
6 |
+
*
|
7 |
+
* @param string $code
|
8 |
+
* @return Mage_Eav_Model_Entity_Attribute_Abstract
|
9 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
10 |
+
*/
|
11 |
+
public function getAttribute($code)
|
12 |
+
{
|
13 |
+
return Mage::getModel('catalog/product')
|
14 |
+
->getResource()
|
15 |
+
->getAttribute($code);
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Retreive attribute option id by value.
|
20 |
+
*
|
21 |
+
* @param mixed $attribute
|
22 |
+
* @param string $value
|
23 |
+
* @return int
|
24 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
25 |
+
*/
|
26 |
+
public function getAttributeOptionId($attribute, $value)
|
27 |
+
{
|
28 |
+
if (!$attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) {
|
29 |
+
$attribute = $this->getAttribute($attribute);
|
30 |
+
}
|
31 |
+
|
32 |
+
return $attribute->getSource()->getOptionId($value);
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Retrieve attribute set by code.
|
37 |
+
*
|
38 |
+
* @param string $code
|
39 |
+
* @return Mage_Eav_Model_Entity_Attribute_Set
|
40 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
41 |
+
*/
|
42 |
+
public function getAttributeSet($code)
|
43 |
+
{
|
44 |
+
$attributeSet = Mage::getResourceModel('eav/entity_attribute_set_collection')
|
45 |
+
->setEntityTypeFilter($this->getEntityTypeId('catalog_product'))
|
46 |
+
->addFieldToFilter('attribute_set_name', $code)
|
47 |
+
->getFirstItem();
|
48 |
+
|
49 |
+
return $attributeSet;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Retrieve entity type id by code.
|
54 |
+
*
|
55 |
+
* @param string $code
|
56 |
+
* @return int
|
57 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
58 |
+
*/
|
59 |
+
public function getEntityTypeId($code)
|
60 |
+
{
|
61 |
+
return Mage::getModel('eav/entity_type')->loadByCode($code)->getId();
|
62 |
+
}
|
63 |
+
}
|
app/code/core/Ampersand/Catalog/etc/config.xml
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Ampersand_Catalog>
|
5 |
+
<version>0.0.1</version>
|
6 |
+
</Ampersand_Catalog>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<helpers>
|
10 |
+
<ampersand_catalog>
|
11 |
+
<class>Ampersand_Catalog_Helper</class>
|
12 |
+
</ampersand_catalog>
|
13 |
+
</helpers>
|
14 |
+
</global>
|
15 |
+
</config>
|
app/code/core/Ampersand/Core/Helper/Data.php
CHANGED
@@ -1,13 +1,141 @@
|
|
1 |
<?php
|
2 |
class Ampersand_Core_Helper_Data extends Ampersand_Core_Helper_Abstract
|
3 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
public function prepareStringForHtmlRender($string)
|
5 |
{
|
|
|
6 |
$string = str_replace(' ', '<space/>', $string);
|
7 |
-
$string = $this->
|
8 |
$string = str_replace('<space/>', ' ', $string);
|
9 |
$string = nl2br($string);
|
10 |
|
11 |
return $string;
|
12 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
}
|
1 |
<?php
|
2 |
class Ampersand_Core_Helper_Data extends Ampersand_Core_Helper_Abstract
|
3 |
{
|
4 |
+
const CONFIG_PATH_PREFIX = '__AMPERSAND/';
|
5 |
+
|
6 |
+
protected $_lockFiles = array();
|
7 |
+
protected $_cachedValues = array();
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @param string $string
|
11 |
+
* @return string
|
12 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
13 |
+
*/
|
14 |
public function prepareStringForHtmlRender($string)
|
15 |
{
|
16 |
+
$string = utf8_encode($string);
|
17 |
$string = str_replace(' ', '<space/>', $string);
|
18 |
+
$string = $this->htmlEscape($string, array('space'));
|
19 |
$string = str_replace('<space/>', ' ', $string);
|
20 |
$string = nl2br($string);
|
21 |
|
22 |
return $string;
|
23 |
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @param string $key
|
27 |
+
* @return bool Returns true on success or false on failure
|
28 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
29 |
+
*/
|
30 |
+
public function lock($key)
|
31 |
+
{
|
32 |
+
if (!$file = $this->_getLockFile($key)) {
|
33 |
+
return false;
|
34 |
+
}
|
35 |
+
|
36 |
+
return flock($file, LOCK_EX | LOCK_NB);
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @param string $key
|
41 |
+
* @return bool Returns true on success or false on failure
|
42 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
43 |
+
*/
|
44 |
+
public function unlock($key)
|
45 |
+
{
|
46 |
+
if (!$file = $this->_getLockFile($key)) {
|
47 |
+
return false;
|
48 |
+
|
49 |
+
}
|
50 |
+
|
51 |
+
return flock($file, LOCK_UN);
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @param string $key
|
56 |
+
* @return resource
|
57 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
58 |
+
*/
|
59 |
+
protected function _getLockFile($key)
|
60 |
+
{
|
61 |
+
if (!array_key_exists($key, $this->_lockFiles)) {
|
62 |
+
$varDir = Mage::getConfig()->getVarDir('locks');
|
63 |
+
$filePath = $varDir . DS . 'ampersand_' . md5($key) . '.lock';
|
64 |
+
|
65 |
+
if (is_file($filePath)) {
|
66 |
+
$this->_lockFiles[$key] = fopen($filePath, 'w');
|
67 |
+
} else {
|
68 |
+
$this->_lockFiles[$key] = fopen($filePath, 'x');
|
69 |
+
|
70 |
+
$oldMask = umask(0);
|
71 |
+
chmod($filePath, 0777);
|
72 |
+
umask($oldMask);
|
73 |
+
}
|
74 |
+
|
75 |
+
fwrite($this->_lockFiles[$key], date('r'));
|
76 |
+
}
|
77 |
+
|
78 |
+
return $this->_lockFiles[$key];
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* @param string $name
|
83 |
+
* @param mixed $value
|
84 |
+
* @return Ampersand_Core_Helper_Data
|
85 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
86 |
+
*/
|
87 |
+
public function saveValue($name, $value)
|
88 |
+
{
|
89 |
+
Mage::getModel('ampersand_core/value')
|
90 |
+
->setName($name)
|
91 |
+
->setValue($value)
|
92 |
+
->save();
|
93 |
+
|
94 |
+
$this->_cachedValues[$name] = $value;
|
95 |
+
|
96 |
+
return $this;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @param string $name
|
101 |
+
* @return null|string
|
102 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
103 |
+
*/
|
104 |
+
public function loadValue($name)
|
105 |
+
{
|
106 |
+
if (!in_array($name, $this->_cachedValues)) {
|
107 |
+
$this->_cachedValues[$name] = Mage::getModel('ampersand_core/value')
|
108 |
+
->load($name)
|
109 |
+
->getValue();
|
110 |
+
}
|
111 |
+
|
112 |
+
return $this->_cachedValues[$name];
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* @param string $name
|
117 |
+
* @return Ampersand_Core_Helper_Data
|
118 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
119 |
+
*/
|
120 |
+
public function deleteValue($name)
|
121 |
+
{
|
122 |
+
Mage::getModel('ampersand_core/value')
|
123 |
+
->load($name)
|
124 |
+
->delete();
|
125 |
+
|
126 |
+
unset($this->_cachedValues[$name]);
|
127 |
+
|
128 |
+
return $this;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Retrieve whether the current request is secure.
|
133 |
+
*
|
134 |
+
* @return bool
|
135 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
136 |
+
*/
|
137 |
+
public function isSecure()
|
138 |
+
{
|
139 |
+
return Mage::app()->getStore()->isCurrentlySecure();
|
140 |
+
}
|
141 |
}
|
app/code/core/Ampersand/Core/Helper/File.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* method related to file system
|
4 |
+
*/
|
5 |
+
class Ampersand_Core_Helper_File extends Mage_Core_Helper_Abstract
|
6 |
+
{
|
7 |
+
/**
|
8 |
+
* delete a directory and its contents recursively(child first)
|
9 |
+
* @param String $dir File system's directory path
|
10 |
+
*/
|
11 |
+
public function removeDirectory($dir)
|
12 |
+
{
|
13 |
+
if (is_null($dir) || !opendir($dir)) {
|
14 |
+
return;
|
15 |
+
}
|
16 |
+
|
17 |
+
$iterator = new RecursiveIteratorIterator(
|
18 |
+
new RecursiveDirectoryIterator($dir),
|
19 |
+
RecursiveIteratorIterator::CHILD_FIRST
|
20 |
+
);
|
21 |
+
|
22 |
+
foreach ($iterator as $path) {
|
23 |
+
if ($path->isDir()) {
|
24 |
+
rmdir($path->__toString());
|
25 |
+
} else {
|
26 |
+
unlink($path->__toString());
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
rmdir($dir);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
app/code/core/Ampersand/Core/Helper/Validate.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Core_Helper_Validate extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Retrieve whether the provided variable is numeric.
|
6 |
+
*
|
7 |
+
* @param mixed $value
|
8 |
+
* @return bool
|
9 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
10 |
+
*/
|
11 |
+
public function isNumeric($value)
|
12 |
+
{
|
13 |
+
return $this->isInt($value) || $this->isFloat($value);
|
14 |
+
}
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Retrieve whether the provided variable is an integer.
|
18 |
+
* Leading zero's are permitted, as are minus numbers.
|
19 |
+
*
|
20 |
+
* See test data for accepted and invalid formats.
|
21 |
+
*
|
22 |
+
* @param mixed $value
|
23 |
+
* @return bool
|
24 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
25 |
+
*/
|
26 |
+
public function isInt($value)
|
27 |
+
{
|
28 |
+
return preg_match('/^\-*\d+$/', (string)$value) === 1;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Retrieve whether the provided variable is a float.
|
33 |
+
* At least one decimal place must be included.
|
34 |
+
* Leading zero's are permitted, as are minus numbers.
|
35 |
+
*
|
36 |
+
* See test data for accepted and invalid formats.
|
37 |
+
*
|
38 |
+
* @param mixed $value
|
39 |
+
* @return bool
|
40 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
41 |
+
*/
|
42 |
+
public function isFloat($value)
|
43 |
+
{
|
44 |
+
return preg_match('/^\-*\d+\.\d+$/', (string)$value) === 1;
|
45 |
+
}
|
46 |
+
}
|
app/code/core/Ampersand/Core/Model/Mysql4/Abstract.php
CHANGED
@@ -1,5 +1,21 @@
|
|
1 |
<?php
|
2 |
abstract class Ampersand_Core_Model_Mysql4_Abstract extends Mage_Core_Model_Mysql4_Abstract
|
3 |
{
|
4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
}
|
1 |
<?php
|
2 |
abstract class Ampersand_Core_Model_Mysql4_Abstract extends Mage_Core_Model_Mysql4_Abstract
|
3 |
{
|
4 |
+
/**
|
5 |
+
* Retrieves the connection configuration with the provided name, and opens a new connection to
|
6 |
+
* the database using that configuration. Useful when multiple database connections are needed
|
7 |
+
* in order to avoid unwanted transaction rollbacks
|
8 |
+
*
|
9 |
+
* @param string $connectionConfigName OPTIONAL Defaults to core write connection
|
10 |
+
* @return Varien_Db_Adapter_Pdo_Mysql
|
11 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
12 |
+
*/
|
13 |
+
public function getNewConnection($connectionConfigName = 'core_write')
|
14 |
+
{
|
15 |
+
$connConfig = Mage::getConfig()->getResourceConnectionConfig($connectionConfigName);
|
16 |
+
$typeInstance = Mage::getSingleton('core/resource')
|
17 |
+
->getConnectionTypeInstance((string) $connConfig->type);
|
18 |
+
|
19 |
+
return $typeInstance->getConnection($connConfig);
|
20 |
+
}
|
21 |
}
|
app/code/core/Ampersand/Core/Model/Mysql4/Collection.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Core_Model_Mysql4_Collection extends Ampersand_Core_Model_Mysql4_Collection_Abstract
|
3 |
+
{
|
4 |
+
public function fromCollection(Varien_Data_Collection_Db $collection)
|
5 |
+
{
|
6 |
+
$this->fromSelect($collection->getSelect());
|
7 |
+
$this->setItemObjectClass($collection->_itemObjectClass);
|
8 |
+
|
9 |
+
return $this;
|
10 |
+
}
|
11 |
+
|
12 |
+
public function fromSelect(Zend_Db_Select $select)
|
13 |
+
{
|
14 |
+
$this->_select = $select;
|
15 |
+
|
16 |
+
return $this;
|
17 |
+
}
|
18 |
+
}
|
app/code/core/Ampersand/Core/Model/Mysql4/Collection/Abstract.php
CHANGED
@@ -61,10 +61,10 @@ abstract class Ampersand_Core_Model_Mysql4_Collection_Abstract
|
|
61 |
|
62 |
public function addFieldToFilterHaving($field, $condition = null)
|
63 |
{
|
|
|
|
|
64 |
$field = $this->_getMappedField($field);
|
65 |
-
$this->_select->having(
|
66 |
-
$this->_getConditionSql($field, $condition), null, Varien_Db_Select::TYPE_CONDITION
|
67 |
-
);
|
68 |
|
69 |
return $this;
|
70 |
}
|
@@ -97,4 +97,44 @@ abstract class Ampersand_Core_Model_Mysql4_Collection_Abstract
|
|
97 |
|
98 |
return $this;
|
99 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
}
|
61 |
|
62 |
public function addFieldToFilterHaving($field, $condition = null)
|
63 |
{
|
64 |
+
$this->_preserveColumnsOnCount = true;
|
65 |
+
|
66 |
$field = $this->_getMappedField($field);
|
67 |
+
$this->_select->having($this->_getConditionSql($field, $condition));
|
|
|
|
|
68 |
|
69 |
return $this;
|
70 |
}
|
97 |
|
98 |
return $this;
|
99 |
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Add filter to Map
|
103 |
+
*
|
104 |
+
* This is missing from Mage 1.4.0.1 CE - taken from Varien_Data_Collection_Db
|
105 |
+
*
|
106 |
+
* @param string $filter
|
107 |
+
* @param string $alias
|
108 |
+
* @param string $group default 'fields'
|
109 |
+
* @return Varien_Data_Collection_Db
|
110 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
111 |
+
*/
|
112 |
+
public function addFilterToMap($filter, $alias, $group = 'fields')
|
113 |
+
{
|
114 |
+
if (method_exists(get_parent_class(), 'addFilterToMap')) {
|
115 |
+
return parent::addFilterToMap($filter, $alias, $group);
|
116 |
+
}
|
117 |
+
|
118 |
+
if (is_null($this->_map)) {
|
119 |
+
$this->_map = array($group => array());
|
120 |
+
} else if(is_null($this->_map[$group])) {
|
121 |
+
$this->_map[$group] = array();
|
122 |
+
}
|
123 |
+
$this->_map[$group][$filter] = $alias;
|
124 |
+
|
125 |
+
return $this;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* @param int $collectionSize OPTIONAL Pass the total number of records in the search to prevent
|
130 |
+
* an additional database query
|
131 |
+
* @return Ampersand_Adminhtml_Model_Search
|
132 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
133 |
+
*/
|
134 |
+
public function getSearch($collectionSize = null)
|
135 |
+
{
|
136 |
+
return Mage::getModel('ampersand_adminhtml/search')
|
137 |
+
->fromCollection($this, $collectionSize)
|
138 |
+
->save();
|
139 |
+
}
|
140 |
}
|
app/code/core/Ampersand/Core/Model/Mysql4/Value.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Core_Model_Mysql4_Value extends Mage_Core_Model_Mysql4_Abstract
|
3 |
+
{
|
4 |
+
protected $_isPkAutoIncrement = false;
|
5 |
+
|
6 |
+
protected function _construct()
|
7 |
+
{
|
8 |
+
$this->_init('ampersand_core/value', 'name');
|
9 |
+
}
|
10 |
+
}
|
app/code/core/Ampersand/Core/Model/Resource/Setup.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Core_Model_Resource_Setup extends Mage_Core_Model_Resource_Setup
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Retrieve the name of the upgrade file being run and log for debugging purposes.
|
6 |
+
*
|
7 |
+
* @return Mage_Core_Model_Resource_Setup
|
8 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
9 |
+
*/
|
10 |
+
public function startSetup()
|
11 |
+
{
|
12 |
+
parent::startSetup();
|
13 |
+
|
14 |
+
$trace = Ampersand::trace(false);
|
15 |
+
$lines = explode(PHP_EOL, $trace);
|
16 |
+
$setupLine = $lines[1];
|
17 |
+
preg_match('/(?P<filename>\/app\/code\/(.*)):/', $setupLine, $matches);
|
18 |
+
|
19 |
+
if (array_key_exists('filename', $matches)) {
|
20 |
+
$this->_logSetupStart($matches['filename']);
|
21 |
+
} else {
|
22 |
+
$this->_logSetupStart($setupLine);
|
23 |
+
}
|
24 |
+
|
25 |
+
return $this;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Log the install script location in system.log so we see any associated errors in place.
|
30 |
+
*
|
31 |
+
* @param string $message
|
32 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
33 |
+
*/
|
34 |
+
protected function _logSetupStart($message)
|
35 |
+
{
|
36 |
+
Mage::log('SETUP SCRIPT: ' . $message, null, null, true);
|
37 |
+
}
|
38 |
+
}
|
app/code/core/Ampersand/Core/Model/SessionObject.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Semi-implemented for use in Monocore Meal Plan. Untested.
|
4 |
+
*
|
5 |
+
* The idea being that you could extend this abstract and have an object that
|
6 |
+
* saved its values in the session rather than in a database, perhaps for some temporary
|
7 |
+
* storage for example a multi-part process that you only want to persist once complete.
|
8 |
+
*/
|
9 |
+
abstract class Ampersand_Core_Model_SessionObject extends Mage_Core_Model_Abstract
|
10 |
+
{
|
11 |
+
protected $_sessionModel = 'core/session';
|
12 |
+
|
13 |
+
protected $_sessionDataKey = null;
|
14 |
+
|
15 |
+
public function getData($key = '', $index = null)
|
16 |
+
{
|
17 |
+
$data = $this->_getSession()->getData($this->_getSessionDataKey());
|
18 |
+
|
19 |
+
if ($key == '') {
|
20 |
+
return $data;
|
21 |
+
}
|
22 |
+
|
23 |
+
return array_key_exists($key, $data) ? $data[$key] : null;
|
24 |
+
}
|
25 |
+
|
26 |
+
public function setData($key, $value=null)
|
27 |
+
{
|
28 |
+
$data = $this->getData();
|
29 |
+
|
30 |
+
if (!is_array($data)) {
|
31 |
+
$data = array();
|
32 |
+
}
|
33 |
+
|
34 |
+
if (is_array($key)) {
|
35 |
+
$data = $key;
|
36 |
+
} else {
|
37 |
+
$data[$key] = $value;
|
38 |
+
}
|
39 |
+
|
40 |
+
$this->_getSession()->setData($this->_getSessionDataKey(), $data);
|
41 |
+
|
42 |
+
return $this;
|
43 |
+
}
|
44 |
+
|
45 |
+
protected function _getSessionModel()
|
46 |
+
{
|
47 |
+
$sessionModel = $this->_sessionModel;
|
48 |
+
|
49 |
+
if (is_null($sessionModel)) {
|
50 |
+
Mage::throwException('Session model must be defined.');
|
51 |
+
}
|
52 |
+
|
53 |
+
return $sessionModel;
|
54 |
+
}
|
55 |
+
|
56 |
+
protected function _getSessionDataKey()
|
57 |
+
{
|
58 |
+
$sessionDataKey = $this->_sessionDataKey;
|
59 |
+
|
60 |
+
if (is_null($sessionDataKey)) {
|
61 |
+
Mage::throwException('Session data key must be defined.');
|
62 |
+
}
|
63 |
+
|
64 |
+
return $sessionDataKey;
|
65 |
+
}
|
66 |
+
|
67 |
+
protected function _getSession()
|
68 |
+
{
|
69 |
+
return Mage::getSingleton($this->_getSessionModel());
|
70 |
+
}
|
71 |
+
}
|
app/code/core/Ampersand/Core/Model/Value.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Core_Model_Value extends Mage_Core_Model_Abstract
|
3 |
+
{
|
4 |
+
protected function _construct()
|
5 |
+
{
|
6 |
+
$this->_init('ampersand_core/value');
|
7 |
+
}
|
8 |
+
}
|
app/code/core/Ampersand/Core/Model/Versioning.php
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Core_Model_Versioning
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Editions of Magento.
|
6 |
+
*/
|
7 |
+
const EDITION_CE = 'ce';
|
8 |
+
const EDITION_EE = 'ee';
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Compare Magento edition and version to the current version.
|
12 |
+
*
|
13 |
+
* @param string $requiredEdition
|
14 |
+
* @param string $requiredVersion
|
15 |
+
* @return bool
|
16 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
17 |
+
*/
|
18 |
+
public function compare($requiredEdition, $requiredVersion)
|
19 |
+
{
|
20 |
+
$actualEdition = $this->getEdition();
|
21 |
+
if ($requiredEdition != $actualEdition) {
|
22 |
+
return false;
|
23 |
+
}
|
24 |
+
|
25 |
+
$actualVersion = $this->getVersion();
|
26 |
+
$result = version_compare($requiredVersion, $actualVersion);
|
27 |
+
|
28 |
+
// required version is lower than the actual version
|
29 |
+
if ($result === -1) {
|
30 |
+
return true;
|
31 |
+
}
|
32 |
+
|
33 |
+
// the two versions are the same
|
34 |
+
if ($result === 0) {
|
35 |
+
return true;
|
36 |
+
}
|
37 |
+
|
38 |
+
// required version is higher than the actual version
|
39 |
+
if ($result === 1) {
|
40 |
+
return false;
|
41 |
+
}
|
42 |
+
|
43 |
+
// should never get here, but safer to assume the worst
|
44 |
+
return false;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Retreive the current Magento edition.
|
49 |
+
*
|
50 |
+
* @return string
|
51 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
52 |
+
*/
|
53 |
+
public function getEdition()
|
54 |
+
{
|
55 |
+
$edition = self::EDITION_CE;
|
56 |
+
|
57 |
+
if ($this->isModuleEnabled('Enterprise_Enterprise')) {
|
58 |
+
$edition = self::EDITION_EE;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @todo handle PE or other editions
|
63 |
+
*/
|
64 |
+
|
65 |
+
return $edition;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Retrieve the current Magento version.
|
70 |
+
*
|
71 |
+
* @return string
|
72 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
73 |
+
*/
|
74 |
+
public function getVersion()
|
75 |
+
{
|
76 |
+
$versionData = Mage::getVersionInfo();
|
77 |
+
|
78 |
+
$version = '';
|
79 |
+
$version .= $versionData['major'] . '.';
|
80 |
+
$version .= $versionData['minor'] . '.';
|
81 |
+
$version .= $versionData['revision'] . '.';
|
82 |
+
$version .= $versionData['patch'] . '.';
|
83 |
+
|
84 |
+
$version = rtrim($version, '.');
|
85 |
+
|
86 |
+
return $version;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* This is a copy of Mage_Core_Helper_Abstract::isModuleEnabled().
|
91 |
+
*
|
92 |
+
* @param string $moduleName
|
93 |
+
* @return bool
|
94 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
95 |
+
*/
|
96 |
+
public function isModuleEnabled($moduleName)
|
97 |
+
{
|
98 |
+
if (!Mage::getConfig()->getNode('modules/' . $moduleName)) {
|
99 |
+
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
$isActive = Mage::getConfig()->getNode('modules/' . $moduleName . '/active');
|
103 |
+
if (!$isActive || !in_array((string)$isActive, array('true', '1'))) {
|
104 |
+
return false;
|
105 |
+
}
|
106 |
+
|
107 |
+
return true;
|
108 |
+
}
|
109 |
+
}
|
app/code/core/Ampersand/Core/changelog.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
17/10/2011 - v0.2.0 - Moved Ampersand_Integration to its own module.
|
2 |
|
3 |
28/09/2011 - v0.1.0 - Initial release.
|
1 |
+
11/01/2013 - v0.2.6 - Added Ampersand System module.
|
2 |
+
|
3 |
+
10/01/2013 - v0.2.5 - Added Ampersand Api module.
|
4 |
+
|
5 |
+
07/01/2013 - v0.2.4 - Various additional functionality. No major changes.
|
6 |
+
|
7 |
17/10/2011 - v0.2.0 - Moved Ampersand_Integration to its own module.
|
8 |
|
9 |
28/09/2011 - v0.1.0 - Initial release.
|
app/code/core/Ampersand/Core/etc/config.xml
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<config>
|
3 |
<modules>
|
4 |
<Ampersand_Core>
|
5 |
-
<version>0.2.
|
6 |
</Ampersand_Core>
|
7 |
</modules>
|
8 |
<global>
|
@@ -11,5 +11,26 @@
|
|
11 |
<class>Ampersand_Core_Helper</class>
|
12 |
</ampersand_core>
|
13 |
</helpers>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
</global>
|
15 |
</config>
|
2 |
<config>
|
3 |
<modules>
|
4 |
<Ampersand_Core>
|
5 |
+
<version>0.2.6</version>
|
6 |
</Ampersand_Core>
|
7 |
</modules>
|
8 |
<global>
|
11 |
<class>Ampersand_Core_Helper</class>
|
12 |
</ampersand_core>
|
13 |
</helpers>
|
14 |
+
<models>
|
15 |
+
<ampersand_core>
|
16 |
+
<class>Ampersand_Core_Model</class>
|
17 |
+
<resourceModel>ampersand_core_mysql4</resourceModel>
|
18 |
+
</ampersand_core>
|
19 |
+
<ampersand_core_mysql4>
|
20 |
+
<class>Ampersand_Core_Model_Mysql4</class>
|
21 |
+
<entities>
|
22 |
+
<value>
|
23 |
+
<table>ampersand_core_value</table>
|
24 |
+
</value>
|
25 |
+
</entities>
|
26 |
+
</ampersand_core_mysql4>
|
27 |
+
</models>
|
28 |
+
<resources>
|
29 |
+
<ampersand_core_setup>
|
30 |
+
<setup>
|
31 |
+
<module>Ampersand_Core</module>
|
32 |
+
</setup>
|
33 |
+
</ampersand_core_setup>
|
34 |
+
</resources>
|
35 |
</global>
|
36 |
</config>
|
app/code/core/Ampersand/Core/sql/ampersand_core_setup/mysql4-install-0.2.3.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$this->startSetup();
|
4 |
+
|
5 |
+
$this->run("
|
6 |
+
|
7 |
+
CREATE TABLE `{$this->getTable('ampersand_core/value')}` (
|
8 |
+
`name` VARCHAR(128) NOT NULL,
|
9 |
+
`value` TEXT NOT NULL,
|
10 |
+
PRIMARY KEY (`name`)
|
11 |
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
12 |
+
|
13 |
+
");
|
14 |
+
|
15 |
+
$this->endSetup();
|
app/code/core/Ampersand/Fakepay/Helper/Data.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Fakepay_Helper_Data extends Ampersand_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
|
5 |
+
}
|
app/code/core/Ampersand/Fakepay/Model/Method.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Fakepay_Model_Method extends Mage_Payment_Model_Method_Cc
|
3 |
+
{
|
4 |
+
protected $_code = 'ampersand_fakepay';
|
5 |
+
|
6 |
+
protected $_isGateway = true;
|
7 |
+
protected $_canOrder = true;
|
8 |
+
protected $_canAuthorize = true;
|
9 |
+
protected $_canCapture = true;
|
10 |
+
protected $_canCapturePartial = true;
|
11 |
+
protected $_canRefund = true;
|
12 |
+
protected $_canRefundInvoicePartial = true;
|
13 |
+
protected $_canVoid = true;
|
14 |
+
}
|
app/code/core/Ampersand/Fakepay/etc/config.xml
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<ampersand_fakepay>
|
5 |
+
<version>0.0.1</version>
|
6 |
+
</ampersand_fakepay>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<models>
|
10 |
+
<ampersand_fakepay>
|
11 |
+
<class>Ampersand_Fakepay_Model</class>
|
12 |
+
</ampersand_fakepay>
|
13 |
+
</models>
|
14 |
+
<helpers>
|
15 |
+
<ampersand_fakepay>
|
16 |
+
<class>Ampersand_Fakepay_Helper</class>
|
17 |
+
</ampersand_fakepay>
|
18 |
+
</helpers>
|
19 |
+
</global>
|
20 |
+
<default>
|
21 |
+
<payment>
|
22 |
+
<ampersand_fakepay>
|
23 |
+
<active>0</active>
|
24 |
+
<title>Ampersand Dummy Payments</title>
|
25 |
+
<cctypes>VI,MC</cctypes>
|
26 |
+
<model>ampersand_fakepay/method</model>
|
27 |
+
<order_status>processing</order_status>
|
28 |
+
<payment_action>authorize_capture</payment_action>
|
29 |
+
</ampersand_fakepay>
|
30 |
+
</payment>
|
31 |
+
</default>
|
32 |
+
</config>
|
app/code/core/Ampersand/Fakepay/etc/system.xml
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<sections>
|
4 |
+
<payment>
|
5 |
+
<groups>
|
6 |
+
<ampersand_fakepay translate="label" module="ampersand_fakepay">
|
7 |
+
<label>Ampersand Dummy Payments</label>
|
8 |
+
<sort_order>10001</sort_order>
|
9 |
+
<show_in_default>1</show_in_default>
|
10 |
+
<show_in_website>1</show_in_website>
|
11 |
+
<show_in_store>0</show_in_store>
|
12 |
+
<fields>
|
13 |
+
<active translate="label">
|
14 |
+
<label>Enabled</label>
|
15 |
+
<frontend_type>select</frontend_type>
|
16 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
17 |
+
<sort_order>10</sort_order>
|
18 |
+
<show_in_default>1</show_in_default>
|
19 |
+
<show_in_website>1</show_in_website>
|
20 |
+
<show_in_store>0</show_in_store>
|
21 |
+
</active>
|
22 |
+
<title translate="label">
|
23 |
+
<label>Title</label>
|
24 |
+
<frontend_type>text</frontend_type>
|
25 |
+
<sort_order>20</sort_order>
|
26 |
+
<show_in_default>1</show_in_default>
|
27 |
+
<show_in_website>1</show_in_website>
|
28 |
+
<show_in_store>0</show_in_store>
|
29 |
+
</title>
|
30 |
+
<order_status translate="label">
|
31 |
+
<label>New order status</label>
|
32 |
+
<frontend_type>select</frontend_type>
|
33 |
+
<source_model>adminhtml/system_config_source_order_status_processing</source_model>
|
34 |
+
<sort_order>30</sort_order>
|
35 |
+
<show_in_default>1</show_in_default>
|
36 |
+
<show_in_website>1</show_in_website>
|
37 |
+
<show_in_store>0</show_in_store>
|
38 |
+
</order_status>
|
39 |
+
<payment_action translate="label">
|
40 |
+
<label>Payment Action</label>
|
41 |
+
<frontend_type>select</frontend_type>
|
42 |
+
<source_model>paygate/authorizenet_source_paymentAction</source_model>
|
43 |
+
<sort_order>40</sort_order>
|
44 |
+
<show_in_default>1</show_in_default>
|
45 |
+
<show_in_website>1</show_in_website>
|
46 |
+
<show_in_store>0</show_in_store>
|
47 |
+
</payment_action>
|
48 |
+
</fields>
|
49 |
+
</ampersand_fakepay>
|
50 |
+
</groups>
|
51 |
+
</payment>
|
52 |
+
</sections>
|
53 |
+
</config>
|
app/code/core/Ampersand/PageCache/Model/Container/NoCache.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_PageCache_Model_Container_NoCache
|
3 |
+
extends Enterprise_PageCache_Model_Container_Abstract
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Retrieve container individual cache id
|
7 |
+
*
|
8 |
+
* @return string
|
9 |
+
* @author Joseph McDeromtt <joseph.mcdermott@ampersandcommerce.com>
|
10 |
+
*/
|
11 |
+
protected function _getCacheId()
|
12 |
+
{
|
13 |
+
return $this->_placeholder->getAttribute('placeholder') .
|
14 |
+
md5(
|
15 |
+
$this->_placeholder->getAttribute('cache_id')
|
16 |
+
. $this->_getCookieValue('frontend', '')
|
17 |
+
);
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Render block content from placeholder.
|
22 |
+
*
|
23 |
+
* @return string
|
24 |
+
* @author Joseph McDeromtt <joseph.mcdermott@ampersandcommerce.com>
|
25 |
+
*/
|
26 |
+
protected function _renderBlock()
|
27 |
+
{
|
28 |
+
$blockClass = $this->_placeholder->getAttribute('block');
|
29 |
+
$template = $this->_placeholder->getAttribute('template');
|
30 |
+
|
31 |
+
$block = new $blockClass;
|
32 |
+
$block->setTemplate($template);
|
33 |
+
|
34 |
+
return $block->toHtml();
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Do not save data to cache storage.
|
39 |
+
*
|
40 |
+
* @param string $data
|
41 |
+
* @param string $id
|
42 |
+
* @param array $tags
|
43 |
+
* @author Joseph McDeromtt <joseph.mcdermott@ampersandcommerce.com>
|
44 |
+
*/
|
45 |
+
protected function _saveCache($data, $id, $tags = array(), $lifetime = null)
|
46 |
+
{
|
47 |
+
$lifetime = 0;
|
48 |
+
parent::_saveCache($data, $id, $tags, $lifetime);
|
49 |
+
}
|
50 |
+
}
|
app/code/core/Ampersand/Sales/Helper/Quote.php
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Sales_Helper_Quote extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Prepare the request object for adding a product to the quote.
|
6 |
+
*
|
7 |
+
* @param mixed $product
|
8 |
+
* @param mixed $productData
|
9 |
+
* @param mixed $childProduct
|
10 |
+
* @param array $configurableAttributes
|
11 |
+
* @return Ampersand_Object
|
12 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
13 |
+
*/
|
14 |
+
public function prepareProductRequest($product, $productData, $childProduct = null,
|
15 |
+
$configurableAttributes = array())
|
16 |
+
{
|
17 |
+
// initialize request object
|
18 |
+
$request = new Ampersand_Object();
|
19 |
+
|
20 |
+
// initialize product
|
21 |
+
$product = $this->_initProduct($product);
|
22 |
+
|
23 |
+
// set the product data
|
24 |
+
if (!is_array($productData)) {
|
25 |
+
$productData = array(
|
26 |
+
'qty' => $productData
|
27 |
+
);
|
28 |
+
}
|
29 |
+
$request->addData($productData);
|
30 |
+
|
31 |
+
// prepare any configurable attributes by provided child product
|
32 |
+
if (!is_null($childProduct)) {
|
33 |
+
$childProduct = $this->_initProduct($childProduct);
|
34 |
+
$superAttributeData = $this->getSuperAttributeDataFromProducts($product, $childProduct);
|
35 |
+
$request->setSuperAttribute($superAttributeData);
|
36 |
+
}
|
37 |
+
|
38 |
+
// prepare any configurable attributes by provided attribute values
|
39 |
+
if (is_null($childProduct) && count($configurableAttributes) > 0) {
|
40 |
+
$superAttributeData = $this->getSuperAttributeDataFromValues($configurableAttributes);
|
41 |
+
$request->setSuperAttribute($superAttributeData);
|
42 |
+
}
|
43 |
+
|
44 |
+
return $request;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Retrieve super attribute data for adding a configurable product to the basket,
|
49 |
+
* having been provided with the configurable $product and simple $childProduct.
|
50 |
+
*
|
51 |
+
* @param mixed $product
|
52 |
+
* @param mixed $childProduct
|
53 |
+
* @return array
|
54 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
55 |
+
*/
|
56 |
+
public function getSuperAttributeDataFromProducts($product, $childProduct)
|
57 |
+
{
|
58 |
+
$product = $this->_initProduct($product);
|
59 |
+
$childProduct = $this->_initProduct($childProduct);
|
60 |
+
|
61 |
+
if (!$product->isConfigurable()) {
|
62 |
+
return array();
|
63 |
+
}
|
64 |
+
|
65 |
+
$superAttributeData = array();
|
66 |
+
|
67 |
+
foreach ($product->getTypeInstance()->getConfigurableAttributes() as $_attribute) {
|
68 |
+
$_productAttribute = $_attribute->getProductAttribute();
|
69 |
+
$_attributeId = $_productAttribute->getId();
|
70 |
+
$_attributeValue = $childProduct->getData($_productAttribute->getAttributeCode());
|
71 |
+
$superAttributeData[$_attributeId] = $_attributeValue;
|
72 |
+
}
|
73 |
+
|
74 |
+
return $superAttributeData;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Retrieve super attribute data for adding a configurable product to the basket,
|
79 |
+
* having been provided with an array of the attribute codes and values (not ids).
|
80 |
+
*
|
81 |
+
* @param array $configurableAttributes
|
82 |
+
* @return array
|
83 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
84 |
+
*/
|
85 |
+
public function getSuperAttributeDataFromValues($configurableAttributes)
|
86 |
+
{
|
87 |
+
$superAttributeData = array();
|
88 |
+
|
89 |
+
$attributeHelper = Mage::helper('ampersand_catalog/product_attribute');
|
90 |
+
|
91 |
+
foreach ($configurableAttributes as $_code => $_value) {
|
92 |
+
$_productAttribute = $attributeHelper->getAttribute($_code);
|
93 |
+
$_attributeId = $_productAttribute->getId();
|
94 |
+
$_attributeValue = $attributeHelper->getAttributeOptionId($_productAttribute, $_value);
|
95 |
+
$superAttributeData[$_attributeId] = $_attributeValue;
|
96 |
+
}
|
97 |
+
|
98 |
+
return $superAttributeData;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Retrive product object from provided product id or object.
|
103 |
+
*
|
104 |
+
* @param mixed $product
|
105 |
+
* @return Mage_Catalog_Model_Product
|
106 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
107 |
+
*/
|
108 |
+
protected function _initProduct($product)
|
109 |
+
{
|
110 |
+
if (!$product instanceof Mage_Catalog_Model_Product) {
|
111 |
+
$product = Mage::getModel('catalog/product')->load($product);
|
112 |
+
}
|
113 |
+
|
114 |
+
return $product;
|
115 |
+
}
|
116 |
+
}
|
app/code/core/Ampersand/Sales/Model/AbstractHelper.php
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
abstract class Ampersand_Sales_Model_AbstractHelper extends Varien_Object
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Product id to sku mapping for this object.
|
6 |
+
*
|
7 |
+
* @var array $_productIdSkuMap
|
8 |
+
*/
|
9 |
+
protected $_productIdSkuMap;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Generate product id to sku mapping for this object.
|
13 |
+
*
|
14 |
+
* @param array $items
|
15 |
+
* @return array
|
16 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
17 |
+
*/
|
18 |
+
public function getProductIdSkuMap($items)
|
19 |
+
{
|
20 |
+
if (is_null($this->_productIdSkuMap)) {
|
21 |
+
// first get all the product ids we need
|
22 |
+
$productIds = array();
|
23 |
+
foreach ($items as $_item) {
|
24 |
+
$productIds[] = $_item->getProductId();
|
25 |
+
if ($_item->getHasChildren()) {
|
26 |
+
foreach ($_item->getChildrenItems() as $__child) {
|
27 |
+
$productIds[] = $__child->getProductId();
|
28 |
+
}
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
// fetch the skus from the database
|
33 |
+
$productResourceSingleton = Mage::getResourceSingleton('catalog/product');
|
34 |
+
if (method_exists($productResourceSingleton, 'getProductsSku')) {
|
35 |
+
$productsSkuResult = $productResourceSingleton->getProductsSku($productIds);
|
36 |
+
} else {
|
37 |
+
$productsSkuResult = array();
|
38 |
+
$productCollection = Mage::getModel('catalog/product')->getCollection()
|
39 |
+
->addAttributeToFilter('entity_id', $productIds);
|
40 |
+
foreach ($productCollection as $_product) {
|
41 |
+
$productsSkuResult[] = array(
|
42 |
+
'entity_id' => $_product->getId(),
|
43 |
+
'sku' => $_product->getSku(),
|
44 |
+
);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
// convert the result to a productId => sku array
|
49 |
+
$productIdSkuData = array();
|
50 |
+
foreach ($productsSkuResult as $_skuData) {
|
51 |
+
$productIdSkuData[$_skuData['entity_id']] = $_skuData['sku'];
|
52 |
+
}
|
53 |
+
|
54 |
+
$this->_productIdSkuMap = $productIdSkuData;
|
55 |
+
}
|
56 |
+
|
57 |
+
return $this->_productIdSkuMap;
|
58 |
+
}
|
59 |
+
}
|
app/code/core/Ampersand/Sales/Model/InvoiceHelper.php
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Sales_Model_InvoiceHelper extends Ampersand_Sales_Model_AbstractHelper
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* The invoice associated with this object.
|
6 |
+
*
|
7 |
+
* @var Mage_Sales_Model_Order_Invoice $_invoice
|
8 |
+
*/
|
9 |
+
protected $_invoice;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Order item id to invoice item mapping for this invoice.
|
13 |
+
*
|
14 |
+
* @var array $_orderItemIdInvoiceItemMap
|
15 |
+
*/
|
16 |
+
protected $_orderItemIdInvoiceItemMap;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Initialize object with invoice if provided.
|
20 |
+
*
|
21 |
+
* @param Mage_Sales_Model_Order_Invoice $invoice
|
22 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
23 |
+
*/
|
24 |
+
public function __construct(Mage_Sales_Model_Order_Invoice $invoice = null)
|
25 |
+
{
|
26 |
+
parent::__construct();
|
27 |
+
|
28 |
+
$this->setInvoice($invoice);
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Associate invoice with this object and reset associated data.
|
33 |
+
*
|
34 |
+
* @param Mage_Sales_Model_Order_Invoice $invoice
|
35 |
+
* @return Ampersand_Sales_Model_InvoiceHelper
|
36 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
37 |
+
*/
|
38 |
+
public function setInvoice(Mage_Sales_Model_Order_Invoice $invoice)
|
39 |
+
{
|
40 |
+
$this->_invoice = $invoice;
|
41 |
+
$this->_productIdSkuMap = null;
|
42 |
+
$this->_orderItemIdInvoiceItemMap = null;
|
43 |
+
|
44 |
+
return $this;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Retrieve the invoice associated with this object.
|
49 |
+
*
|
50 |
+
* @return Mage_Sales_Model_Order_Invoice
|
51 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
52 |
+
*/
|
53 |
+
public function getInvoice()
|
54 |
+
{
|
55 |
+
return $this->_invoice;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Retrieve an invoice item by sku and optionally child sku
|
60 |
+
*
|
61 |
+
* @param string $sku
|
62 |
+
* @param string $childSku
|
63 |
+
* @param bool $returnChild
|
64 |
+
* @return Mage_Sales_Model_Order_Invoice_Item
|
65 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
66 |
+
*/
|
67 |
+
public function getItemBySku($sku, $childSku = null, $returnChild = false)
|
68 |
+
{
|
69 |
+
$invoiceItem = null;
|
70 |
+
$invoice = $this->getInvoice();
|
71 |
+
|
72 |
+
// initialize product id to sku mapping
|
73 |
+
$productIdSkuMap = $this->getProductIdSkuMap($invoice->getAllItems());
|
74 |
+
|
75 |
+
// attempt to match the invoice item
|
76 |
+
foreach ($invoice->getAllItems() as $_item) {
|
77 |
+
if (is_null($childSku)) {
|
78 |
+
if ($sku != $productIdSkuMap[$_item->getProductId()]) {
|
79 |
+
continue;
|
80 |
+
}
|
81 |
+
if ($_item->getHasChildren() || $_item->getParentItemId()) {
|
82 |
+
continue;
|
83 |
+
}
|
84 |
+
$invoiceItem = $_item;
|
85 |
+
break;
|
86 |
+
} else {
|
87 |
+
if ($childSku != $productIdSkuMap[$_item->getProductId()]) {
|
88 |
+
continue;
|
89 |
+
}
|
90 |
+
$_orderItem = Mage::getModel('sales/order_item')->load($_item->getOrderItemId());
|
91 |
+
if (!$_orderItem->getParentItemId()) {
|
92 |
+
continue;
|
93 |
+
}
|
94 |
+
$_parentOrderItem = Mage::getModel('sales/order_item')->load($_orderItem->getParentItemId());
|
95 |
+
if ($sku != $productIdSkuMap[$_parentOrderItem->getProductId()]) {
|
96 |
+
continue;
|
97 |
+
}
|
98 |
+
$invoiceItem = $returnChild
|
99 |
+
? $_item
|
100 |
+
: $this->getInvoiceItemByOrderItemId($_orderItem->getParentItemId());
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
return $invoiceItem;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Retrieve an invoice item by order item id.
|
109 |
+
*
|
110 |
+
* @param int $orderItemId
|
111 |
+
* @return Mage_Sales_Model_Order_Invoice_Item
|
112 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
113 |
+
*/
|
114 |
+
public function getInvoiceItemByOrderItemId($orderItemId)
|
115 |
+
{
|
116 |
+
if (is_null($this->_orderItemIdInvoiceItemMap)) {
|
117 |
+
foreach ($this->getInvoice()->getAllItems() as $_item) {
|
118 |
+
$this->_orderItemIdInvoiceItemMap[$_item->getOrderItemId()] = $_item;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
return $this->_orderItemIdInvoiceItemMap[$orderItemId];
|
123 |
+
}
|
124 |
+
}
|
app/code/core/Ampersand/Sales/Model/OrderHelper.php
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Sales_Model_OrderHelper extends Ampersand_Sales_Model_AbstractHelper
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* The order associated with this object.
|
6 |
+
*
|
7 |
+
* @var Mage_Sales_Model_Order $_order
|
8 |
+
*/
|
9 |
+
protected $_order;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Order item id to order item mapping for this order.
|
13 |
+
*
|
14 |
+
* @var array $_orderItemIdOrderItemMap
|
15 |
+
*/
|
16 |
+
protected $_orderItemIdOrderItemMap;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Initialize object with order if provided.
|
20 |
+
*
|
21 |
+
* @param Mage_Sales_Model_Order $order
|
22 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
23 |
+
*/
|
24 |
+
public function __construct(Mage_Sales_Model_Order $order = null)
|
25 |
+
{
|
26 |
+
parent::__construct();
|
27 |
+
|
28 |
+
$this->setOrder($order);
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Associate order with this object and reset associated data.
|
33 |
+
*
|
34 |
+
* @param Mage_Sales_Model_Order $order
|
35 |
+
* @return Ampersand_Sales_Model_OrderHelper
|
36 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
37 |
+
*/
|
38 |
+
public function setOrder(Mage_Sales_Model_Order $order)
|
39 |
+
{
|
40 |
+
$this->_order = $order;
|
41 |
+
$this->_productIdSkuMap = null;
|
42 |
+
|
43 |
+
return $this;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Retrieve the order associated with this object.
|
48 |
+
*
|
49 |
+
* @return Mage_Sales_Model_Order
|
50 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
51 |
+
*/
|
52 |
+
public function getOrder()
|
53 |
+
{
|
54 |
+
return $this->_order;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Retrieve an order item by sku and optionally child sku
|
59 |
+
*
|
60 |
+
* @param string $sku
|
61 |
+
* @param string $childSku
|
62 |
+
* @param bool $returnChild
|
63 |
+
* @return Mage_Sales_Model_Order_Item
|
64 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
65 |
+
*/
|
66 |
+
public function getItemBySku($sku, $childSku = null, $returnChild = false)
|
67 |
+
{
|
68 |
+
$orderItem = null;
|
69 |
+
$order = $this->getOrder();
|
70 |
+
|
71 |
+
// initialize product id to sku mapping
|
72 |
+
$productIdSkuMap = $this->getProductIdSkuMap($order->getAllItems());
|
73 |
+
|
74 |
+
// attempt to match the order item
|
75 |
+
foreach ($order->getAllItems() as $_item) {
|
76 |
+
if (is_null($childSku)) {
|
77 |
+
if ($sku != $productIdSkuMap[$_item->getProductId()]) {
|
78 |
+
continue;
|
79 |
+
}
|
80 |
+
if ($_item->getHasChildren() || $_item->getParentItemId()) {
|
81 |
+
continue;
|
82 |
+
}
|
83 |
+
$orderItem = $_item;
|
84 |
+
break;
|
85 |
+
} else {
|
86 |
+
if ($childSku != $productIdSkuMap[$_item->getProductId()]) {
|
87 |
+
continue;
|
88 |
+
}
|
89 |
+
if (!$_item->getParentItemId()) {
|
90 |
+
continue;
|
91 |
+
}
|
92 |
+
$_parentItem = Mage::getModel('sales/order_item')->load($_item->getParentItemId());
|
93 |
+
if ($sku != $productIdSkuMap[$_parentItem->getProductId()]) {
|
94 |
+
continue;
|
95 |
+
}
|
96 |
+
$orderItem = $returnChild ? $_item : $_parentItem;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
return $orderItem;
|
101 |
+
}
|
102 |
+
}
|
app/code/core/Ampersand/Sales/Model/Quote/Address/Total/Discount/PercentageAbstract.php
ADDED
@@ -0,0 +1,255 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
Usage:
|
4 |
+
======
|
5 |
+
|
6 |
+
Add a new total to config.xml:
|
7 |
+
<config>
|
8 |
+
<global>
|
9 |
+
<sales>
|
10 |
+
<quote>
|
11 |
+
<totals>
|
12 |
+
<unique_code_for_your_total>
|
13 |
+
<!-- model defined below should extend this class -->
|
14 |
+
<class>namespace/model</class>
|
15 |
+
<after>discount</after>
|
16 |
+
<before>grand_total</before>
|
17 |
+
</unique_code_for_your_total>
|
18 |
+
</totals>
|
19 |
+
</quote>
|
20 |
+
</sales>
|
21 |
+
</global>
|
22 |
+
<default>
|
23 |
+
<sales>
|
24 |
+
<totals_sort>
|
25 |
+
<unique_code_for_your_total>21</unique_code_for_your_total>
|
26 |
+
</totals_sort>
|
27 |
+
</sales>
|
28 |
+
</default>
|
29 |
+
</config>
|
30 |
+
|
31 |
+
Add a new total sort to system.xml:
|
32 |
+
<config>
|
33 |
+
<sections>
|
34 |
+
<sales>
|
35 |
+
<groups>
|
36 |
+
<totals_sort>
|
37 |
+
<fields>
|
38 |
+
<unique_code_for_your_total translate="label">
|
39 |
+
<label>Label for your Discount</label>
|
40 |
+
<frontend_type>text</frontend_type>
|
41 |
+
<sort_order>201</sort_order>
|
42 |
+
<show_in_default>1</show_in_default>
|
43 |
+
<show_in_website>1</show_in_website>
|
44 |
+
<show_in_store>0</show_in_store>
|
45 |
+
</unique_code_for_your_total>
|
46 |
+
</fields>
|
47 |
+
</totals_sort>
|
48 |
+
</groups>
|
49 |
+
</sales>
|
50 |
+
</sections>
|
51 |
+
</config>
|
52 |
+
|
53 |
+
======
|
54 |
+
*
|
55 |
+
*/
|
56 |
+
abstract class Ampersand_Sales_Model_Quote_Address_Total_Discount_PercentageAbstract
|
57 |
+
extends Mage_Sales_Model_Quote_Address_Total_Abstract
|
58 |
+
{
|
59 |
+
/**
|
60 |
+
* Collect address discount amount.
|
61 |
+
*
|
62 |
+
* @param Mage_Sales_Model_Quote_Address $address
|
63 |
+
* @return Ampersand_Sales_Model_Quote_Address_Total_Discount_PercentageAbstract
|
64 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
65 |
+
*/
|
66 |
+
public function collect(Mage_Sales_Model_Quote_Address $address)
|
67 |
+
{
|
68 |
+
parent::collect($address);
|
69 |
+
|
70 |
+
$items = $this->_getAddressItems($address);
|
71 |
+
if (!count($items)) {
|
72 |
+
return $this;
|
73 |
+
}
|
74 |
+
|
75 |
+
foreach ($items as $_item) {
|
76 |
+
if ($_item->getParentItemId()) {
|
77 |
+
continue;
|
78 |
+
}
|
79 |
+
|
80 |
+
if ($_item->getHasChildren() && $_item->isChildrenCalculated()) {
|
81 |
+
foreach ($_item->getChildren() as $_child) {
|
82 |
+
$this->_processItem($_child);
|
83 |
+
$this->_aggregateItemDiscount($_child);
|
84 |
+
}
|
85 |
+
} else {
|
86 |
+
$this->_processItem($_item);
|
87 |
+
$this->_aggregateItemDiscount($_item);
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Add discount total information to address.
|
96 |
+
*
|
97 |
+
* @param Mage_Sales_Model_Quote_Address $address
|
98 |
+
* @return Ampersand_Sales_Model_Quote_Address_Total_Discount_PercentageAbstract
|
99 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
100 |
+
*/
|
101 |
+
public function fetch(Mage_Sales_Model_Quote_Address $address)
|
102 |
+
{
|
103 |
+
$amount = $address->getData($this->getCode());
|
104 |
+
|
105 |
+
if (!empty($amount)) {
|
106 |
+
$address->addTotal(array(
|
107 |
+
'code' => $this->getCode(),
|
108 |
+
'title' => $this->_getTitle(),
|
109 |
+
'value' => $amount
|
110 |
+
));
|
111 |
+
}
|
112 |
+
|
113 |
+
return $this;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Retrieve the title of the discount.
|
118 |
+
*
|
119 |
+
* @return string
|
120 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
121 |
+
*/
|
122 |
+
abstract protected function _getTitle();
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Retrieve the value of the discount.
|
126 |
+
*
|
127 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $item
|
128 |
+
* @return float
|
129 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
130 |
+
*/
|
131 |
+
abstract protected function _getDiscountValue(Mage_Sales_Model_Quote_Item_Abstract $item);
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Quote item discount calculation process.
|
135 |
+
*
|
136 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $item
|
137 |
+
* @return Ampersand_Sales_Model_Quote_Address_Total_Discount_PercentageAbstract
|
138 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
139 |
+
*/
|
140 |
+
protected function _processItem(Mage_Sales_Model_Quote_Item_Abstract $item)
|
141 |
+
{
|
142 |
+
$customDiscountValue = $this->_getDiscountValue($item);
|
143 |
+
$discountPercent = min(100, $customDiscountValue);
|
144 |
+
$discountPercentMultiplier = $discountPercent / 100;
|
145 |
+
if ($discountPercent <= 0) {
|
146 |
+
return $this;
|
147 |
+
}
|
148 |
+
|
149 |
+
// retrieve the quantity of this item to discount
|
150 |
+
$qty = $this->_getItemQty($item);
|
151 |
+
if ($qty <= 0) {
|
152 |
+
return $this;
|
153 |
+
}
|
154 |
+
|
155 |
+
// retrieve the original price of the item, before any discounts were applied
|
156 |
+
$originalPrice = $this->_getItemOriginalPrice($item);
|
157 |
+
$baseOriginalPrice = $this->_getItemBaseOriginalPrice($item);
|
158 |
+
if ($originalPrice <= 0) {
|
159 |
+
return $this;
|
160 |
+
}
|
161 |
+
|
162 |
+
// calculate the total discount percentage
|
163 |
+
$discountPercent = min(100, $item->getDiscountPercent() + $discountPercent);
|
164 |
+
$item->setDiscountPercent($discountPercent);
|
165 |
+
|
166 |
+
// calculate the total discount amount
|
167 |
+
$discountAmount = ($qty * $originalPrice) * $discountPercentMultiplier;
|
168 |
+
$discountAmount = $item->getQuote()->getStore()->roundPrice($discountAmount);
|
169 |
+
$item->setData($this->getCode(), $discountAmount);
|
170 |
+
$discountAmount = $item->getDiscountAmount() + $discountAmount;
|
171 |
+
$item->setDiscountAmount($discountAmount);
|
172 |
+
|
173 |
+
// calculate the total base discount amount
|
174 |
+
$baseDiscountAmount = ($qty * $baseOriginalPrice) * $discountPercentMultiplier;
|
175 |
+
$baseDiscountAmount = $item->getQuote()->getStore()->roundPrice($baseDiscountAmount);
|
176 |
+
$item->setData("base_{$this->getCode()}", $baseDiscountAmount);
|
177 |
+
$baseDiscountAmount = $item->getBaseDiscountAmount() + $baseDiscountAmount;
|
178 |
+
$item->setBaseDiscountAmount($baseDiscountAmount);
|
179 |
+
|
180 |
+
return $this;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Return item quantity to apply discount to.
|
185 |
+
*
|
186 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $item
|
187 |
+
* @return int
|
188 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
189 |
+
*/
|
190 |
+
protected function _getItemQty(Mage_Sales_Model_Quote_Item_Abstract $item)
|
191 |
+
{
|
192 |
+
return $item->getTotalQty();
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Return item original price.
|
197 |
+
*
|
198 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $item
|
199 |
+
* @return float
|
200 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
201 |
+
*/
|
202 |
+
protected function _getItemOriginalPrice(Mage_Sales_Model_Quote_Item_Abstract $item)
|
203 |
+
{
|
204 |
+
return $this->_getApplyDiscountAfterTax($item)
|
205 |
+
? $item->getPriceInclTax()
|
206 |
+
: $item->getPrice();
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Return item base original price.
|
211 |
+
*
|
212 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $item
|
213 |
+
* @return float
|
214 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
215 |
+
*/
|
216 |
+
protected function _getItemBaseOriginalPrice(Mage_Sales_Model_Quote_Item_Abstract $item)
|
217 |
+
{
|
218 |
+
return $this->_getApplyDiscountAfterTax($item)
|
219 |
+
? $item->getBasePriceInclTax()
|
220 |
+
: $item->getBasePrice();
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Retrieve whether to apply discount before(false) or after(true) tax.
|
225 |
+
*
|
226 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $item
|
227 |
+
* @return bool
|
228 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
229 |
+
*/
|
230 |
+
protected function _getApplyDiscountAfterTax(Mage_Sales_Model_Quote_Item_Abstract $item)
|
231 |
+
{
|
232 |
+
return true;
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Aggregate item discount information to address data and related properties
|
237 |
+
*
|
238 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $item
|
239 |
+
* @return Ampersand_Sales_Model_Quote_Address_Total_Discount_PercentageAbstract
|
240 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
241 |
+
*/
|
242 |
+
protected function _aggregateItemDiscount(Mage_Sales_Model_Quote_Item_Abstract $item)
|
243 |
+
{
|
244 |
+
// update the amounts associated with this address
|
245 |
+
$this->_addAmount(-$item->getData($this->getCode()));
|
246 |
+
$this->_addBaseAmount(-$item->getData("base_{$this->getCode()}"));
|
247 |
+
|
248 |
+
// update internal property so we can display discount amount to customer
|
249 |
+
$addressCustomDiscount = $this->_getAddress()->getData($this->getCode());
|
250 |
+
$updatedAddressCustomDiscount = $addressCustomDiscount - $item->getData($this->getCode());
|
251 |
+
$this->_getAddress()->setData($this->getCode(), $updatedAddressCustomDiscount);
|
252 |
+
|
253 |
+
return $this;
|
254 |
+
}
|
255 |
+
}
|
app/code/core/Ampersand/Sales/etc/config.xml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Ampersand_Sales>
|
5 |
+
<version>0.0.1</version>
|
6 |
+
</Ampersand_Sales>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<helpers>
|
10 |
+
<ampersand_sales>
|
11 |
+
<class>Ampersand_Sales_Helper</class>
|
12 |
+
</ampersand_sales>
|
13 |
+
</helpers>
|
14 |
+
<models>
|
15 |
+
<ampersand_sales>
|
16 |
+
<class>Ampersand_Sales_Model</class>
|
17 |
+
</ampersand_sales>
|
18 |
+
</models>
|
19 |
+
</global>
|
20 |
+
</config>
|
app/code/core/Ampersand/System/Helper/Data.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Helper_Data extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Check if the object already exists and set its data if so
|
6 |
+
*
|
7 |
+
* @param mixed $object Object to check if exists
|
8 |
+
* @param string $modelName Shortname of the type of model
|
9 |
+
* @param string $loadField Field name to try loading by
|
10 |
+
* @return Ampersand_System_Helper_Store
|
11 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
12 |
+
*/
|
13 |
+
public function loadIfExists($object, $modelName, $loadField)
|
14 |
+
{
|
15 |
+
if ((!$object->getIsObjectLoaded())
|
16 |
+
&& ($model = Mage::getModel($modelName))
|
17 |
+
&& ($model->load($object->getData($loadField), $loadField))
|
18 |
+
&& ($model->getId())) {
|
19 |
+
$mergedData = array_merge($model->getData(), $object->getData());
|
20 |
+
$object->addData($mergedData);
|
21 |
+
$object->setIsObjectLoaded(true);
|
22 |
+
}
|
23 |
+
|
24 |
+
return $this;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Ensure all required fields are populated and valid
|
29 |
+
*
|
30 |
+
* @param mixed $object Object to validate
|
31 |
+
* @param array $requiredFields Array of required field => default value
|
32 |
+
* @return Ampersand_System_Helper_Store
|
33 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
34 |
+
*/
|
35 |
+
public function validate($object, $requiredFields)
|
36 |
+
{
|
37 |
+
$errors = array();
|
38 |
+
|
39 |
+
foreach ($requiredFields as $_field => $_defaultValue) {
|
40 |
+
if (is_null($object->getDataUsingMethod($_field))) {
|
41 |
+
if (is_null($_defaultValue)) {
|
42 |
+
$errors[] = $_field;
|
43 |
+
} else {
|
44 |
+
$object->setData($_field, $_defaultValue);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
if ($errors) {
|
50 |
+
Mage::throwException('Missing or invalid data: ' . implode(', ', $errors));
|
51 |
+
}
|
52 |
+
|
53 |
+
return $this;
|
54 |
+
}
|
55 |
+
}
|
app/code/core/Ampersand/System/Helper/Store.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Helper_Store extends Mage_Core_Helper_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Flag to ensure reinitStores is only run once
|
6 |
+
*
|
7 |
+
* @var bool $_reinitStoreFlag
|
8 |
+
*/
|
9 |
+
protected $_reinitStoreFlag = false;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Cached default store view
|
13 |
+
*
|
14 |
+
* @var Mage_Core_Model_Store $_defaultStoreView
|
15 |
+
*/
|
16 |
+
protected $_defaultStoreView;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* If Mage::app()->_initStores() has not been run any attempts to retrieve arrays of
|
20 |
+
* stores or websites, eg. Mage::app()->getWebsites() will return empty arrays.
|
21 |
+
*
|
22 |
+
* @return Ampersand_System_Helper_Data
|
23 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
24 |
+
*/
|
25 |
+
public function reinitStores()
|
26 |
+
{
|
27 |
+
if (!$this->_reinitStoreFlag) {
|
28 |
+
$this->_reinitStoreFlag = true;
|
29 |
+
Mage::app()->reinitStores();
|
30 |
+
}
|
31 |
+
|
32 |
+
return $this;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Retrieve the default store view by first re-initialising stores
|
37 |
+
* to ensure Mage_Core_Model_App::_websites is populated.
|
38 |
+
*
|
39 |
+
* @return Mage_Core_Model_Store
|
40 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
41 |
+
*/
|
42 |
+
public function getDefaultStoreView()
|
43 |
+
{
|
44 |
+
if (!$this->_defaultStoreView) {
|
45 |
+
$this->reinitStores();
|
46 |
+
$this->_defaultStoreView = Mage::app()->getDefaultStoreView();
|
47 |
+
}
|
48 |
+
|
49 |
+
return $this->_defaultStoreView;
|
50 |
+
}
|
51 |
+
}
|
app/code/core/Ampersand/System/Model/Cache.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Cache
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Disable cache.
|
6 |
+
*
|
7 |
+
* @return Ampersand_System_Model_Cache
|
8 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
9 |
+
*/
|
10 |
+
public function disableCache()
|
11 |
+
{
|
12 |
+
$options = $this->_getAllOptionsAsDisabled();
|
13 |
+
$this->_getResourceModel()->saveAllOptions($options);
|
14 |
+
|
15 |
+
$this->flushCache();
|
16 |
+
|
17 |
+
return $this;
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Flush cache by following the behaviour of the 'Flush Cache Storage' button.
|
22 |
+
*
|
23 |
+
* @return Ampersand_System_Model_Cache
|
24 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
25 |
+
*/
|
26 |
+
public function flushCache()
|
27 |
+
{
|
28 |
+
if (function_exists('apc_clear_cache')) {
|
29 |
+
apc_clear_cache();
|
30 |
+
apc_clear_cache('user');
|
31 |
+
apc_clear_cache('opcode');
|
32 |
+
}
|
33 |
+
|
34 |
+
Mage::dispatchEvent('adminhtml_cache_flush_all');
|
35 |
+
Mage::app()->getCacheInstance()->flush();
|
36 |
+
|
37 |
+
return $this;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Retreive all cache options as an array with each value set to disabled.
|
42 |
+
*
|
43 |
+
* @return array
|
44 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
45 |
+
*/
|
46 |
+
protected function _getAllOptionsAsDisabled()
|
47 |
+
{
|
48 |
+
$options = $this->_getResourceModel()->getAllOptions();
|
49 |
+
foreach ($options as $_option => &$_value) {
|
50 |
+
$_value = '0';
|
51 |
+
}
|
52 |
+
|
53 |
+
return $options;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Retrieve cache resource model.
|
58 |
+
*
|
59 |
+
* @return type Mage_Core_Model_Mysql4_Cache
|
60 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
61 |
+
*/
|
62 |
+
protected function _getResourceModel()
|
63 |
+
{
|
64 |
+
return Mage::getResourceSingleton('core/cache');
|
65 |
+
}
|
66 |
+
}
|
app/code/core/Ampersand/System/Model/Category.php
ADDED
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Category
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Imported CSV file
|
6 |
+
*
|
7 |
+
* @var array $_importData
|
8 |
+
*/
|
9 |
+
protected $_importData = array();
|
10 |
+
|
11 |
+
/**
|
12 |
+
* RootCategoryId for the selected store
|
13 |
+
*
|
14 |
+
* @var array $_rootCategoryId
|
15 |
+
*/
|
16 |
+
protected $_rootCategoryId;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Currently selected store
|
20 |
+
*
|
21 |
+
* @var Mage_Core_Model_Store
|
22 |
+
*/
|
23 |
+
protected $_store;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Set the scope for store specific config settings
|
27 |
+
*
|
28 |
+
* @param mixed $store Varien_Object, store id or store code
|
29 |
+
* @return Ampersand_System_Model_Category
|
30 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
31 |
+
*/
|
32 |
+
public function setStore($store)
|
33 |
+
{
|
34 |
+
if (!is_object($store)) {
|
35 |
+
$store = Mage::app()->getStore($store);
|
36 |
+
}
|
37 |
+
|
38 |
+
$this->_store = $store;
|
39 |
+
|
40 |
+
return $this;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Set the scope for store specific config settings
|
45 |
+
*
|
46 |
+
* @param mixed $store Varien_Object, store id or store code
|
47 |
+
* @return Ampersand_System_Model_Category
|
48 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
49 |
+
*/
|
50 |
+
public function setDefault()
|
51 |
+
{
|
52 |
+
$this->setStore('default');
|
53 |
+
return $this;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Imports the CSV file of Categories formatted with "Name","url_key","parent_url_key","featured"
|
58 |
+
* The CSV file must be located under $moduleName/data/
|
59 |
+
* @param string $moduleName
|
60 |
+
* @param string $filepath
|
61 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
62 |
+
*/
|
63 |
+
public function import($moduleName, $filepath)
|
64 |
+
{
|
65 |
+
if(!$this->_store){
|
66 |
+
throw new Exception('Store not set');
|
67 |
+
}
|
68 |
+
|
69 |
+
$this->_lockIndexer();
|
70 |
+
// Auto detect line endings
|
71 |
+
ini_set('auto_detect_line_endings', true);
|
72 |
+
|
73 |
+
// Import CSV
|
74 |
+
$parser = new Varien_File_Csv();
|
75 |
+
$filePath = Mage::getModuleDir('', $moduleName) . DS. 'data' . DS . $filepath;
|
76 |
+
$this->_importData = $parser->getData($filePath);
|
77 |
+
|
78 |
+
$this->_rootCategoryId = $this->_store->getRootCategoryId();
|
79 |
+
|
80 |
+
$currentStoreId = Mage::app()->getStore()->getId();
|
81 |
+
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
|
82 |
+
$this->_deleteAllCategories();
|
83 |
+
$this->_createNewCategories();
|
84 |
+
$this->_makeAllCategoriesAnchors();
|
85 |
+
$this->_reIndex();
|
86 |
+
Mage::app()->getStore()->setId($currentStoreId);
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Locks the indexer prior to deleting and creating categories
|
91 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
92 |
+
*/
|
93 |
+
protected function _lockIndexer()
|
94 |
+
{
|
95 |
+
Mage::getSingleton('index/indexer')->lockIndexer();
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Delete all categories below the root category
|
100 |
+
*/
|
101 |
+
protected function _deleteAllCategories()
|
102 |
+
{
|
103 |
+
$rootCategory = Mage::getModel('catalog/category')->load($this->_rootCategoryId);
|
104 |
+
$query = "DELETE FROM `catalog_category_product` WHERE `category_id` IN (SELECT entity_id FROM `catalog_category_entity` WHERE `path` LIKE '{$rootCategory->getPath()}/%')";
|
105 |
+
Mage::getResourceModel('catalog/category')->getWriteConnection()->query($query);
|
106 |
+
|
107 |
+
$query = "DELETE FROM catalog_category_entity where `path` LIKE '{$rootCategory->getPath()}/%'";
|
108 |
+
Mage::getResourceModel('catalog/category')->getWriteConnection()->query($query);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Creates New Categories based on those retrieved from the uploaded CSV file
|
113 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
114 |
+
*/
|
115 |
+
protected function _createNewCategories()
|
116 |
+
{
|
117 |
+
$csvCategories = array();
|
118 |
+
$parentCategories = array();
|
119 |
+
|
120 |
+
foreach ($this->_importData as $_line) {
|
121 |
+
$name = isset($_line[0]) ? $_line[0] : '';
|
122 |
+
$urlKey = isset($_line[1]) ? $_line[1] : '';
|
123 |
+
$parentUrlKey = isset($_line[2]) ? $_line[2] : '';
|
124 |
+
$featured = isset($_line[3]) ? $_line[3] : '0';
|
125 |
+
|
126 |
+
$name = trim($name);
|
127 |
+
$urlKey = strtolower(preg_replace('/[^a-zA-Z0-9\\\]/', '-', str_replace(array(' & ', ' &', '& '), '-and-', trim($urlKey))));
|
128 |
+
$parentUrlKey = strtolower(preg_replace('/[^a-zA-Z0-9\\\]/', '-', str_replace(array(' & ', ' &', '& '), '-and-', trim($parentUrlKey))));
|
129 |
+
|
130 |
+
if (!$name || !$urlKey) {
|
131 |
+
//echo 'Missing name or url key: ' . print_r($_line, true) . '<br />';
|
132 |
+
continue;
|
133 |
+
}
|
134 |
+
if (!$parentUrlKey) {
|
135 |
+
$parentId = $this->_rootCategoryId;
|
136 |
+
|
137 |
+
} else {
|
138 |
+
if (array_key_exists($parentUrlKey, $parentCategories)) {
|
139 |
+
$parentId = $parentCategories[$parentUrlKey];
|
140 |
+
} else {
|
141 |
+
//echo 'Parent Category does not exist: ' . print_r($_line, true) . '<br />';
|
142 |
+
continue;
|
143 |
+
}
|
144 |
+
}
|
145 |
+
$parentCategories[$urlKey] = $this->_createCategory(array(
|
146 |
+
'name' => $name,
|
147 |
+
'url_key' => $urlKey,
|
148 |
+
'featured' => $featured,
|
149 |
+
), $parentId);
|
150 |
+
}
|
151 |
+
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Creates an individual category
|
156 |
+
*
|
157 |
+
* @param array $categoryData
|
158 |
+
* @param int $parentId
|
159 |
+
* @return categoryId
|
160 |
+
*/
|
161 |
+
protected function _createCategory($categoryData, $parentId)
|
162 |
+
{
|
163 |
+
// Default required fields
|
164 |
+
$categoryDefaultData = array(
|
165 |
+
'name' => 'Name',
|
166 |
+
'url_key' => 'url-key',
|
167 |
+
'available_sort_by' => 'position',
|
168 |
+
'default_sort_by' => 'position',
|
169 |
+
'include_in_menu' => '1',
|
170 |
+
'is_active' => '1',
|
171 |
+
);
|
172 |
+
|
173 |
+
$categoryDataObject = new stdClass();
|
174 |
+
$categoryData = array_merge($categoryDefaultData, $categoryData);
|
175 |
+
foreach ($categoryData as $_field => &$_value) {
|
176 |
+
// Make sure we have values set for the required attributes
|
177 |
+
if (array_key_exists($_field, $categoryDefaultData) && !$_value) {
|
178 |
+
$_value = $categoryDefaultData[$_field];
|
179 |
+
}
|
180 |
+
$categoryDataObject->{$_field} = $_value;
|
181 |
+
}
|
182 |
+
try {
|
183 |
+
$categoryId = Mage::getModel('catalog/category_api_v2')
|
184 |
+
->create($parentId, $categoryDataObject, null)
|
185 |
+
;
|
186 |
+
|
187 |
+
} catch (Exception $e) {
|
188 |
+
Mage::log($e->getMessage() . PHP_EOL . print_r($categoryDataObject, true) . PHP_EOL . $e->getTraceAsString());
|
189 |
+
die('Unable to create category' . PHP_EOL . print_r($categoryDataObject, true));
|
190 |
+
}
|
191 |
+
return $categoryId;
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Make all categories anchors
|
196 |
+
*/
|
197 |
+
protected function _makeAllCategoriesAnchors()
|
198 |
+
{
|
199 |
+
$categoryIds = Mage::getResourceModel('catalog/category_collection')
|
200 |
+
->addAttributeToFilter('level', array('gteq' => '2'))
|
201 |
+
->getAllIds()
|
202 |
+
;
|
203 |
+
|
204 |
+
foreach ($categoryIds as $_categoryId) {
|
205 |
+
$category = Mage::getModel('catalog/category')->load($_categoryId);
|
206 |
+
$category->setIsAnchor(true);
|
207 |
+
$category->save();
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Unlock and reIndex categories
|
213 |
+
*/
|
214 |
+
protected function _reIndex()
|
215 |
+
{
|
216 |
+
Mage::getSingleton('index/indexer')->unlockIndexer()->indexEvents();
|
217 |
+
}
|
218 |
+
}
|
app/code/core/Ampersand/System/Model/Cms/Block.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Cms_Block extends Mage_Cms_Model_Block
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Shortname of this class
|
6 |
+
*
|
7 |
+
* @var string $_modelName
|
8 |
+
*/
|
9 |
+
protected $_modelName = 'cms/block';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Field to load by when checking if already exists
|
13 |
+
*
|
14 |
+
* @var string $_loadField
|
15 |
+
*/
|
16 |
+
protected $_loadField = 'identifier';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Database column name of the id field
|
20 |
+
*
|
21 |
+
* @var string $_idField
|
22 |
+
*/
|
23 |
+
protected $_idField = 'block_id';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Required fields for saving this object.
|
27 |
+
* If a default value is allowed then provide a non-null value
|
28 |
+
*
|
29 |
+
* @var array $_requiredFields
|
30 |
+
*/
|
31 |
+
protected $_requiredFields = array(
|
32 |
+
'title' => null,
|
33 |
+
'identifier' => null,
|
34 |
+
'stores' => array('0' => '0'),
|
35 |
+
'is_active' => '1',
|
36 |
+
'content' => ' ',
|
37 |
+
);
|
38 |
+
|
39 |
+
/**
|
40 |
+
* By setting the ID of a Block, we attempt to load it. If we are unable
|
41 |
+
* to load the Block, unset the id field as we want a new Sroup to be created.
|
42 |
+
*
|
43 |
+
* @param type $id int
|
44 |
+
* @return Ampersand_System_Model_Cms_Block
|
45 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
46 |
+
*/
|
47 |
+
public function setId($id)
|
48 |
+
{
|
49 |
+
parent::setData($this->_idField, $id);
|
50 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_idField);
|
51 |
+
|
52 |
+
if (!$this->getIsObjectLoaded()) {
|
53 |
+
parent::unsData($this->_idField);
|
54 |
+
}
|
55 |
+
|
56 |
+
return $this;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Load if exists, validate and save the object
|
61 |
+
*
|
62 |
+
* @return Mage_Core_Model_Website
|
63 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
64 |
+
*/
|
65 |
+
protected function _beforeSave()
|
66 |
+
{
|
67 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_loadField);
|
68 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
69 |
+
|
70 |
+
return parent::_beforeSave();
|
71 |
+
}
|
72 |
+
}
|
app/code/core/Ampersand/System/Model/Cms/Page.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Cms_Page extends Mage_Cms_Model_Page
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Shortname of this class
|
6 |
+
*
|
7 |
+
* @var string $_modelName
|
8 |
+
*/
|
9 |
+
protected $_modelName = 'cms/page';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Field to load by when checking if already exists
|
13 |
+
*
|
14 |
+
* @var string $_loadField
|
15 |
+
*/
|
16 |
+
protected $_loadField = 'identifier';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Database column name of the id field
|
20 |
+
*
|
21 |
+
* @var string $_idField
|
22 |
+
*/
|
23 |
+
protected $_idField = 'page_id';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Required fields for saving this object.
|
27 |
+
* If a default value is allowed then provide a non-null value
|
28 |
+
*
|
29 |
+
* @var array $_requiredFields
|
30 |
+
*/
|
31 |
+
protected $_requiredFields = array(
|
32 |
+
'title' => null,
|
33 |
+
'identifier' => null,
|
34 |
+
'is_active' => '1',
|
35 |
+
'content_heading' => '',
|
36 |
+
'content' => ' ',
|
37 |
+
'root_template' => 'empty',
|
38 |
+
'under_version_control' => '0',
|
39 |
+
'stores' => array(0),
|
40 |
+
);
|
41 |
+
|
42 |
+
/**
|
43 |
+
* By setting the ID of a Page, we attempt to load it. If we are unable
|
44 |
+
* to load the Page, unset the id field as we want a new Sroup to be created.
|
45 |
+
*
|
46 |
+
* @param type $id int
|
47 |
+
* @return Ampersand_System_Model_Cms_Page
|
48 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
49 |
+
*/
|
50 |
+
public function setId($id)
|
51 |
+
{
|
52 |
+
parent::setData($this->_idField, $id);
|
53 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_idField);
|
54 |
+
|
55 |
+
if (!$this->getIsObjectLoaded()) {
|
56 |
+
parent::unsData($this->_idField);
|
57 |
+
}
|
58 |
+
|
59 |
+
return $this;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Load if exists, validate and save the object
|
64 |
+
*
|
65 |
+
* @return Mage_Core_Model_Website
|
66 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
67 |
+
*/
|
68 |
+
protected function _beforeSave()
|
69 |
+
{
|
70 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_loadField);
|
71 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
72 |
+
|
73 |
+
return parent::_beforeSave();
|
74 |
+
}
|
75 |
+
}
|
app/code/core/Ampersand/System/Model/Config.php
ADDED
@@ -0,0 +1,401 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Config extends Mage_Core_Model_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Required fields for saving this object.
|
6 |
+
* If a default value is allowed then provide a non-null value
|
7 |
+
*
|
8 |
+
* @var array $_requiredFields
|
9 |
+
*/
|
10 |
+
protected $_requiredFields = array(
|
11 |
+
'scope' => null,
|
12 |
+
'scope_id' => null,
|
13 |
+
'scope_code' => null,
|
14 |
+
);
|
15 |
+
|
16 |
+
/**
|
17 |
+
* If these methods are called with setXxx, addXxx, setData(xxx, xxx) etc.
|
18 |
+
* setDataUsingMethod() will always be forced.
|
19 |
+
*
|
20 |
+
* @var array $_forceSetDataUsingMethod
|
21 |
+
*/
|
22 |
+
protected $_forceSetDataUsingMethod = array(
|
23 |
+
'default',
|
24 |
+
'website',
|
25 |
+
'store',
|
26 |
+
'node',
|
27 |
+
);
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Scope of config item to be saved
|
31 |
+
*
|
32 |
+
* @var string $_scope
|
33 |
+
*/
|
34 |
+
protected $_scope;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* For store and website scope, this value should be the store or website id
|
38 |
+
*
|
39 |
+
* @var int $_scopeId
|
40 |
+
*/
|
41 |
+
protected $_scopeId;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* For store and website scope, this value should be the store or website code
|
45 |
+
*
|
46 |
+
* @var int $_scopeCode
|
47 |
+
*/
|
48 |
+
protected $_scopeCode;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Config nodes to be updated
|
52 |
+
*
|
53 |
+
* @var array $_nodes
|
54 |
+
*/
|
55 |
+
protected $_nodes = array();
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Default scope
|
59 |
+
*/
|
60 |
+
const SCOPE_DEFAULT = 'default';
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Website specific scope
|
64 |
+
*/
|
65 |
+
const SCOPE_WEBSITE = 'websites';
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Store specific scope
|
69 |
+
*/
|
70 |
+
const SCOPE_STORE = 'stores';
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Default scope id
|
74 |
+
*/
|
75 |
+
const DEFAULT_SCOPE_ID = 0;
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Default scope code
|
79 |
+
*/
|
80 |
+
const DEFAULT_SCOPE_CODE = '';
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Set the scope for default config settings
|
84 |
+
*
|
85 |
+
* @param bool OPTIONAL Friendly syntax for setData('default', true);
|
86 |
+
* @return Ampersand_System_Model_Config
|
87 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
88 |
+
*/
|
89 |
+
public function setDefault($foobar = true)
|
90 |
+
{
|
91 |
+
$this->_scope = self::SCOPE_DEFAULT;
|
92 |
+
$this->_scopeId = self::DEFAULT_SCOPE_ID;
|
93 |
+
$this->_scopeCode = self::DEFAULT_SCOPE_CODE;
|
94 |
+
|
95 |
+
return $this;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Set the scope for website specific config settings
|
100 |
+
*
|
101 |
+
* @param mixed $website Varien_Object, website id or website code
|
102 |
+
* @return Ampersand_System_Model_Config
|
103 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
104 |
+
*/
|
105 |
+
public function setWebsite($website)
|
106 |
+
{
|
107 |
+
if (!is_object($website)) {
|
108 |
+
$website = Mage::app()->getWebsite($website);
|
109 |
+
}
|
110 |
+
$websiteId = $website->getId();
|
111 |
+
$websiteCode = $website->getCode();
|
112 |
+
|
113 |
+
if ($websiteId !== self::DEFAULT_SCOPE_ID) {
|
114 |
+
$this->_scope = self::SCOPE_WEBSITE;
|
115 |
+
$this->_scopeId = $websiteId;
|
116 |
+
$this->_scopeCode = $websiteCode;
|
117 |
+
}
|
118 |
+
|
119 |
+
return $this;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Set the scope for store specific config settings
|
124 |
+
*
|
125 |
+
* @param mixed $store Varien_Object, store id or store code
|
126 |
+
* @return Ampersand_System_Model_Config
|
127 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
128 |
+
*/
|
129 |
+
public function setStore($store)
|
130 |
+
{
|
131 |
+
if (!is_object($store)) {
|
132 |
+
$store = Mage::app()->getStore($store);
|
133 |
+
}
|
134 |
+
$storeId = $store->getId();
|
135 |
+
$storeCode = $store->getCode();
|
136 |
+
|
137 |
+
if ($storeId !== self::DEFAULT_SCOPE_ID) {
|
138 |
+
$this->_scope = self::SCOPE_STORE;
|
139 |
+
$this->_scopeId = $storeId;
|
140 |
+
$this->_scopeCode = $storeCode;
|
141 |
+
}
|
142 |
+
|
143 |
+
return $this;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Add a new config node to be updated. Multiple values can be set using an
|
148 |
+
* array of path => value pairs. If the value is set to null, then the
|
149 |
+
* corresponding config node will be deleted for that scope.
|
150 |
+
*
|
151 |
+
* @param mixed $path Array of path => value or single path of config setting
|
152 |
+
* @param type $value New value of config setting
|
153 |
+
* @return Ampersand_System_Model_Config
|
154 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
155 |
+
*/
|
156 |
+
public function setNode($path, $value = null)
|
157 |
+
{
|
158 |
+
if (is_array($path)) {
|
159 |
+
foreach ($path as $_path => $_value) {
|
160 |
+
$this->setNode($_path, $_value);
|
161 |
+
}
|
162 |
+
} else {
|
163 |
+
$path = trim($path, ' /');
|
164 |
+
$this->_nodes[$path] = $value;
|
165 |
+
}
|
166 |
+
|
167 |
+
return $this;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Retrieve config node value by $path. If no value is found for the current scope
|
172 |
+
* the value in the parent scope will be returned. eg. website or default config value.
|
173 |
+
*
|
174 |
+
* @param string $path Path of config setting to retrieve
|
175 |
+
* @return string
|
176 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
177 |
+
*/
|
178 |
+
public function getNode($path)
|
179 |
+
{
|
180 |
+
$path = trim($path, ' /');
|
181 |
+
|
182 |
+
$value = Mage::getConfig()->getNode(
|
183 |
+
$path,
|
184 |
+
$this->getScope(),
|
185 |
+
$this->getScopeCode()
|
186 |
+
);
|
187 |
+
|
188 |
+
return $value ? (string)$value : null;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Retrieve config node value by $path for the the current scope only. If no value
|
193 |
+
* is found in this scope no value will be returned, regardless of parent scope values.
|
194 |
+
*
|
195 |
+
* @param string $path Path of config setting to retrieve
|
196 |
+
* @return string
|
197 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
198 |
+
*/
|
199 |
+
public function getNodeInScope($path)
|
200 |
+
{
|
201 |
+
$config = Mage::getResourceModel('core/config');
|
202 |
+
$connection = $config->getReadConnection();
|
203 |
+
$select = $connection->select()
|
204 |
+
->from($config->getMainTable())
|
205 |
+
->where('path=?', $path)
|
206 |
+
->where('scope=?', $this->getScope())
|
207 |
+
->where('scope_id=?', $this->getScopeId());
|
208 |
+
$row = $connection->fetchRow($select);
|
209 |
+
return (is_array($row)) ? $row['value'] : null;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Retrieve the current scope
|
214 |
+
*
|
215 |
+
* @return string
|
216 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
217 |
+
*/
|
218 |
+
public function getScope()
|
219 |
+
{
|
220 |
+
if (!$this->_scope) {
|
221 |
+
$this->setDefault();
|
222 |
+
}
|
223 |
+
|
224 |
+
return $this->_scope;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Retrieve the current scope id
|
229 |
+
*
|
230 |
+
* @return int
|
231 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
232 |
+
*/
|
233 |
+
public function getScopeId()
|
234 |
+
{
|
235 |
+
if (!$this->_scopeId) {
|
236 |
+
$this->setDefault();
|
237 |
+
}
|
238 |
+
|
239 |
+
return $this->_scopeId;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Retrieve the current scope code
|
244 |
+
*
|
245 |
+
* @return string
|
246 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
247 |
+
*/
|
248 |
+
public function getScopeCode()
|
249 |
+
{
|
250 |
+
if (!$this->_scopeCode) {
|
251 |
+
$this->setDefault();
|
252 |
+
}
|
253 |
+
|
254 |
+
return $this->_scopeCode;
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
259 |
+
*
|
260 |
+
* @param mixed $key
|
261 |
+
* @param mixed $value
|
262 |
+
* @return Ampersand_System_Model_Config
|
263 |
+
*/
|
264 |
+
public function setData($key, $value = null)
|
265 |
+
{
|
266 |
+
if (is_array($key)) {
|
267 |
+
foreach ($key as $_key => $_value) {
|
268 |
+
$this->_setDataUsingMethod($_key, $_value);
|
269 |
+
}
|
270 |
+
} else {
|
271 |
+
$this->_setDataUsingMethod($key, $value);
|
272 |
+
}
|
273 |
+
|
274 |
+
return $this;
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
279 |
+
*
|
280 |
+
* @param string $key
|
281 |
+
* @param mixed $value
|
282 |
+
* @return Ampersand_System_Model_Config
|
283 |
+
*/
|
284 |
+
protected function _setDataUsingMethod($key, $value = null)
|
285 |
+
{
|
286 |
+
if (in_array($key, $this->_forceSetDataUsingMethod)) {
|
287 |
+
$this->setDataUsingMethod($key, $value);
|
288 |
+
} else {
|
289 |
+
parent::setData($key, $value);
|
290 |
+
}
|
291 |
+
|
292 |
+
return $this;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Update the config settings
|
297 |
+
*
|
298 |
+
* @return Ampersand_System_Model_Config
|
299 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
300 |
+
*/
|
301 |
+
public function save($reinit = true, $useBackend = false)
|
302 |
+
{
|
303 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
304 |
+
|
305 |
+
foreach ($this->_nodes as $_path => $_value) {
|
306 |
+
$config = Mage::getModel('core/config');
|
307 |
+
if (is_null($_value)) {
|
308 |
+
$config->deleteConfig($_path, $this->getScope(), $this->getScopeId());
|
309 |
+
} else {
|
310 |
+
if (!$useBackend || !$this->_saveWithClassInstance($_path, $_value)) {
|
311 |
+
$config->saveConfig($_path, $_value, $this->getScope(), $this->getScopeId());
|
312 |
+
}
|
313 |
+
}
|
314 |
+
}
|
315 |
+
|
316 |
+
if ($reinit) {
|
317 |
+
$this->_reinit();
|
318 |
+
}
|
319 |
+
|
320 |
+
return $this;
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Attempt to save the config node using the backend model, if specified. This resolves
|
325 |
+
* issues with values like passwords which need to be encrypted before being saved.
|
326 |
+
*
|
327 |
+
* @param string $path
|
328 |
+
* @param string $value
|
329 |
+
* @return bool
|
330 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
331 |
+
*/
|
332 |
+
public function _saveWithClassInstance($path, $value)
|
333 |
+
{
|
334 |
+
$configSections = Mage::getSingleton('adminhtml/config')->getSections();
|
335 |
+
if (!$configSections) {
|
336 |
+
return false;
|
337 |
+
}
|
338 |
+
|
339 |
+
$pathParts = explode('/', $path);
|
340 |
+
$backendModelNode = $configSections->xpath("//sections/{$pathParts[0]}/groups/{$pathParts[1]}/fields/{$pathParts[2]}/backend_model");
|
341 |
+
if (!is_array($backendModelNode)) {
|
342 |
+
return false;
|
343 |
+
}
|
344 |
+
|
345 |
+
$backendModelAlias = array_shift($backendModelNode);
|
346 |
+
$backendModelAlias = (string)$backendModelAlias;
|
347 |
+
if ($backendModelAlias == '') {
|
348 |
+
return false;
|
349 |
+
}
|
350 |
+
|
351 |
+
$classInstance = Mage::getModel($backendModelAlias);
|
352 |
+
if (!$classInstance instanceof Mage_Core_Model_Config_Data) {
|
353 |
+
return false;
|
354 |
+
}
|
355 |
+
|
356 |
+
$node = $classInstance->getCollection()
|
357 |
+
->addFieldToFilter('scope', $this->getScope())
|
358 |
+
->addFieldToFilter('scope_id', $this->getScopeId())
|
359 |
+
->addFieldToFilter('path', $path)
|
360 |
+
->getFirstItem();
|
361 |
+
|
362 |
+
if ($nodeId = $node->getId()) {
|
363 |
+
$classInstance->load($nodeId);
|
364 |
+
}
|
365 |
+
|
366 |
+
$classInstance->addData(array(
|
367 |
+
'scope' => $this->getScope(),
|
368 |
+
'scope_id' => $this->getScopeId(),
|
369 |
+
'path' => $path,
|
370 |
+
'value' => $value,
|
371 |
+
));
|
372 |
+
|
373 |
+
$classInstance->save();
|
374 |
+
|
375 |
+
return true;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Reinit config so latest changes immediately available
|
380 |
+
*
|
381 |
+
* @return Ampersand_System_Model_Config
|
382 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
383 |
+
*/
|
384 |
+
protected function _reinit()
|
385 |
+
{
|
386 |
+
switch ($this->getScope())
|
387 |
+
{
|
388 |
+
case self::SCOPE_DEFAULT:
|
389 |
+
case self::SCOPE_WEBSITE:
|
390 |
+
$config = Mage::getConfig();
|
391 |
+
$config->reinit($config->getOptions());
|
392 |
+
break;
|
393 |
+
|
394 |
+
case self::SCOPE_STORE:
|
395 |
+
Mage::app()->getStore($this->getScopeId())->resetConfig();
|
396 |
+
break;
|
397 |
+
}
|
398 |
+
|
399 |
+
return $this;
|
400 |
+
}
|
401 |
+
}
|
app/code/core/Ampersand/System/Model/Group.php
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Group extends Mage_Core_Model_Store_Group
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Shortname of this class
|
6 |
+
*
|
7 |
+
* @var string $_modelName
|
8 |
+
*/
|
9 |
+
protected $_modelName = 'core/store_group';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Field to load by when checking if already exists
|
13 |
+
*
|
14 |
+
* @var string $_loadField
|
15 |
+
*/
|
16 |
+
protected $_loadField = 'name';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Database column name of the id field
|
20 |
+
*
|
21 |
+
* @var string $_idField
|
22 |
+
*/
|
23 |
+
protected $_idField = 'group_id';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Required fields for saving this object.
|
27 |
+
* If a default value is allowed then provide a non-null value
|
28 |
+
*
|
29 |
+
* @var array $_requiredFields
|
30 |
+
*/
|
31 |
+
protected $_requiredFields = array(
|
32 |
+
'name' => null,
|
33 |
+
'website_id' => null,
|
34 |
+
'root_category_id' => null,
|
35 |
+
);
|
36 |
+
|
37 |
+
/**
|
38 |
+
* If these methods are called with setXxx, addXxx, setData(xxx, xxx) etc.
|
39 |
+
* setDataUsingMethod() will always be forced.
|
40 |
+
*
|
41 |
+
* @var array $_forceSetDataUsingMethod
|
42 |
+
*/
|
43 |
+
protected $_forceSetDataUsingMethod = array(
|
44 |
+
'id',
|
45 |
+
'website_id',
|
46 |
+
);
|
47 |
+
|
48 |
+
/**
|
49 |
+
* By setting the ID of a Group, we attempt to load it. If we are unable
|
50 |
+
* to load the Group, unset the id field as we want a new Group to be created.
|
51 |
+
*
|
52 |
+
* @param type $id int
|
53 |
+
* @return Ampersand_System_Model_Group
|
54 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
55 |
+
*/
|
56 |
+
public function setId($id)
|
57 |
+
{
|
58 |
+
parent::setData($this->_idField, $id);
|
59 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_idField);
|
60 |
+
|
61 |
+
if (!$this->getIsObjectLoaded()) {
|
62 |
+
parent::unsData($this->_idField);
|
63 |
+
}
|
64 |
+
|
65 |
+
return $this;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Set the website id to associate this Group with
|
70 |
+
*
|
71 |
+
* @param mixed $website Varien_Object, website id or website code
|
72 |
+
* @return Ampersand_System_Model_Group
|
73 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
74 |
+
*/
|
75 |
+
public function setWebsiteId($website)
|
76 |
+
{
|
77 |
+
if (!is_object($website)) {
|
78 |
+
$website = Mage::app()->getWebsite($website);
|
79 |
+
}
|
80 |
+
$websiteId = $website->getId();
|
81 |
+
parent::setData('website_id', $websiteId);
|
82 |
+
|
83 |
+
return $this;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* If not already set, retrieve the default website/group/store
|
88 |
+
* combination and return the website id for that store.
|
89 |
+
*
|
90 |
+
* @return int
|
91 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
92 |
+
*/
|
93 |
+
public function getWebsiteId()
|
94 |
+
{
|
95 |
+
if (!$websiteId = $this->getData('website_id')) {
|
96 |
+
if ($defaultStoreView = Mage::helper('ampersand_system/store')->getDefaultStoreView()) {
|
97 |
+
$websiteId = $defaultStoreView->getWebsiteId();
|
98 |
+
}
|
99 |
+
parent::setData('website_id', $websiteId);
|
100 |
+
}
|
101 |
+
|
102 |
+
return $websiteId;
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* If not already set, retrieve the default website/group/store
|
107 |
+
* combination and return the root category for that store.
|
108 |
+
*
|
109 |
+
* @return int
|
110 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
111 |
+
*/
|
112 |
+
public function getRootCategoryId()
|
113 |
+
{
|
114 |
+
if (!$rootCategoryId = $this->getData('root_category_id')) {
|
115 |
+
if ($defaultStoreView = Mage::helper('ampersand_system/store')->getDefaultStoreView()) {
|
116 |
+
$rootCategoryId = $defaultStoreView->getRootCategoryId();
|
117 |
+
}
|
118 |
+
$this->setRootCategoryId($rootCategoryId);
|
119 |
+
}
|
120 |
+
|
121 |
+
return $rootCategoryId;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
126 |
+
*
|
127 |
+
* @param mixed $key
|
128 |
+
* @param mixed $value
|
129 |
+
* @return Ampersand_System_Model_Group
|
130 |
+
*/
|
131 |
+
public function setData($key, $value = null)
|
132 |
+
{
|
133 |
+
if (is_array($key)) {
|
134 |
+
foreach ($key as $_key => $_value) {
|
135 |
+
$this->_setDataUsingMethod($_key, $_value);
|
136 |
+
}
|
137 |
+
} else {
|
138 |
+
$this->_setDataUsingMethod($key, $value);
|
139 |
+
}
|
140 |
+
|
141 |
+
return $this;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
146 |
+
*
|
147 |
+
* @param string $key
|
148 |
+
* @param mixed $value
|
149 |
+
* @return Ampersand_System_Model_Group
|
150 |
+
*/
|
151 |
+
protected function _setDataUsingMethod($key, $value = null)
|
152 |
+
{
|
153 |
+
if (in_array($key, $this->_forceSetDataUsingMethod)) {
|
154 |
+
$this->setDataUsingMethod($key, $value);
|
155 |
+
} else {
|
156 |
+
parent::setData($key, $value);
|
157 |
+
}
|
158 |
+
|
159 |
+
return $this;
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Load if exists, validate and save the object
|
164 |
+
*
|
165 |
+
* @return Ampersand_System_Model_Group
|
166 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
167 |
+
*/
|
168 |
+
protected function _beforeSave()
|
169 |
+
{
|
170 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_loadField);
|
171 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
172 |
+
|
173 |
+
return parent::_beforeSave();
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Reinitstores required so new object available from Mage::app().
|
178 |
+
*
|
179 |
+
* @return Ampersand_System_Model_Group
|
180 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
181 |
+
*/
|
182 |
+
protected function _afterSave()
|
183 |
+
{
|
184 |
+
parent::_afterSave();
|
185 |
+
|
186 |
+
if ($this->isObjectNew()) {
|
187 |
+
Mage::app()->reinitStores();
|
188 |
+
}
|
189 |
+
|
190 |
+
return $this;
|
191 |
+
}
|
192 |
+
}
|
app/code/core/Ampersand/System/Model/Images.php
ADDED
@@ -0,0 +1,305 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Images
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Path to the source directory where images to be uploaded are held
|
6 |
+
*
|
7 |
+
* @var string $_srcDir
|
8 |
+
*/
|
9 |
+
protected $_srcDir;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Path to the destination directory where images are to be copied
|
13 |
+
*
|
14 |
+
* @var string $_destDir
|
15 |
+
*/
|
16 |
+
protected $_destDir;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Used to reference the system.xml config object
|
20 |
+
*
|
21 |
+
* @var Mage_Core_Model_Config $_config
|
22 |
+
*/
|
23 |
+
protected $_config;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Used to store the details of the images to be upload
|
27 |
+
*
|
28 |
+
* @var array $_files
|
29 |
+
*/
|
30 |
+
protected $_files;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* List of valid image file extensions
|
34 |
+
*
|
35 |
+
* @var array $_files
|
36 |
+
*/
|
37 |
+
protected $_allowedFileTypes = array(
|
38 |
+
'jpg',
|
39 |
+
'jpeg',
|
40 |
+
'gif',
|
41 |
+
'png',
|
42 |
+
);
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Initialises the source, destination directories and loads the system.xml config
|
46 |
+
*
|
47 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
48 |
+
*/
|
49 |
+
public function __construct()
|
50 |
+
{
|
51 |
+
$this->_srcDir = Mage::app()->getConfig()->getBaseDir() . DS .'media' . DS . 'ampersand';
|
52 |
+
$this->_destDir = Mage::app()->getConfig()->getBaseDir() . DS .'media';
|
53 |
+
$this->_config = Mage::getConfig()->loadModulesConfiguration('system.xml');
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Returns the config page for given image file name in a special format i.e. sales-identity-logo.jpg
|
58 |
+
* 'sales-identity-logo' would be the config path
|
59 |
+
*
|
60 |
+
* @param string $path
|
61 |
+
* @return string
|
62 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
63 |
+
*/
|
64 |
+
protected function _getConfigPath($path)
|
65 |
+
{
|
66 |
+
$path = split('\.',$path);
|
67 |
+
$path = str_replace('-',DS,$path[0]);
|
68 |
+
$configPath = $path;
|
69 |
+
return $configPath;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Returns the source path under the media/ampersand folder to the image file to be uploaded
|
74 |
+
* i.e. 'stores/default'
|
75 |
+
*
|
76 |
+
* @param string $path
|
77 |
+
* @return string
|
78 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
79 |
+
*/
|
80 |
+
protected function _getSourcePath($path)
|
81 |
+
{
|
82 |
+
$sourcePath = str_replace($this->_srcDir . DS,'',$path);
|
83 |
+
return $sourcePath;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Returns the destination path under the destination upload url by converting the source
|
88 |
+
* i.e. source path - 'stores/default' would be convert to destination path - 'stores/1'
|
89 |
+
*
|
90 |
+
* @param string $path
|
91 |
+
* @return string
|
92 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
93 |
+
*/
|
94 |
+
protected function getDestinationPath($path)
|
95 |
+
{
|
96 |
+
$path = $this->_getSourcePath($path);
|
97 |
+
$path = split(DS,$path);
|
98 |
+
if (count($path)>1) {
|
99 |
+
if ($path[0]=='websites') {
|
100 |
+
$id = Mage::app()->getWebsite($path[1])->getId();
|
101 |
+
} elseif ($path[0]=='stores') {
|
102 |
+
$id = Mage::app()->getStore($path[1])->getId();
|
103 |
+
}
|
104 |
+
$destinationPath = $path[0]. DS . $id;
|
105 |
+
} else {
|
106 |
+
$destinationPath = $path[0];
|
107 |
+
}
|
108 |
+
return $destinationPath;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Returns the uploadUrl folder to which images are to be copied
|
113 |
+
* This is retrieved by searching the system.xml file using the config path
|
114 |
+
*
|
115 |
+
* @param string $configPath
|
116 |
+
* @return string
|
117 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
118 |
+
*/
|
119 |
+
protected function _getUploadUrl($configPath)
|
120 |
+
{
|
121 |
+
$configPath = $this->_getConfigPath($configPath);
|
122 |
+
$configPath = split(DS, $configPath);
|
123 |
+
$results = $this->_config->getNode('sections/' . $configPath[0] . '/groups/' . $configPath[1] . '/fields/' . $configPath[2] . '/upload_dir');
|
124 |
+
if (empty($results)) throw new Exception();
|
125 |
+
return (string) $results;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Returns the scope to which this image should be associated with i.e. default, websites, stores
|
130 |
+
*
|
131 |
+
* @param string $path
|
132 |
+
* @return string
|
133 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
134 |
+
*/
|
135 |
+
protected function _getScope($path)
|
136 |
+
{
|
137 |
+
$path = $this->_getSourcePath($path);
|
138 |
+
$path = split(DS,$path);
|
139 |
+
return $path[0];
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Returns the scopeId to which this image should be associated
|
144 |
+
*
|
145 |
+
* @param string $path
|
146 |
+
* @return int
|
147 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
148 |
+
*/
|
149 |
+
protected function _getScopeId($path)
|
150 |
+
{
|
151 |
+
$path = $this->_getSourcePath($path);
|
152 |
+
$path = $this->getDestinationPath($path);
|
153 |
+
$path = split(DS,$path);
|
154 |
+
if ($path[0]=='websites' || $path[0]=='stores') {
|
155 |
+
$scopeId = $path[1];
|
156 |
+
} else {
|
157 |
+
$scopeId = 0;
|
158 |
+
}
|
159 |
+
return $scopeId;
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Checks if a image file has a valid file extension
|
164 |
+
*
|
165 |
+
* @param string $filename
|
166 |
+
* @return boolean
|
167 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
168 |
+
*/
|
169 |
+
protected function _isValidImage($filename)
|
170 |
+
{
|
171 |
+
$filename = explode('.', $filename);
|
172 |
+
if (!in_array($filename[1], $this->_allowedFileTypes)) {
|
173 |
+
return false;
|
174 |
+
}
|
175 |
+
|
176 |
+
return true;
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Retrieves the image details for all the images in the source folder i.e. 'media/ampersand'
|
181 |
+
* This recusively iterates through the folders until it gets to an image file upon which the
|
182 |
+
* images details are retrieved and added to an array
|
183 |
+
*
|
184 |
+
* @param string $outerDir
|
185 |
+
* @return array
|
186 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
187 |
+
*/
|
188 |
+
protected function _getImageData($outerDir)
|
189 |
+
{
|
190 |
+
$dirs = array_diff( scandir( $outerDir ), Array( '.', '..', '.svn' ) );
|
191 |
+
foreach ( $dirs as $d ) {
|
192 |
+
if ( is_dir($outerDir . DS . $d)) {
|
193 |
+
$this->_getImageData( $outerDir . DS . $d );
|
194 |
+
} else {
|
195 |
+
if (!$this->_isValidImage($d)) {
|
196 |
+
throw new Exception();
|
197 |
+
}
|
198 |
+
|
199 |
+
$this->_files[] = array(
|
200 |
+
'configPath' => $this->_getConfigPath($d),
|
201 |
+
'sourcePath' => $this->_getSourcePath($outerDir),
|
202 |
+
'filename' => $d,
|
203 |
+
'destinationPath' => $this->getDestinationPath($outerDir),
|
204 |
+
'uploadurl' => $this->_getUploadUrl($d),
|
205 |
+
'scope' => $this->_getScope($outerDir),
|
206 |
+
'scopeId' => $this->_getScopeId($outerDir),
|
207 |
+
);
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
return $this->_files;
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Creates a directory path under the destination upload url
|
216 |
+
*
|
217 |
+
* @param string $path
|
218 |
+
* @return boolean
|
219 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
220 |
+
*/
|
221 |
+
protected function _createDirectory($path)
|
222 |
+
{
|
223 |
+
$path = explode(DS, $path, -1);
|
224 |
+
$path = implode(DS, $path);
|
225 |
+
if (!mkdir($path, 0777, true)) {
|
226 |
+
return false;
|
227 |
+
}
|
228 |
+
return true;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Copies a file from a source path to a destination path
|
233 |
+
*
|
234 |
+
* @param string $src
|
235 |
+
* @param string $dest
|
236 |
+
* @return boolean
|
237 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
238 |
+
*/
|
239 |
+
protected function _copyFile($src,$dest)
|
240 |
+
{
|
241 |
+
if (!copy($src, $dest)) {
|
242 |
+
return false;
|
243 |
+
}
|
244 |
+
return true;
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Iterates through the array of images checks to see if file already exists, if not constructs the correct destination path,
|
249 |
+
* copies the image, and adds the relevane values in 'core_config_data' table
|
250 |
+
*
|
251 |
+
* @param array $images
|
252 |
+
* @return boolean
|
253 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
254 |
+
*/
|
255 |
+
protected function _uploadImage($images, $allowOverwrite)
|
256 |
+
{
|
257 |
+
foreach($images as $image){
|
258 |
+
$destinationPath = $this->_destDir . DS . $image['uploadurl'] . DS . $image['destinationPath'] . DS . $image['filename'];
|
259 |
+
$src = $this->_srcDir . DS . $image['sourcePath'] . DS . $image['filename'];
|
260 |
+
if (file_exists($destinationPath) && !$allowOverwrite) {
|
261 |
+
continue;
|
262 |
+
} else {
|
263 |
+
$this->_createDirectory($destinationPath);
|
264 |
+
if ($this->_copyFile($src,$destinationPath)) {
|
265 |
+
if ($image['scope']=='default') {
|
266 |
+
$config = Mage::getModel('ampersand_system/config')
|
267 |
+
->setDefault()
|
268 |
+
->setNode(array(
|
269 |
+
$image['configPath'] => $image['destinationPath'] . DS . $image['filename'],
|
270 |
+
))
|
271 |
+
->save();
|
272 |
+
} else if($image['scope']=='websites') {
|
273 |
+
$config = Mage::getModel('ampersand_system/config')
|
274 |
+
->setWebsite($image['scopeId'])
|
275 |
+
->setNode(array(
|
276 |
+
$image['configPath'] => $image['destinationPath'] . DS . $image['filename'],
|
277 |
+
))
|
278 |
+
->save();
|
279 |
+
} else if($image['scope']=='stores') {
|
280 |
+
$config = Mage::getModel('ampersand_system/config')
|
281 |
+
->setStore($image['scopeId'])
|
282 |
+
->setNode(array(
|
283 |
+
$image['configPath'] => $image['destinationPath'] . DS . $image['filename'],
|
284 |
+
))
|
285 |
+
->save();
|
286 |
+
}
|
287 |
+
}
|
288 |
+
}
|
289 |
+
}
|
290 |
+
return true;
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Calls the functions to retrieve image details of files to be uploaded and the passes these to the upload
|
295 |
+
* function
|
296 |
+
*
|
297 |
+
* @param boolean $allowOverwrite
|
298 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
299 |
+
*/
|
300 |
+
public function upload($allowOverwrite = false)
|
301 |
+
{
|
302 |
+
$images = $this->_getImageData( $this->_srcDir );
|
303 |
+
$this->_uploadImage($images, $allowOverwrite);
|
304 |
+
}
|
305 |
+
}
|
app/code/core/Ampersand/System/Model/Index.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Index
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Perform a full re-index.
|
6 |
+
*
|
7 |
+
* @return Ampersand_System_Model_Index
|
8 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
9 |
+
*/
|
10 |
+
public function reindexAll()
|
11 |
+
{
|
12 |
+
$processCollection = $this->_getIndexProcesses();
|
13 |
+
foreach ($processCollection as $_process) {
|
14 |
+
$_process->reindexEverything();
|
15 |
+
}
|
16 |
+
|
17 |
+
return $this;
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Retreive array of all index processes.
|
22 |
+
*
|
23 |
+
* @return array
|
24 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
25 |
+
*/
|
26 |
+
protected function _getIndexProcesses()
|
27 |
+
{
|
28 |
+
$processes = array();
|
29 |
+
$collection = $this->_getModel()->getProcessesCollection();
|
30 |
+
foreach ($collection as $_process) {
|
31 |
+
$processes[] = $_process;
|
32 |
+
}
|
33 |
+
|
34 |
+
return $processes;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Retreive the indexer model.
|
39 |
+
*
|
40 |
+
* @return Mage_Index_Model_Indexer
|
41 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
42 |
+
*/
|
43 |
+
protected function _getModel()
|
44 |
+
{
|
45 |
+
return Mage::getSingleton('index/indexer');
|
46 |
+
}
|
47 |
+
}
|
app/code/core/Ampersand/System/Model/Shipping.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Shipping
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Update Tablerate shipping options from a CSV file
|
6 |
+
*
|
7 |
+
* @param type $moduleName Name of the module which contains the data file (Namespace_Module)
|
8 |
+
* @param type $websiteId Website ID or code
|
9 |
+
* @param type $condition Tablerate shipping condition. package_weight, package_value or package_qty
|
10 |
+
* @param type $filepath Full path to the CSV file of table rates to import
|
11 |
+
* @param string $shippingMethod Name of the module and resource model that define the shipping method, modulename/resource_path
|
12 |
+
* @param string $fieldId configuable file path that resoucr model handles, this should correspond with $shippingMethod
|
13 |
+
* @return Ampersand_System_Model_Shipping
|
14 |
+
* @author Stephen O'Shea <stephen.o'shea@ampersandcommerce.com>
|
15 |
+
*/
|
16 |
+
public function updateTablerate($moduleName, $websiteId, $condition, $filepath,
|
17 |
+
$shippingMethod='shipping/carrier_tablerate',$fieldId='tablerate')
|
18 |
+
{
|
19 |
+
$filepath = Mage::getModuleDir('', $moduleName) . DS. 'data' . DS . $filepath;
|
20 |
+
|
21 |
+
if (isset($_FILES['groups']['tmp_name'][$fieldId]['fields']['import']['value'])) {
|
22 |
+
$origFilesTablerateImportValue = $_FILES['groups']['tmp_name'][$fieldId]['fields']['import']['value'];
|
23 |
+
}
|
24 |
+
|
25 |
+
$_FILES['groups']['tmp_name'][$fieldId]['fields']['import']['value'] = $filepath;
|
26 |
+
|
27 |
+
$importParams = array(
|
28 |
+
'groups' => array(
|
29 |
+
$fieldId => array(
|
30 |
+
'fields' => array(
|
31 |
+
'condition_name' => array(
|
32 |
+
'value' => $condition,
|
33 |
+
),
|
34 |
+
),
|
35 |
+
),
|
36 |
+
),
|
37 |
+
'scope_id' => $websiteId,
|
38 |
+
);
|
39 |
+
|
40 |
+
$importObject = new Varien_Object($importParams);
|
41 |
+
|
42 |
+
Mage::helper('ampersand_system/store')->reinitStores();
|
43 |
+
Mage::getResourceModel($shippingMethod)
|
44 |
+
->uploadAndImport($importObject);
|
45 |
+
|
46 |
+
if (isset($origFilesTablerateImportValue)) {
|
47 |
+
$_FILES['groups']['tmp_name'][$fieldId]['fields']['import']['value'] = $origFilesTablerateImportValue;
|
48 |
+
}
|
49 |
+
|
50 |
+
return $this;
|
51 |
+
}
|
52 |
+
}
|
app/code/core/Ampersand/System/Model/Store.php
ADDED
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Store extends Mage_Core_Model_Store
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Shortname of this class
|
6 |
+
*
|
7 |
+
* @var string $_modelName
|
8 |
+
*/
|
9 |
+
protected $_modelName = 'core/store';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Field to load by when checking if already exists
|
13 |
+
*
|
14 |
+
* @var string $_loadField
|
15 |
+
*/
|
16 |
+
protected $_loadField = 'code';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Database column name of the id field
|
20 |
+
*
|
21 |
+
* @var string $_idField
|
22 |
+
*/
|
23 |
+
protected $_idField = 'store_id';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Required fields for saving this object.
|
27 |
+
* If a default value is allowed then provide a non-null value
|
28 |
+
*
|
29 |
+
* @var array $_requiredFields
|
30 |
+
*/
|
31 |
+
protected $_requiredFields = array(
|
32 |
+
'name' => null,
|
33 |
+
'code' => null,
|
34 |
+
'group_id' => null,
|
35 |
+
'website_id' => null,
|
36 |
+
'is_active' => '0',
|
37 |
+
'is_default' => '0',
|
38 |
+
'sort_order' => '0',
|
39 |
+
);
|
40 |
+
|
41 |
+
/**
|
42 |
+
* If these methods are called with setXxx, addXxx, setData(xxx, xxx) etc.
|
43 |
+
* setDataUsingMethod() will always be forced.
|
44 |
+
*
|
45 |
+
* @var array $_forceSetDataUsingMethod
|
46 |
+
*/
|
47 |
+
protected $_forceSetDataUsingMethod = array(
|
48 |
+
'id',
|
49 |
+
'website_id',
|
50 |
+
);
|
51 |
+
|
52 |
+
/**
|
53 |
+
* By setting the ID of a Store, we attempt to load it. If we are unable
|
54 |
+
* to load the Store, unset the id field as we want a new Sroup to be created.
|
55 |
+
*
|
56 |
+
* @param type $id int
|
57 |
+
* @return Ampersand_System_Model_Store
|
58 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
59 |
+
*/
|
60 |
+
public function setId($id)
|
61 |
+
{
|
62 |
+
parent::setData($this->_idField, $id);
|
63 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_idField);
|
64 |
+
|
65 |
+
if (!$this->getIsObjectLoaded()) {
|
66 |
+
parent::unsData($this->_idField);
|
67 |
+
}
|
68 |
+
|
69 |
+
return $this;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* If not already set, retrieve the default website/group/store
|
74 |
+
* combination and return the group id for that store.
|
75 |
+
*
|
76 |
+
* @return int
|
77 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
78 |
+
*/
|
79 |
+
public function getGroupId()
|
80 |
+
{
|
81 |
+
if (!$groupId = $this->getData('group_id')) {
|
82 |
+
if ($defaultStoreView = Mage::helper('ampersand_system/store')->getDefaultStoreView()) {
|
83 |
+
$groupId = $defaultStoreView->getGroupId();
|
84 |
+
}
|
85 |
+
$this->setGroupId($groupId);
|
86 |
+
|
87 |
+
if (!$websiteId = parent::getData('website_id')) {
|
88 |
+
$group = Mage::app()->getGroup($groupId);
|
89 |
+
parent::setData('website_id', $group->getWebsiteId());
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
return $groupId;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Set the website id to associate this Group with
|
98 |
+
*
|
99 |
+
* @param mixed $website Varien_Object, website id or website code
|
100 |
+
* @return Ampersand_System_Model_Store
|
101 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
102 |
+
*/
|
103 |
+
public function setWebsiteId($website)
|
104 |
+
{
|
105 |
+
if (!is_object($website)) {
|
106 |
+
$website = Mage::app()->getWebsite($website);
|
107 |
+
}
|
108 |
+
|
109 |
+
parent::setData('website_id', $website->getId());
|
110 |
+
|
111 |
+
if ((!$groupId = parent::getData('group_id')) || (!in_array($groupId, $website->getGroupIds()))) {
|
112 |
+
parent::setData('group_id', $website->getDefaultGroup()->getId());
|
113 |
+
}
|
114 |
+
|
115 |
+
return $this;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* If not already set, retrieve the group for this store and
|
120 |
+
* return the website id for that group.
|
121 |
+
*
|
122 |
+
* @return int
|
123 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
124 |
+
*/
|
125 |
+
public function getWebsiteId()
|
126 |
+
{
|
127 |
+
if (!$websiteId = $this->getData('website_id')) {
|
128 |
+
$websiteId = $this->getGroup()->getWebsiteId();
|
129 |
+
parent::setData('website_id', $websiteId);
|
130 |
+
}
|
131 |
+
|
132 |
+
return $websiteId;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
137 |
+
*
|
138 |
+
* @param mixed $key
|
139 |
+
* @param mixed $value
|
140 |
+
* @return Ampersand_System_Model_Store
|
141 |
+
*/
|
142 |
+
public function setData($key, $value = null)
|
143 |
+
{
|
144 |
+
if (is_array($key)) {
|
145 |
+
foreach ($key as $_key => $_value) {
|
146 |
+
$this->_setDataUsingMethod($_key, $_value);
|
147 |
+
}
|
148 |
+
} else {
|
149 |
+
$this->_setDataUsingMethod($key, $value);
|
150 |
+
}
|
151 |
+
|
152 |
+
return $this;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
157 |
+
*
|
158 |
+
* @param string $key
|
159 |
+
* @param mixed $value
|
160 |
+
* @return Ampersand_System_Model_Store
|
161 |
+
*/
|
162 |
+
protected function _setDataUsingMethod($key, $value = null)
|
163 |
+
{
|
164 |
+
if (in_array($key, $this->_forceSetDataUsingMethod)) {
|
165 |
+
$this->setDataUsingMethod($key, $value);
|
166 |
+
} else {
|
167 |
+
parent::setData($key, $value);
|
168 |
+
}
|
169 |
+
|
170 |
+
return $this;
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Load if exists, validate and save the object
|
175 |
+
*
|
176 |
+
* @return Ampersand_System_Model_Store
|
177 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
178 |
+
*/
|
179 |
+
protected function _beforeSave()
|
180 |
+
{
|
181 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_loadField);
|
182 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
183 |
+
|
184 |
+
return parent::_beforeSave();
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Reinitstores required so new object available from Mage::app().
|
189 |
+
*
|
190 |
+
* @return Ampersand_System_Model_Store
|
191 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
192 |
+
*/
|
193 |
+
protected function _afterSave()
|
194 |
+
{
|
195 |
+
parent::_afterSave();
|
196 |
+
|
197 |
+
if ($this->isObjectNew()) {
|
198 |
+
Mage::app()->reinitStores();
|
199 |
+
}
|
200 |
+
|
201 |
+
return $this;
|
202 |
+
}
|
203 |
+
}
|
app/code/core/Ampersand/System/Model/TaxRate.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_TaxRate extends Mage_Tax_Model_Calculation_Rate
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Shortname of this class
|
6 |
+
*
|
7 |
+
* @var string $_modelName
|
8 |
+
*/
|
9 |
+
protected $_modelName = 'tax/calculation_rate';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Field to load by when checking if already exists
|
13 |
+
*
|
14 |
+
* @var string $_loadField
|
15 |
+
*/
|
16 |
+
protected $_loadField = 'code';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Database column name of the id field
|
20 |
+
*
|
21 |
+
* @var string $_idField
|
22 |
+
*/
|
23 |
+
protected $_idField = 'tax_calculation_rate_id';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Required fields for saving this object.
|
27 |
+
* If a default value is allowed then provide a non-null value
|
28 |
+
*
|
29 |
+
* @var array $_requiredFields
|
30 |
+
*/
|
31 |
+
protected $_requiredFields = array(
|
32 |
+
'code' => null,
|
33 |
+
'tax_country_id' => null,
|
34 |
+
'rate' => 0,
|
35 |
+
);
|
36 |
+
|
37 |
+
/**
|
38 |
+
* If these methods are called with setXxx, addXxx, setData(xxx, xxx) etc.
|
39 |
+
* setDataUsingMethod() will always be forced.
|
40 |
+
*
|
41 |
+
* @var array $_forceSetDataUsingMethod
|
42 |
+
*/
|
43 |
+
protected $_forceSetDataUsingMethod = array(
|
44 |
+
);
|
45 |
+
|
46 |
+
/**
|
47 |
+
* By setting the ID of a Store, we attempt to load it. If we are unable
|
48 |
+
* to load the Store, unset the id field as we want a new Sroup to be created.
|
49 |
+
*
|
50 |
+
* @param type $id int
|
51 |
+
* @return Ampersand_System_Model_Store
|
52 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
53 |
+
*/
|
54 |
+
public function setId($id)
|
55 |
+
{
|
56 |
+
parent::setData($this->_idField, $id);
|
57 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_idField);
|
58 |
+
|
59 |
+
if (!$this->getIsObjectLoaded()) {
|
60 |
+
parent::unsData($this->_idField);
|
61 |
+
}
|
62 |
+
return $this;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
67 |
+
*
|
68 |
+
* @param mixed $key
|
69 |
+
* @param mixed $value
|
70 |
+
* @return Ampersand_System_Model_Store
|
71 |
+
*/
|
72 |
+
public function setData($key, $value = null)
|
73 |
+
{
|
74 |
+
if (is_array($key)) {
|
75 |
+
foreach ($key as $_key => $_value) {
|
76 |
+
$this->_setDataUsingMethod($_key, $_value);
|
77 |
+
}
|
78 |
+
} else {
|
79 |
+
$this->_setDataUsingMethod($key, $value);
|
80 |
+
}
|
81 |
+
|
82 |
+
return $this;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
87 |
+
*
|
88 |
+
* @param string $key
|
89 |
+
* @param mixed $value
|
90 |
+
* @return Ampersand_System_Model_Store
|
91 |
+
*/
|
92 |
+
protected function _setDataUsingMethod($key, $value = null)
|
93 |
+
{
|
94 |
+
if (in_array($key, $this->_forceSetDataUsingMethod)) {
|
95 |
+
$this->setDataUsingMethod($key, $value);
|
96 |
+
} else {
|
97 |
+
parent::setData($key, $value);
|
98 |
+
}
|
99 |
+
|
100 |
+
return $this;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Load if exists, validate and save the object
|
105 |
+
*
|
106 |
+
* @return Ampersand_System_Model_Store
|
107 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
108 |
+
*/
|
109 |
+
protected function _beforeSave()
|
110 |
+
{
|
111 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_loadField);
|
112 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
113 |
+
|
114 |
+
return parent::_beforeSave();
|
115 |
+
}
|
116 |
+
|
117 |
+
//
|
118 |
+
// public function addNewTaxRate()
|
119 |
+
// {
|
120 |
+
// $taxModel = Mage::getModel('');
|
121 |
+
// $taxRate = $taxModel->loadByCode('UK');
|
122 |
+
// $taxRate->setData('code', 'UK');
|
123 |
+
// $taxRate->setData('tax_country_id', 'GB');
|
124 |
+
// $taxRate->setData('zip_is_range', false);
|
125 |
+
// $taxRate->setData('rate', 20);
|
126 |
+
// $taxRate->save();
|
127 |
+
// }
|
128 |
+
|
129 |
+
}
|
app/code/core/Ampersand/System/Model/TaxRule.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Ampersand_System_Model_TaxRule extends Mage_Tax_Model_Calculation_Rule
|
4 |
+
{
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Shortname of this class
|
8 |
+
*
|
9 |
+
* @var string $_modelName
|
10 |
+
*/
|
11 |
+
protected $_modelName = 'tax/calculation_rule';
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Field to load by when checking if already exists
|
15 |
+
*
|
16 |
+
* @var string $_loadField
|
17 |
+
*/
|
18 |
+
protected $_loadField = 'code';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Database column name of the id field
|
22 |
+
*
|
23 |
+
* @var string $_idField
|
24 |
+
*/
|
25 |
+
protected $_idField = 'tax_calculation_rule_id';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Required fields for saving this object.
|
29 |
+
* If a default value is allowed then provide a non-null value
|
30 |
+
*
|
31 |
+
* @var array $_requiredFields
|
32 |
+
*/
|
33 |
+
protected $_requiredFields = array(
|
34 |
+
'code' => null,
|
35 |
+
'priority' => 0,
|
36 |
+
'position' => 0,
|
37 |
+
'tax_rate' => null,
|
38 |
+
'tax_product_class' =>null,
|
39 |
+
'tax_customer_class' => null,
|
40 |
+
);
|
41 |
+
|
42 |
+
/**
|
43 |
+
* If these methods are called with setXxx, addXxx, setData(xxx, xxx) etc.
|
44 |
+
* setDataUsingMethod() will always be forced.
|
45 |
+
*
|
46 |
+
* @var array $_forceSetDataUsingMethod
|
47 |
+
*/
|
48 |
+
protected $_forceSetDataUsingMethod = array(
|
49 |
+
);
|
50 |
+
|
51 |
+
/**
|
52 |
+
* By setting the ID of a Store, we attempt to load it. If we are unable
|
53 |
+
* to load the Store, unset the id field as we want a new Sroup to be created.
|
54 |
+
*
|
55 |
+
* @param type $id int
|
56 |
+
* @return Ampersand_System_Model_Store
|
57 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
58 |
+
*/
|
59 |
+
public function setId($id)
|
60 |
+
{
|
61 |
+
parent::setData($this->_idField, $id);
|
62 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_idField);
|
63 |
+
|
64 |
+
if (!$this->getIsObjectLoaded()) {
|
65 |
+
parent::unsData($this->_idField);
|
66 |
+
}
|
67 |
+
return $this;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
72 |
+
*
|
73 |
+
* @param mixed $key
|
74 |
+
* @param mixed $value
|
75 |
+
* @return Ampersand_System_Model_Store
|
76 |
+
*/
|
77 |
+
public function setData($key, $value = null)
|
78 |
+
{
|
79 |
+
if (is_array($key)) {
|
80 |
+
foreach ($key as $_key => $_value) {
|
81 |
+
$this->_setDataUsingMethod($_key, $_value);
|
82 |
+
}
|
83 |
+
} else {
|
84 |
+
$this->_setDataUsingMethod($key, $value);
|
85 |
+
}
|
86 |
+
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
92 |
+
*
|
93 |
+
* @param string $key
|
94 |
+
* @param mixed $value
|
95 |
+
* @return Ampersand_System_Model_Store
|
96 |
+
*/
|
97 |
+
protected function _setDataUsingMethod($key, $value = null)
|
98 |
+
{
|
99 |
+
if (in_array($key, $this->_forceSetDataUsingMethod)) {
|
100 |
+
$this->setDataUsingMethod($key, $value);
|
101 |
+
} else {
|
102 |
+
parent::setData($key, $value);
|
103 |
+
}
|
104 |
+
|
105 |
+
return $this;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Load if exists, validate and save the object
|
110 |
+
*
|
111 |
+
* @return Ampersand_System_Model_Store
|
112 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
113 |
+
*/
|
114 |
+
protected function _beforeSave()
|
115 |
+
{
|
116 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_loadField);
|
117 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
118 |
+
return parent::_beforeSave();
|
119 |
+
}
|
120 |
+
}
|
app/code/core/Ampersand/System/Model/Website.php
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_System_Model_Website extends Mage_Core_Model_Website
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Shortname of this class
|
6 |
+
*
|
7 |
+
* @var string $_modelName
|
8 |
+
*/
|
9 |
+
protected $_modelName = 'core/website';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Field to load by when checking if already exists
|
13 |
+
*
|
14 |
+
* @var string $_loadField
|
15 |
+
*/
|
16 |
+
protected $_loadField = 'code';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Database column name of the id field
|
20 |
+
*
|
21 |
+
* @var string $_idField
|
22 |
+
*/
|
23 |
+
protected $_idField = 'website_id';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Required fields for saving this object.
|
27 |
+
* If a default value is allowed then provide a non-null value
|
28 |
+
*
|
29 |
+
* @var array $_requiredFields
|
30 |
+
*/
|
31 |
+
protected $_requiredFields = array(
|
32 |
+
'name' => null,
|
33 |
+
'code' => null,
|
34 |
+
'sort_order' => '0',
|
35 |
+
);
|
36 |
+
|
37 |
+
/**
|
38 |
+
* If these methods are called with setXxx, addXxx, setData(xxx, xxx) etc.
|
39 |
+
* setDataUsingMethod() will always be forced.
|
40 |
+
*
|
41 |
+
* @var array $_forceSetDataUsingMethod
|
42 |
+
*/
|
43 |
+
protected $_forceSetDataUsingMethod = array(
|
44 |
+
'id',
|
45 |
+
);
|
46 |
+
|
47 |
+
/**
|
48 |
+
* By setting the ID of a Website, we attempt to load it. If we are unable
|
49 |
+
* to load the Website, unset the id field as we want a new Website to be created.
|
50 |
+
*
|
51 |
+
* @param type $id int
|
52 |
+
* @return Ampersand_System_Model_Website
|
53 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
54 |
+
*/
|
55 |
+
public function setId($id)
|
56 |
+
{
|
57 |
+
parent::setData($this->_idField, $id);
|
58 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_idField);
|
59 |
+
|
60 |
+
if (!$this->getIsObjectLoaded()) {
|
61 |
+
parent::unsData($this->_idField);
|
62 |
+
}
|
63 |
+
|
64 |
+
return $this;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
69 |
+
*
|
70 |
+
* @param mixed $key
|
71 |
+
* @param mixed $value
|
72 |
+
* @return Ampersand_System_Model_Website
|
73 |
+
*/
|
74 |
+
public function setData($key, $value = null)
|
75 |
+
{
|
76 |
+
if (is_array($key)) {
|
77 |
+
foreach ($key as $_key => $_value) {
|
78 |
+
$this->_setDataUsingMethod($_key, $_value);
|
79 |
+
}
|
80 |
+
} else {
|
81 |
+
$this->_setDataUsingMethod($key, $value);
|
82 |
+
}
|
83 |
+
|
84 |
+
return $this;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Ensure we force the method use, rather than setData, where appropriate
|
89 |
+
*
|
90 |
+
* @param string $key
|
91 |
+
* @param mixed $value
|
92 |
+
* @return Ampersand_System_Model_Website
|
93 |
+
*/
|
94 |
+
protected function _setDataUsingMethod($key, $value = null)
|
95 |
+
{
|
96 |
+
if (in_array($key, $this->_forceSetDataUsingMethod)) {
|
97 |
+
$this->setDataUsingMethod($key, $value);
|
98 |
+
} else {
|
99 |
+
parent::setData($key, $value);
|
100 |
+
}
|
101 |
+
|
102 |
+
return $this;
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Load if exists, validate and save the object
|
107 |
+
*
|
108 |
+
* @return Ampersand_System_Model_Website
|
109 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
110 |
+
*/
|
111 |
+
protected function _beforeSave()
|
112 |
+
{
|
113 |
+
Mage::helper('ampersand_system')->loadIfExists($this, $this->_modelName, $this->_loadField);
|
114 |
+
Mage::helper('ampersand_system')->validate($this, $this->_requiredFields);
|
115 |
+
|
116 |
+
return parent::_beforeSave();
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Reinitstores required so new object available from Mage::app().
|
121 |
+
*
|
122 |
+
* @return Ampersand_System_Model_Website
|
123 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
124 |
+
*/
|
125 |
+
protected function _afterSave()
|
126 |
+
{
|
127 |
+
parent::_afterSave();
|
128 |
+
|
129 |
+
if ($this->isObjectNew()) {
|
130 |
+
Mage::app()->reinitStores();
|
131 |
+
}
|
132 |
+
|
133 |
+
return $this;
|
134 |
+
}
|
135 |
+
}
|
app/code/core/Ampersand/System/etc/config.xml
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Ampersand_System>
|
5 |
+
<version>0.0.1</version>
|
6 |
+
</Ampersand_System>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<helpers>
|
10 |
+
<ampersand_system>
|
11 |
+
<class>Ampersand_System_Helper</class>
|
12 |
+
</ampersand_system>
|
13 |
+
</helpers>
|
14 |
+
<models>
|
15 |
+
<ampersand_system>
|
16 |
+
<class>Ampersand_System_Model</class>
|
17 |
+
</ampersand_system>
|
18 |
+
</models>
|
19 |
+
</global>
|
20 |
+
<phpunit>
|
21 |
+
<suite>
|
22 |
+
<modules>
|
23 |
+
<Ampersand_System/>
|
24 |
+
</modules>
|
25 |
+
</suite>
|
26 |
+
</phpunit>
|
27 |
+
</config>
|
app/design/adminhtml/base/default/template/ampersand_adminhtml/catalog/form/renderer/element/use-config.phtml
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php $_readOnly = $this->getElement()->getReadonly() ?>
|
2 |
+
|
3 |
+
<input type="checkbox"
|
4 |
+
id="<?php echo $this->getUseConfigAttributeCode() ?>"
|
5 |
+
name="<?php echo $this->getUseConfigInputName() ?>"
|
6 |
+
value="1"
|
7 |
+
<?php echo $this->getShouldUseConfig() ? 'checked="checked"' : '' ?>
|
8 |
+
onclick="toggleValueElements(this, this.parentNode);toggleHiddenElement(this)"
|
9 |
+
class="checkbox"
|
10 |
+
<?php echo $_readOnly ?>
|
11 |
+
/>
|
12 |
+
<label for="<?php echo $this->getUseConfigAttributeCode() ?>" class="normal">
|
13 |
+
<?php echo Mage::helper('catalog')->__('Use Config Settings') ?>
|
14 |
+
</label>
|
15 |
+
|
16 |
+
<input type="hidden"
|
17 |
+
name="<?php echo $this->getUseConfigHiddenInputName() ?>"
|
18 |
+
value="<?php echo $this->getUseConfigHiddenInputValue() ?>"
|
19 |
+
/>
|
20 |
+
|
21 |
+
<?php if (!$_readOnly): ?>
|
22 |
+
<script type="text/javascript">
|
23 |
+
//<![CDATA[
|
24 |
+
Event.observe(window, 'load', function() {
|
25 |
+
var $useDefaultElement = $('<?php echo $this->getElement()->getHtmlId() ?>_default');
|
26 |
+
if ($useDefaultElement && $useDefaultElement.checked) {
|
27 |
+
toggleValueElements($useDefaultElement, $useDefaultElement.parentNode.parentNode);
|
28 |
+
} else {
|
29 |
+
var $useConfigElement = $('<?php echo $this->getUseConfigAttributeCode() ?>');
|
30 |
+
toggleValueElements($useConfigElement, $useConfigElement.parentNode);
|
31 |
+
}
|
32 |
+
});
|
33 |
+
//]]>
|
34 |
+
</script>
|
35 |
+
<?php endif ?>
|
app/design/adminhtml/base/default/template/ampersand_adminhtml/system/config-form-array-simple.phtml
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$_htmlId = $this->getHtmlId() ? $this->getHtmlId() : '_' . uniqid();
|
3 |
+
|
4 |
+
$_colspan = 2;
|
5 |
+
if (!$this->_addAfter) {
|
6 |
+
$_colspan -= 1;
|
7 |
+
}
|
8 |
+
$_colspan = $_colspan > 1 ? 'colspan="' . $_colspan . '"' : '';
|
9 |
+
?>
|
10 |
+
|
11 |
+
<div class="grid" id="grid<?php echo $_htmlId ?>">
|
12 |
+
<table cellpadding="0" cellspacing="0" class="border">
|
13 |
+
<tbody>
|
14 |
+
|
15 |
+
<tr class="headings" id="headings<?php echo $_htmlId ?>">
|
16 |
+
<?php foreach ($this->_columns as $columnName => $column):?>
|
17 |
+
<th><?php echo $column['label'] ?></th>
|
18 |
+
<?php endforeach;?>
|
19 |
+
</tr>
|
20 |
+
|
21 |
+
</tbody>
|
22 |
+
</table>
|
23 |
+
<input type="hidden" name="<?php echo $this->getElement()->getName() ?>[__empty]" value="" />
|
24 |
+
</div>
|
25 |
+
|
26 |
+
<script type="text/javascript">
|
27 |
+
//<![CDATA[
|
28 |
+
// create row creator
|
29 |
+
var arrayRow<?php echo $_htmlId ?> = {
|
30 |
+
// define row prototypeJS template
|
31 |
+
template : new Template(
|
32 |
+
'<tr id="#{_id}">'
|
33 |
+
<?php foreach ($this->_columns as $columnName => $column):?>
|
34 |
+
+'<td>'
|
35 |
+
+'<?php echo $this->_renderCellTemplate($columnName)?>'
|
36 |
+
+'<\/td>'
|
37 |
+
<?php endforeach;?>
|
38 |
+
+'<\/tr>'
|
39 |
+
),
|
40 |
+
|
41 |
+
rowsCount : 0,
|
42 |
+
|
43 |
+
add : function(templateData, insertAfterId)
|
44 |
+
{
|
45 |
+
// generate default template data
|
46 |
+
if ('' == templateData) {
|
47 |
+
var d = new Date();
|
48 |
+
var templateData = {
|
49 |
+
<?php foreach ($this->_columns as $columnName => $column):?>
|
50 |
+
<?php echo $columnName ?> : '',
|
51 |
+
<?php endforeach;?>
|
52 |
+
_id : '_' + d.getTime() + '_' + d.getMilliseconds()
|
53 |
+
};
|
54 |
+
}
|
55 |
+
|
56 |
+
Element.insert($(insertAfterId), {after: this.template.evaluate(templateData)});
|
57 |
+
|
58 |
+
this.rowsCount += 1;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
// add existing rows
|
63 |
+
<?php
|
64 |
+
$_addAfterId = "headings{$_htmlId}";
|
65 |
+
foreach ($this->getArrayRows() as $_rowId => $_row) {
|
66 |
+
echo "arrayRow{$_htmlId}.add(" . $_row->toJson() . ", '{$_addAfterId}');\n";
|
67 |
+
$_addAfterId = $_rowId;
|
68 |
+
}
|
69 |
+
?>
|
70 |
+
|
71 |
+
// toggle the grid, if element is disabled (depending on scope)
|
72 |
+
<?php if ($this->getElement()->getDisabled()):?>
|
73 |
+
toggleValueElements({checked:true}, $('grid<?php echo $_htmlId ?>').parentNode);
|
74 |
+
<?php endif;?>
|
75 |
+
//]]>
|
76 |
+
</script>
|
app/etc/modules/Ampersand_Core.xml
CHANGED
@@ -8,6 +8,15 @@
|
|
8 |
<Ampersand_Core/>
|
9 |
</depends>
|
10 |
</Ampersand_Adminhtml>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
<Ampersand_Catalog>
|
13 |
<active>true</active>
|
@@ -21,5 +30,20 @@
|
|
21 |
<active>true</active>
|
22 |
<codePool>core</codePool>
|
23 |
</Ampersand_Core>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
</modules>
|
25 |
</config>
|
8 |
<Ampersand_Core/>
|
9 |
</depends>
|
10 |
</Ampersand_Adminhtml>
|
11 |
+
|
12 |
+
<Ampersand_Api>
|
13 |
+
<active>true</active>
|
14 |
+
<codePool>core</codePool>
|
15 |
+
<depends>
|
16 |
+
<Ampersand_Core/>
|
17 |
+
<Ampersand_Sales/>
|
18 |
+
</depends>
|
19 |
+
</Ampersand_Api>
|
20 |
|
21 |
<Ampersand_Catalog>
|
22 |
<active>true</active>
|
30 |
<active>true</active>
|
31 |
<codePool>core</codePool>
|
32 |
</Ampersand_Core>
|
33 |
+
|
34 |
+
<Ampersand_Fakepay>
|
35 |
+
<active>true</active>
|
36 |
+
<codePool>core</codePool>
|
37 |
+
</Ampersand_Fakepay>
|
38 |
+
|
39 |
+
<Ampersand_Sales>
|
40 |
+
<active>true</active>
|
41 |
+
<codePool>core</codePool>
|
42 |
+
</Ampersand_Sales>
|
43 |
+
|
44 |
+
<Ampersand_System>
|
45 |
+
<active>true</active>
|
46 |
+
<codePool>core</codePool>
|
47 |
+
</Ampersand_System>
|
48 |
</modules>
|
49 |
</config>
|
lib/Ampersand.php
CHANGED
@@ -1,57 +1,126 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
final class Ampersand
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Property for storing stopwatch timings
|
6 |
+
*
|
7 |
+
* @var double $_stopwatchClock
|
8 |
+
*/
|
9 |
+
private static $_stopwatchClock = null;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Initialize Magento for scripts.
|
13 |
+
*
|
14 |
+
* @param string $path
|
15 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
16 |
+
*/
|
17 |
+
public static function initMage($path = '.')
|
18 |
+
{
|
19 |
+
require_once($path . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'Mage.php');
|
20 |
+
Mage::app();
|
21 |
+
umask(0);
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Retrieve stack trace from current location
|
26 |
+
*
|
27 |
+
* @param bool $die OPTIONAL Die with trace. False to return trace.
|
28 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
29 |
+
*/
|
30 |
+
public static function trace($die = true)
|
31 |
+
{
|
32 |
+
$e = new Exception();
|
33 |
+
$trace = $e->getTraceAsString();
|
34 |
+
|
35 |
+
return $die ? die($trace) : $trace;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Toggle error reporting
|
40 |
+
*
|
41 |
+
* @param bool $enabled OPTIONAL Enable error reporting. False to disable.
|
42 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
43 |
+
*/
|
44 |
+
public static function errorReporting($enabled = true)
|
45 |
+
{
|
46 |
+
if ($enabled) {
|
47 |
+
error_reporting(E_ALL | E_STRICT);
|
48 |
+
ini_set('display_errors', '1');
|
49 |
+
} else {
|
50 |
+
error_reporting(0);
|
51 |
+
ini_set('display_errors', '0');
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Mage::log() with class, method and line number information
|
57 |
+
*
|
58 |
+
* @param string $message OPTIONAL Log message
|
59 |
+
* @param string $filename OPTIONAL Log filename
|
60 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
61 |
+
*/
|
62 |
+
public static function log($message = null, $filename = 'system.log')
|
63 |
+
{
|
64 |
+
$backtrace = debug_backtrace();
|
65 |
+
$className = $backtrace[1]['class'];
|
66 |
+
$methodName = $backtrace[1]['function'];
|
67 |
+
$lineNumber = $backtrace[0]['line'];
|
68 |
+
Mage::log($className . '::' . $methodName . ' (line ' . $lineNumber . ') ' . $message, null, $filename);
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Return the contents of var_dump rather than direct output.
|
73 |
+
*
|
74 |
+
* @param mixed $content
|
75 |
+
* @return string
|
76 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
77 |
+
*/
|
78 |
+
public static function varDump($content)
|
79 |
+
{
|
80 |
+
ob_start();
|
81 |
+
var_dump($content);
|
82 |
+
|
83 |
+
return ob_get_clean();
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Return the time elapsed between each call of this method.
|
88 |
+
*
|
89 |
+
* @param string $message
|
90 |
+
* @return string
|
91 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
92 |
+
*/
|
93 |
+
public static function stopwatch($message = null, $convertNegligable = true)
|
94 |
+
{
|
95 |
+
$microtime = microtime(true);
|
96 |
+
if (!self::$_stopwatchClock) {
|
97 |
+
self::$_stopwatchClock = $microtime;
|
98 |
+
return;
|
99 |
+
}
|
100 |
+
|
101 |
+
$difference = $microtime - self::$_stopwatchClock;
|
102 |
+
|
103 |
+
// these numbers are hard to interpret so sometimes best to ignore them
|
104 |
+
if ($convertNegligable && strpos($difference, 'E-') !== FALSE) {
|
105 |
+
$difference = 'negligable';
|
106 |
+
} else {
|
107 |
+
$difference .= ' seconds';
|
108 |
+
}
|
109 |
+
|
110 |
+
self::$_stopwatchClock = $microtime;
|
111 |
+
|
112 |
+
return !is_null($message) ? "{$difference} :: {$message}" : null;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Reset any Ampersand-related properties
|
117 |
+
*
|
118 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
119 |
+
*/
|
120 |
+
public static function reset()
|
121 |
+
{
|
122 |
+
self::$_stopwatchClock = null;
|
123 |
+
|
124 |
+
Ampersand_Registry::reset();
|
125 |
+
}
|
126 |
+
}
|
lib/Ampersand/BinPack.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack
|
3 |
+
{
|
4 |
+
/** @var null|Ampersand_BinPack_Input */
|
5 |
+
protected $_input;
|
6 |
+
/** @var null|Ampersand_BinPack_Packer_PackerInterface */
|
7 |
+
protected $_packer;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @return Ampersand_BinPack_Input
|
11 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
12 |
+
*/
|
13 |
+
public function getInput()
|
14 |
+
{
|
15 |
+
if (is_null($this->_input)) {
|
16 |
+
$this->_input = new Ampersand_BinPack_Input();
|
17 |
+
}
|
18 |
+
|
19 |
+
return $this->_input;
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param string|Ampersand_BinPack_Packer_PackerInterface $packer
|
24 |
+
* @return Ampersand_BinPack
|
25 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
26 |
+
*/
|
27 |
+
public function setPacker($packer)
|
28 |
+
{
|
29 |
+
if (is_string($packer)) {
|
30 |
+
$packerClass = 'Ampersand_BinPack_Packer_' . ucfirst($packer);
|
31 |
+
|
32 |
+
if (!class_exists($packerClass)) {
|
33 |
+
throw new Exception("Unknown packer '$packer'.");
|
34 |
+
}
|
35 |
+
|
36 |
+
$packer = new $packerClass;
|
37 |
+
}
|
38 |
+
|
39 |
+
if (!$packer instanceof Ampersand_BinPack_Packer_PackerInterface) {
|
40 |
+
throw new Exception('Packer must be an instance of Ampersand_BinPack_Packer_PackerInterface.');
|
41 |
+
}
|
42 |
+
|
43 |
+
$this->_packer = $packer;
|
44 |
+
|
45 |
+
return $this;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @param string|Ampersand_BinPack_Dimension_DimensionInterface $identifier
|
50 |
+
* @param int|float $binVolume OPTIONAL
|
51 |
+
* @return Ampersand_BinPack
|
52 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
53 |
+
*/
|
54 |
+
public function addDimension($identifier, $binVolume = null)
|
55 |
+
{
|
56 |
+
$this->getInput()->addDimension($identifier, $binVolume);
|
57 |
+
|
58 |
+
return $this;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @param string $identifier
|
63 |
+
* @param array|int|float $volumes
|
64 |
+
* @param int $quantity OPTIONAL
|
65 |
+
* @return Ampersand_BinPack
|
66 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
67 |
+
*/
|
68 |
+
public function addItem($identifier, $volumes, $quantity = 1)
|
69 |
+
{
|
70 |
+
$this->getInput()->addItem($identifier, $volumes, $quantity);
|
71 |
+
|
72 |
+
return $this;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @return Ampersand_BinPack_Output
|
77 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
78 |
+
*/
|
79 |
+
public function pack()
|
80 |
+
{
|
81 |
+
if (is_null($this->_packer)) {
|
82 |
+
$this->_packer = new Ampersand_BinPack_Packer_JoshBestFit();
|
83 |
+
}
|
84 |
+
|
85 |
+
$state = Ampersand_BinPack_State::factory($this->getInput());
|
86 |
+
|
87 |
+
$this->_packer->pack($state);
|
88 |
+
|
89 |
+
return Ampersand_BinPack_Output::factory($state);
|
90 |
+
}
|
91 |
+
}
|
lib/Ampersand/BinPack/Bin.php
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_Bin
|
3 |
+
{
|
4 |
+
/** @var array */
|
5 |
+
protected $_binDimensions = array();
|
6 |
+
/** @var array */
|
7 |
+
protected $_items = array();
|
8 |
+
/** @var bool */
|
9 |
+
protected $_isClosed = false;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param array $dimensions
|
13 |
+
* @return Ampersand_BinPack_Bin
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
15 |
+
*/
|
16 |
+
public static function factory(array $dimensions)
|
17 |
+
{
|
18 |
+
$bin = new Ampersand_BinPack_Bin();
|
19 |
+
|
20 |
+
foreach ($dimensions as $_dimension) {
|
21 |
+
$_binDimension = Ampersand_BinPack_BinDimension::factory($bin, $_dimension);
|
22 |
+
$bin->_binDimensions[$_dimension->getIdentifier()] = $_binDimension;
|
23 |
+
}
|
24 |
+
|
25 |
+
return $bin;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param Ampersand_BinPack_Item $item
|
30 |
+
* @return Ampersand_BinPack_Bin
|
31 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
32 |
+
*/
|
33 |
+
public function addItem(Ampersand_BinPack_Item $item)
|
34 |
+
{
|
35 |
+
$this->_items[] = $item;
|
36 |
+
$item->setBin($this);
|
37 |
+
|
38 |
+
return $this;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @return array
|
43 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
44 |
+
*/
|
45 |
+
public function getItems()
|
46 |
+
{
|
47 |
+
return $this->_items;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @return array
|
52 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
53 |
+
*/
|
54 |
+
public function getItemIdentifiers()
|
55 |
+
{
|
56 |
+
$identifiers = array();
|
57 |
+
|
58 |
+
foreach ($this->_items as $_item) {
|
59 |
+
$identifiers[] = $_item->getIdentifier();
|
60 |
+
}
|
61 |
+
|
62 |
+
return $identifiers;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @return array
|
67 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
68 |
+
*/
|
69 |
+
public function getItemQuantities()
|
70 |
+
{
|
71 |
+
$itemQuantities = array();
|
72 |
+
|
73 |
+
foreach ($this->_items as $_item) {
|
74 |
+
if (!array_key_exists($_item->getIdentifier(), $itemQuantities)) {
|
75 |
+
$itemQuantities[$_item->getIdentifier()] = 1;
|
76 |
+
} else {
|
77 |
+
$itemQuantities[$_item->getIdentifier()] += 1;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
return $itemQuantities;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @param Ampersand_BinPack_Item $item
|
86 |
+
* @return bool
|
87 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
88 |
+
*/
|
89 |
+
public function getCanFitItem(Ampersand_BinPack_Item $item)
|
90 |
+
{
|
91 |
+
foreach ($this->_binDimensions as $_binDimension) {
|
92 |
+
/* @var $_binDimension Ampersand_BinPack_BinDimension */
|
93 |
+
if (!$_binDimension->getCanFitItem($item)) {
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
return true;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* @param Ampersand_BinPack_Item $item
|
103 |
+
* @return float 1 => perfect fit, 0 => least perfect fit, < 0 => item cannot fit
|
104 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
105 |
+
*/
|
106 |
+
public function getQualityOfFit(Ampersand_BinPack_Item $item)
|
107 |
+
{
|
108 |
+
$quality = 1.0;
|
109 |
+
|
110 |
+
foreach ($this->_binDimensions as $_binDimension) {
|
111 |
+
/* @var $_binDimension Ampersand_BinPack_BinDimension */
|
112 |
+
if (!$_binDimension->getCanFitItem($item)) {
|
113 |
+
return -1.0;
|
114 |
+
}
|
115 |
+
|
116 |
+
$quality *= $_binDimension->getQualityOfFit($item);
|
117 |
+
}
|
118 |
+
|
119 |
+
return $quality;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* @param Ampersand_BinPack_Dimension_DimensionInterface $dimension
|
124 |
+
* @return null|Ampersand_BinPack_BinDimension
|
125 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
126 |
+
*/
|
127 |
+
public function getBinDimension(Ampersand_BinPack_Dimension_DimensionInterface $dimension)
|
128 |
+
{
|
129 |
+
if (!array_key_exists($dimension->getIdentifier(), $this->_binDimensions)) {
|
130 |
+
return null;
|
131 |
+
}
|
132 |
+
|
133 |
+
return $this->_binDimensions[$dimension->getIdentifier()];
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* @return bool
|
138 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
139 |
+
*/
|
140 |
+
public function getIsClosed()
|
141 |
+
{
|
142 |
+
return $this->_isClosed;
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* @return Ampersand_BinPack_Bin
|
147 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
148 |
+
*/
|
149 |
+
public function close()
|
150 |
+
{
|
151 |
+
$this->_isClosed = true;
|
152 |
+
|
153 |
+
return $this;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* @return array
|
158 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
159 |
+
*/
|
160 |
+
public function getStats()
|
161 |
+
{
|
162 |
+
$stats = array(
|
163 |
+
'nr_of_items' => count($this->_items),
|
164 |
+
'volume_used_pct_normalised' => 0,
|
165 |
+
'dimensions' => array(),
|
166 |
+
);
|
167 |
+
|
168 |
+
foreach ($this->_binDimensions as $_binDimension) {
|
169 |
+
$_dimensionIdentifier = $_binDimension->getDimension()->getIdentifier();
|
170 |
+
$_stats = $_binDimension->getStats();
|
171 |
+
$stats['dimensions'][$_dimensionIdentifier] = $_stats;
|
172 |
+
$stats['volume_used_pct_normalised'] += $_stats['volume_used_pct'];
|
173 |
+
}
|
174 |
+
|
175 |
+
$stats['volume_used_pct_normalised'] /= count($this->_binDimensions);
|
176 |
+
|
177 |
+
return $stats;
|
178 |
+
}
|
179 |
+
}
|
lib/Ampersand/BinPack/BinDimension.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_BinDimension
|
3 |
+
{
|
4 |
+
/** @var Ampersand_BinPack_Bin */
|
5 |
+
protected $_bin;
|
6 |
+
/** @var Ampersand_BinPack_Dimension_DimensionInterface */
|
7 |
+
protected $_dimension;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @param Ampersand_BinPack_Bin $bin
|
11 |
+
* @param Ampersand_BinPack_Dimension_DimensionInterface $dimension
|
12 |
+
* @return Ampersand_BinPack_BinDimension
|
13 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
14 |
+
*/
|
15 |
+
public static function factory(Ampersand_BinPack_Bin $bin,
|
16 |
+
Ampersand_BinPack_Dimension_DimensionInterface $dimension
|
17 |
+
) {
|
18 |
+
$binDimension = new Ampersand_BinPack_BinDimension();
|
19 |
+
|
20 |
+
$binDimension->_bin = $bin;
|
21 |
+
$binDimension->_dimension = $dimension;
|
22 |
+
|
23 |
+
$dimension->addBinDimension($binDimension);
|
24 |
+
|
25 |
+
return $binDimension;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @return int|float
|
30 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
31 |
+
*/
|
32 |
+
public function getVolumeRemaining()
|
33 |
+
{
|
34 |
+
return ($this->_dimension->getBinVolume() - $this->getVolumeUsed());
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @return int|float
|
39 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
40 |
+
*/
|
41 |
+
public function getVolumeUsed()
|
42 |
+
{
|
43 |
+
$volumeUsed = 0;
|
44 |
+
|
45 |
+
foreach ($this->_bin->getItems() as $_item) {
|
46 |
+
$volumeUsed += $_item->getItemDimension($this->_dimension)->getVolume();
|
47 |
+
}
|
48 |
+
|
49 |
+
return $volumeUsed;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @return Ampersand_BinPack_Bin
|
54 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
55 |
+
*/
|
56 |
+
public function getBin()
|
57 |
+
{
|
58 |
+
return $this->_bin;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @return Ampersand_BinPack_Dimension
|
63 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
64 |
+
*/
|
65 |
+
public function getDimension()
|
66 |
+
{
|
67 |
+
return $this->_dimension;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* @param Ampersand_BinPack_Item $item
|
72 |
+
* @return bool
|
73 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
74 |
+
*/
|
75 |
+
public function getCanFitItem(Ampersand_BinPack_Item $item)
|
76 |
+
{
|
77 |
+
if (!$volumeRemainingInBin = $this->getVolumeRemaining()) {
|
78 |
+
return false;
|
79 |
+
}
|
80 |
+
|
81 |
+
$itemVolume = $item->getItemDimension($this->_dimension)->getVolume();
|
82 |
+
|
83 |
+
return ($itemVolume <= $volumeRemainingInBin);
|
84 |
+
}
|
85 |
+
/**
|
86 |
+
* @param Ampersand_BinPack_Item $item
|
87 |
+
* @return float 1 => perfect fit, 0 => least perfect fit, < 0 => item cannot fit
|
88 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
89 |
+
*/
|
90 |
+
public function getQualityOfFit(Ampersand_BinPack_Item $item)
|
91 |
+
{
|
92 |
+
$volumeRemainingInBin = $this->getVolumeRemaining();
|
93 |
+
$itemVolume = $item->getItemDimension($this->_dimension)->getVolume();
|
94 |
+
|
95 |
+
if ($itemVolume > $volumeRemainingInBin) {
|
96 |
+
return -1.0;
|
97 |
+
}
|
98 |
+
|
99 |
+
return (1.0 - (($volumeRemainingInBin - $itemVolume) / $this->_dimension->getBinVolume()));
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* @return array
|
104 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
105 |
+
*/
|
106 |
+
public function getStats()
|
107 |
+
{
|
108 |
+
$binVolume = $this->_dimension->getBinVolume();
|
109 |
+
$volumeUsed = $this->getVolumeUsed();
|
110 |
+
|
111 |
+
return array(
|
112 |
+
'bin_volume' => $binVolume,
|
113 |
+
'volume_used' => $volumeUsed,
|
114 |
+
'volume_remaining' => $this->getVolumeRemaining(),
|
115 |
+
'volume_used_pct' => $volumeUsed / $binVolume,
|
116 |
+
);
|
117 |
+
}
|
118 |
+
}
|
lib/Ampersand/BinPack/Dimension/DimensionInterface.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
interface Ampersand_BinPack_Dimension_DimensionInterface
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @return string
|
6 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
7 |
+
*/
|
8 |
+
public function getIdentifier();
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @return int|float
|
12 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
13 |
+
*/
|
14 |
+
public function getBinVolume();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @param Ampersand_BinPack_ItemDimension $itemDimension
|
18 |
+
* @return Ampersand_BinPack_Dimension_DimensionInterface
|
19 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
20 |
+
*/
|
21 |
+
public function addItemDimension(Ampersand_BinPack_ItemDimension $itemDimension);
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @param Ampersand_BinPack_BinDimension $binDimension
|
25 |
+
* @return Ampersand_BinPack_Dimension_DimensionInterface
|
26 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
27 |
+
*/
|
28 |
+
public function addBinDimension(Ampersand_BinPack_BinDimension $binDimension);
|
29 |
+
}
|
lib/Ampersand/BinPack/Dimension/Standard.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_Dimension_Standard implements Ampersand_BinPack_Dimension_DimensionInterface
|
3 |
+
{
|
4 |
+
/** @var string */
|
5 |
+
protected $_identifier;
|
6 |
+
/** @var int|float */
|
7 |
+
protected $_binVolume;
|
8 |
+
/** @var array */
|
9 |
+
protected $_itemDimensions = array();
|
10 |
+
/** @var array */
|
11 |
+
protected $_binDimensions = array();
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @param string $identifier
|
15 |
+
* @param int|float $binVolume
|
16 |
+
* @return Ampersand_BinPack_Dimension_Standard
|
17 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
18 |
+
*/
|
19 |
+
public static function factory($identifier, $binVolume)
|
20 |
+
{
|
21 |
+
$dimension = new Ampersand_BinPack_Dimension_Standard();
|
22 |
+
|
23 |
+
$dimension->_identifier = $identifier;
|
24 |
+
$dimension->_binVolume = $binVolume;
|
25 |
+
|
26 |
+
return $dimension;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return string
|
31 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
32 |
+
*/
|
33 |
+
public function getIdentifier()
|
34 |
+
{
|
35 |
+
return $this->_identifier;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @return int|float
|
40 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
41 |
+
*/
|
42 |
+
public function getBinVolume()
|
43 |
+
{
|
44 |
+
return $this->_binVolume;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @param Ampersand_BinPack_ItemDimension $itemDimension
|
49 |
+
* @return Ampersand_BinPack_Dimension_DimensionInterface
|
50 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
51 |
+
*/
|
52 |
+
public function addItemDimension(Ampersand_BinPack_ItemDimension $itemDimension)
|
53 |
+
{
|
54 |
+
$this->_itemDimensions[] = $itemDimension;
|
55 |
+
|
56 |
+
return $this;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @param Ampersand_BinPack_BinDimension $binDimension
|
61 |
+
* @return Ampersand_BinPack_Dimension_DimensionInterface
|
62 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
63 |
+
*/
|
64 |
+
public function addBinDimension(Ampersand_BinPack_BinDimension $binDimension)
|
65 |
+
{
|
66 |
+
$this->_binDimensions[] = $binDimension;
|
67 |
+
|
68 |
+
return $this;
|
69 |
+
}
|
70 |
+
}
|
lib/Ampersand/BinPack/Input.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_Input
|
3 |
+
{
|
4 |
+
/** @var array */
|
5 |
+
protected $_dimensions = array();
|
6 |
+
/** @var array */
|
7 |
+
protected $_items = array();
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @param string|Ampersand_BinPack_Dimension_DimensionInterface $identifier
|
11 |
+
* @param int|float $binVolume OPTIONAL
|
12 |
+
* @return Ampersand_BinPack_Input
|
13 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
14 |
+
*/
|
15 |
+
public function addDimension($identifier, $binVolume = null)
|
16 |
+
{
|
17 |
+
if ($identifier instanceof Ampersand_BinPack_Dimension_DimensionInterface) {
|
18 |
+
$dimension = $identifier;
|
19 |
+
$identifier = $dimension->getIdentifier();
|
20 |
+
}
|
21 |
+
|
22 |
+
if (array_key_exists($identifier, $this->_dimensions)) {
|
23 |
+
throw new Exception("'$identifier' is not a unique dimension identifier.");
|
24 |
+
}
|
25 |
+
|
26 |
+
if (!isset($dimension)) {
|
27 |
+
$dimension = Ampersand_BinPack_Dimension_Standard::factory($identifier, $binVolume);
|
28 |
+
}
|
29 |
+
|
30 |
+
$this->_dimensions[$identifier] = $dimension;
|
31 |
+
|
32 |
+
return $this;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return array
|
37 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
38 |
+
*/
|
39 |
+
public function getDimensions()
|
40 |
+
{
|
41 |
+
return $this->_dimensions;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @param string $identifier
|
46 |
+
* @param array|int|float $volumes
|
47 |
+
* @param int $quantity OPTIONAL
|
48 |
+
* @return Ampersand_BinPack_Input
|
49 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
50 |
+
*/
|
51 |
+
public function addItem($identifier, $volumes, $quantity = 1)
|
52 |
+
{
|
53 |
+
for ($_i = 1; $_i <= $quantity; $_i++) {
|
54 |
+
$this->_items[] = Ampersand_BinPack_Item::factory($identifier, $this->_dimensions, $volumes);
|
55 |
+
}
|
56 |
+
|
57 |
+
return $this;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* @return array
|
62 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
63 |
+
*/
|
64 |
+
public function getItems()
|
65 |
+
{
|
66 |
+
return $this->_items;
|
67 |
+
}
|
68 |
+
}
|
lib/Ampersand/BinPack/Item.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_Item
|
3 |
+
{
|
4 |
+
/** @var mixed */
|
5 |
+
protected $_identifier;
|
6 |
+
/** @var array */
|
7 |
+
protected $_itemDimensions = array();
|
8 |
+
/** @var Ampersand_BinPack_Bin */
|
9 |
+
protected $_bin;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param string $identifier
|
13 |
+
* @param array $dimensions
|
14 |
+
* @param array $volumes
|
15 |
+
* @return Ampersand_BinPack_Item
|
16 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
17 |
+
*/
|
18 |
+
public static function factory($identifier, array $dimensions, array $volumes)
|
19 |
+
{
|
20 |
+
$item = new Ampersand_BinPack_Item();
|
21 |
+
|
22 |
+
$item->_identifier = $identifier;
|
23 |
+
|
24 |
+
foreach ($dimensions as $_dimension) {
|
25 |
+
if (!array_key_exists($_dimension->getIdentifier(), $volumes)) {
|
26 |
+
continue;
|
27 |
+
}
|
28 |
+
|
29 |
+
$_volume = $volumes[$_dimension->getIdentifier()];
|
30 |
+
$_itemDimension = Ampersand_BinPack_ItemDimension::factory($item, $_dimension, $_volume);
|
31 |
+
|
32 |
+
$item->_itemDimensions[$_dimension->getIdentifier()] = $_itemDimension;
|
33 |
+
}
|
34 |
+
|
35 |
+
return $item;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @param Ampersand_BinPack_Dimension_DimensionInterface $dimension
|
40 |
+
* @return null|Ampersand_BinPack_ItemDimension
|
41 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
42 |
+
*/
|
43 |
+
public function getItemDimension(Ampersand_BinPack_Dimension_DimensionInterface $dimension)
|
44 |
+
{
|
45 |
+
if (!array_key_exists($dimension->getIdentifier(), $this->_itemDimensions)) {
|
46 |
+
return null;
|
47 |
+
}
|
48 |
+
|
49 |
+
return $this->_itemDimensions[$dimension->getIdentifier()];
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @param Ampersand_BinPack_Bin $bin
|
54 |
+
* @return Ampersand_BinPack_Item
|
55 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
56 |
+
*/
|
57 |
+
public function setBin(Ampersand_BinPack_Bin $bin)
|
58 |
+
{
|
59 |
+
if (!is_null($this->_bin)) {
|
60 |
+
throw new Exception('Item is already assigned to a bin.');
|
61 |
+
}
|
62 |
+
|
63 |
+
$this->_bin = $bin;
|
64 |
+
|
65 |
+
return $this;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* @return Ampersand_BinPack_Bin
|
70 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
71 |
+
*/
|
72 |
+
public function getBin()
|
73 |
+
{
|
74 |
+
return $this->_bin;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @return mixed
|
79 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
80 |
+
*/
|
81 |
+
public function getIdentifier()
|
82 |
+
{
|
83 |
+
return $this->_identifier;
|
84 |
+
}
|
85 |
+
}
|
lib/Ampersand/BinPack/ItemDimension.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_ItemDimension
|
3 |
+
{
|
4 |
+
/** @var Ampersand_BinPack_Item */
|
5 |
+
protected $_item;
|
6 |
+
/** @var Ampersand_BinPack_Dimension_DimensionInterface */
|
7 |
+
protected $_dimension;
|
8 |
+
/** @var null|int|double */
|
9 |
+
protected $_volume;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @param Ampersand_BinPack_Item $item
|
13 |
+
* @param Ampersand_BinPack_Dimension_DimensionInterface $dimension
|
14 |
+
* @param int|double $volume
|
15 |
+
* @return Ampersand_BinPack_ItemDimension
|
16 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
17 |
+
*/
|
18 |
+
public static function factory(Ampersand_BinPack_Item $item,
|
19 |
+
Ampersand_BinPack_Dimension_DimensionInterface $dimension, $volume
|
20 |
+
) {
|
21 |
+
$itemDimension = new Ampersand_BinPack_ItemDimension();
|
22 |
+
|
23 |
+
$itemDimension->_item = $item;
|
24 |
+
$itemDimension->_dimension = $dimension;
|
25 |
+
$itemDimension->_volume = $volume;
|
26 |
+
|
27 |
+
$dimension->addItemDimension($itemDimension);
|
28 |
+
|
29 |
+
return $itemDimension;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @return int|double
|
34 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
35 |
+
*/
|
36 |
+
public function getVolume()
|
37 |
+
{
|
38 |
+
return $this->_volume;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @return Ampersand_BinPack_Item
|
43 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
44 |
+
*/
|
45 |
+
public function getItem()
|
46 |
+
{
|
47 |
+
return $this->_item;
|
48 |
+
}
|
49 |
+
}
|
lib/Ampersand/BinPack/Output.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_Output
|
3 |
+
{
|
4 |
+
protected $_bins;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* @param Ampersand_BinPack_State $state
|
8 |
+
* @return Ampersand_BinPack_Output
|
9 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
10 |
+
*/
|
11 |
+
public static function factory(Ampersand_BinPack_State $state)
|
12 |
+
{
|
13 |
+
$output = new Ampersand_BinPack_Output();
|
14 |
+
|
15 |
+
$output->_setBins($state->getBins());
|
16 |
+
|
17 |
+
return $output;
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param array $bins
|
22 |
+
* @return void
|
23 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
24 |
+
*/
|
25 |
+
protected function _setBins(array $bins)
|
26 |
+
{
|
27 |
+
$this->_bins = array();
|
28 |
+
|
29 |
+
foreach ($bins as $_bin) {
|
30 |
+
if ($_bin->getItems()) {
|
31 |
+
$this->_bins[] = $_bin;
|
32 |
+
}
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @return int
|
38 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
39 |
+
*/
|
40 |
+
public function getNrOfBins()
|
41 |
+
{
|
42 |
+
return count($this->_bins);
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param bool $withQuantities OPTIONAL
|
47 |
+
* @return array
|
48 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
49 |
+
*/
|
50 |
+
public function getAssignments($withQuantities = false)
|
51 |
+
{
|
52 |
+
$assignments = array();
|
53 |
+
|
54 |
+
$methodName = $withQuantities ? 'getItemQuantities' : 'getItemIdentifiers';
|
55 |
+
foreach ($this->_bins as $_bin) {
|
56 |
+
$assignments[] = $_bin->$methodName();
|
57 |
+
}
|
58 |
+
|
59 |
+
return $assignments;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @return array
|
64 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
65 |
+
*/
|
66 |
+
public function getAssignmentStats()
|
67 |
+
{
|
68 |
+
$stats = array(
|
69 |
+
'nr_of_bins' => count($this->_bins),
|
70 |
+
'volume_used_pct_normalised' => 0,
|
71 |
+
'bins' => array(),
|
72 |
+
);
|
73 |
+
|
74 |
+
foreach ($this->_bins as $_bin) {
|
75 |
+
$_stats = $_bin->getStats();
|
76 |
+
$stats['bins'][] = $_bin->getStats();
|
77 |
+
$stats['volume_used_pct_normalised'] += $_stats['volume_used_pct_normalised'];
|
78 |
+
}
|
79 |
+
|
80 |
+
$stats['volume_used_pct_normalised'] /= count($this->_bins);
|
81 |
+
|
82 |
+
return $stats;
|
83 |
+
}
|
84 |
+
}
|
lib/Ampersand/BinPack/Packer/FirstFit.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_Packer_FirstFit extends Ampersand_BinPack_Packer_PackerAbstract
|
3 |
+
{
|
4 |
+
public function pack(Ampersand_BinPack_State $state)
|
5 |
+
{
|
6 |
+
$unassignedItems = $state->getUnassignedItems();
|
7 |
+
|
8 |
+
foreach ($unassignedItems as $_item) {
|
9 |
+
/* @var $_item Ampersand_BinPack_Item */
|
10 |
+
$_selectedBin = null;
|
11 |
+
|
12 |
+
foreach ($state->getOpenBins() as $__bin) {
|
13 |
+
/* @var $__bin Ampersand_BinPack_Bin */
|
14 |
+
if ($__bin->getCanFitItem($_item)) {
|
15 |
+
$_selectedBin = $__bin;
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
if (!$_selectedBin) {
|
20 |
+
$_selectedBin = $state->getNewBin();
|
21 |
+
}
|
22 |
+
|
23 |
+
$_selectedBin->addItem($_item);
|
24 |
+
}
|
25 |
+
|
26 |
+
return $this;
|
27 |
+
}
|
28 |
+
}
|
lib/Ampersand/BinPack/Packer/JoshBestFit.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_Packer_JoshBestFit extends Ampersand_BinPack_Packer_PackerAbstract
|
3 |
+
{
|
4 |
+
public function pack(Ampersand_BinPack_State $state)
|
5 |
+
{
|
6 |
+
$bin = $state->getNewBin();
|
7 |
+
foreach ($state->getUnassignedItems() as $_item) {
|
8 |
+
if (!$bin->getCanFitItem($_item)) {
|
9 |
+
$bin->addItem($_item);
|
10 |
+
$bin->close();
|
11 |
+
$bin = $state->getNewBin();
|
12 |
+
}
|
13 |
+
}
|
14 |
+
|
15 |
+
$_prevItems = null;
|
16 |
+
while ($_items = $state->getUnassignedItems()) {
|
17 |
+
if ($_prevItems && count($_items) == count($_prevItems)) {
|
18 |
+
$state->getNewBin();
|
19 |
+
}
|
20 |
+
|
21 |
+
foreach ($state->getOpenBins() as $__bin) {
|
22 |
+
$__bestFittingItem = null;
|
23 |
+
|
24 |
+
$__qualityOfBestFit = null;
|
25 |
+
foreach ($_items as $___item) {
|
26 |
+
if ($___item->getBin() || !$__bin->getCanFitItem($___item)) {
|
27 |
+
continue;
|
28 |
+
}
|
29 |
+
|
30 |
+
$___fitQuality = $__bin->getQualityOfFit($___item);
|
31 |
+
if (is_null($__bestFittingItem) || $___fitQuality > $__qualityOfBestFit) {
|
32 |
+
$__bestFittingItem = $___item;
|
33 |
+
$__qualityOfBestFit = $___fitQuality;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
if ($__bestFittingItem) {
|
38 |
+
$__bin->addItem($__bestFittingItem);
|
39 |
+
} else {
|
40 |
+
$__bin->close();
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
$_prevItems = $_items;
|
45 |
+
}
|
46 |
+
|
47 |
+
return $this;
|
48 |
+
}
|
49 |
+
}
|
lib/Ampersand/BinPack/Packer/PackerAbstract.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
abstract class Ampersand_BinPack_Packer_PackerAbstract
|
3 |
+
implements Ampersand_BinPack_Packer_PackerInterface
|
4 |
+
{
|
5 |
+
|
6 |
+
}
|
lib/Ampersand/BinPack/Packer/PackerInterface.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
interface Ampersand_BinPack_Packer_PackerInterface
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @param Ampersand_BinPack_State $state
|
6 |
+
* @return Ampersand_BinPack_Packer_PackerInterface
|
7 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
8 |
+
*/
|
9 |
+
public function pack(Ampersand_BinPack_State $state);
|
10 |
+
}
|
lib/Ampersand/BinPack/State.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_BinPack_State
|
3 |
+
{
|
4 |
+
/** @var array */
|
5 |
+
protected $_dimensions = array();
|
6 |
+
/** @var array */
|
7 |
+
protected $_items = array();
|
8 |
+
/** @var array */
|
9 |
+
protected $_unassignedItems = array();
|
10 |
+
/** @var array */
|
11 |
+
protected $_bins = array();
|
12 |
+
/** @var array */
|
13 |
+
protected $_openBins = array();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @param Ampersand_BinPack_Input $input
|
17 |
+
* @return Ampersand_BinPack_State
|
18 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
19 |
+
*/
|
20 |
+
public static function factory(Ampersand_BinPack_Input $input)
|
21 |
+
{
|
22 |
+
$state = new Ampersand_BinPack_State();
|
23 |
+
|
24 |
+
$state->_dimensions = $input->getDimensions();
|
25 |
+
$state->_items = $input->getItems();
|
26 |
+
$state->_unassignedItems = $state->_items;
|
27 |
+
|
28 |
+
return $state;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @return array
|
33 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
34 |
+
*/
|
35 |
+
public function getDimensions()
|
36 |
+
{
|
37 |
+
return $this->_dimensions;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @return array
|
42 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
43 |
+
*/
|
44 |
+
public function getItems()
|
45 |
+
{
|
46 |
+
return $this->_items;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @return array
|
51 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
52 |
+
*/
|
53 |
+
public function getUnassignedItems()
|
54 |
+
{
|
55 |
+
foreach ($this->_unassignedItems as $_key => $_item) {
|
56 |
+
if ($_item->getBin()) {
|
57 |
+
unset($this->_unassignedItems[$_key]);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
return $this->_unassignedItems;
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @return array
|
66 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
67 |
+
*/
|
68 |
+
public function getBins()
|
69 |
+
{
|
70 |
+
return $this->_bins;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* @return array
|
75 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
76 |
+
*/
|
77 |
+
public function getOpenBins()
|
78 |
+
{
|
79 |
+
foreach ($this->_openBins as $_key => $_bin) {
|
80 |
+
if ($_bin->getIsClosed()) {
|
81 |
+
unset($this->_openBins[$_key]);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
return $this->_openBins;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @return Ampersand_BinPack_Bin
|
90 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
91 |
+
*/
|
92 |
+
public function getNewBin()
|
93 |
+
{
|
94 |
+
return ($this->_bins[] = $this->_openBins[] = Ampersand_BinPack_Bin::factory($this->_dimensions));
|
95 |
+
}
|
96 |
+
}
|
lib/Ampersand/ClassProvider.php
CHANGED
@@ -1,30 +1,59 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_ClassProvider
|
17 |
+
{
|
18 |
+
protected $_classes = array();
|
19 |
+
|
20 |
+
public function getObject($alias)
|
21 |
+
{
|
22 |
+
if (!$alias) {
|
23 |
+
throw new Ampersand_Exception('No class alias specified');
|
24 |
+
}
|
25 |
+
if (!$class = $this->getClass($alias)) {
|
26 |
+
throw new Ampersand_Exception("No class found for alias '$alias'");
|
27 |
+
}
|
28 |
+
|
29 |
+
return new $class;
|
30 |
+
}
|
31 |
+
|
32 |
+
public function getSingleton($alias)
|
33 |
+
{
|
34 |
+
$class = $this->getClass($alias);
|
35 |
+
|
36 |
+
if (!$singleton = Ampersand_Registry::get($class, '__singleton')) {
|
37 |
+
$singleton = new $class;
|
38 |
+
Ampersand_Registry::set($class, $singleton, '__singleton');
|
39 |
+
}
|
40 |
+
|
41 |
+
return $singleton;
|
42 |
+
}
|
43 |
+
|
44 |
+
public function getClass($alias)
|
45 |
+
{
|
46 |
+
if (array_key_exists($alias, $this->_classes)) {
|
47 |
+
return $this->_classes[$alias];
|
48 |
+
}
|
49 |
+
|
50 |
+
return null;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function addClass($alias, $class)
|
54 |
+
{
|
55 |
+
$this->_classes[$alias] = $class;
|
56 |
+
|
57 |
+
return $this;
|
58 |
+
}
|
59 |
+
}
|
lib/Ampersand/Db/Test/Abstract.php
CHANGED
@@ -1,59 +1,99 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
abstract class Ampersand_Db_Test_Abstract
|
3 |
+
{
|
4 |
+
/** @var PDO|PDOStatement */
|
5 |
+
protected $_pdoInstance;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Proxy any method calls to the PDO|PDOStatement instance associated to this object. Captures
|
9 |
+
* the output of any calls to the PDO|PDOStatement instance
|
10 |
+
*
|
11 |
+
* @param string $name
|
12 |
+
* @param array $arguments
|
13 |
+
* @return mixed
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
public function __call($name, array $arguments)
|
17 |
+
{
|
18 |
+
$output = call_user_func_array(array($this->_pdoInstance, $name), $arguments);
|
19 |
+
|
20 |
+
if (Ampersand_Db_Test_Config::getIsCaptureEnabled()) {
|
21 |
+
$this->_captureMethodOutput($name, $arguments, $output);
|
22 |
+
} else if (Ampersand_Db_Test_Config::getIsFetchEnabled()) {
|
23 |
+
$output = $this->_fetchNextOutput($name, $arguments);
|
24 |
+
} else {
|
25 |
+
return $output;
|
26 |
+
}
|
27 |
+
|
28 |
+
return $this->_prepareReturnValue($output);
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Persists a method output value so that it can be fetched later
|
33 |
+
*
|
34 |
+
* @param mixed $output
|
35 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
36 |
+
*/
|
37 |
+
protected function _captureMethodOutput($method, array $arguments, $output)
|
38 |
+
{
|
39 |
+
if ($output === $this) {
|
40 |
+
$output = new Ampersand_Db_Test_Output_This();
|
41 |
+
}
|
42 |
+
if ($output instanceof PDOStatement) {
|
43 |
+
$output = new Ampersand_Db_Test_Output_Statement();
|
44 |
+
}
|
45 |
+
|
46 |
+
$hash = $this->_hashMethodCall($method, $arguments);
|
47 |
+
|
48 |
+
Ampersand_Db_Test_Config::addCapturedOutput($method, $output, $hash);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Fetches the next output value from the data source
|
53 |
+
*
|
54 |
+
* @param string $method
|
55 |
+
* @param mixed $output
|
56 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
57 |
+
*/
|
58 |
+
protected function _fetchNextOutput($method, array $arguments)
|
59 |
+
{
|
60 |
+
$hash = $this->_hashMethodCall($method, $arguments);
|
61 |
+
|
62 |
+
return Ampersand_Db_Test_Config::fetchNextOutput($method, $hash);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Produces a hash string based on a method and the arguments passed to it. When fetching
|
67 |
+
* captured PDO outputs from the data source this hash can be used to verify that the correct
|
68 |
+
* output is being returned
|
69 |
+
*
|
70 |
+
* @param string $method
|
71 |
+
* @param array $arguments
|
72 |
+
* @return string
|
73 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
74 |
+
*/
|
75 |
+
protected function _hashMethodCall($method, array $arguments)
|
76 |
+
{
|
77 |
+
return null;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Prepares PDO method output for return to caller. Creates wrapper object where necessary
|
82 |
+
*
|
83 |
+
* @param type $returnValue
|
84 |
+
* @return mixed
|
85 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
86 |
+
*/
|
87 |
+
protected function _prepareReturnValue($returnValue)
|
88 |
+
{
|
89 |
+
if ($returnValue instanceof PDOStatement) {
|
90 |
+
$returnValue = new Ampersand_Db_Test_Statement($returnValue);
|
91 |
+
} else if ($returnValue instanceof Ampersand_Db_Test_Output_This) {
|
92 |
+
$returnValue = $this;
|
93 |
+
} else if ($returnValue instanceof Ampersand_Db_Test_Output_Statement) {
|
94 |
+
$returnValue = new Ampersand_Db_Test_Statement();
|
95 |
+
}
|
96 |
+
|
97 |
+
return $returnValue;
|
98 |
+
}
|
99 |
+
}
|
lib/Ampersand/Db/Test/Adapter.php
CHANGED
@@ -1,45 +1,65 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_Adapter extends Varien_Db_Adapter_Pdo_Mysql
|
3 |
+
{
|
4 |
+
protected function _connect()
|
5 |
+
{
|
6 |
+
// if we already have a PDO object, no need to re-connect.
|
7 |
+
if ($this->_connection) {
|
8 |
+
return;
|
9 |
+
}
|
10 |
+
|
11 |
+
// get the dsn first, because some adapters alter the $_pdoType
|
12 |
+
$dsn = $this->_dsn();
|
13 |
+
|
14 |
+
// check for PDO extension
|
15 |
+
if (!extension_loaded('pdo')) {
|
16 |
+
/**
|
17 |
+
* @see Zend_Db_Adapter_Exception
|
18 |
+
*/
|
19 |
+
#require_once 'Zend/Db/Adapter/Exception.php';
|
20 |
+
throw new Zend_Db_Adapter_Exception('The PDO extension is required for this adapter but the extension is not loaded');
|
21 |
+
}
|
22 |
+
|
23 |
+
// check the PDO driver is available
|
24 |
+
if (!in_array($this->_pdoType, PDO::getAvailableDrivers())) {
|
25 |
+
/**
|
26 |
+
* @see Zend_Db_Adapter_Exception
|
27 |
+
*/
|
28 |
+
#require_once 'Zend/Db/Adapter/Exception.php';
|
29 |
+
throw new Zend_Db_Adapter_Exception('The ' . $this->_pdoType . ' driver is not currently installed');
|
30 |
+
}
|
31 |
+
|
32 |
+
// create PDO connection
|
33 |
+
$q = $this->_profiler->queryStart('connect', Zend_Db_Profiler::CONNECT);
|
34 |
+
|
35 |
+
// add the persistence flag if we find it in our config array
|
36 |
+
if (isset($this->_config['persistent']) && ($this->_config['persistent'] == true)) {
|
37 |
+
$this->_config['driver_options'][PDO::ATTR_PERSISTENT] = true;
|
38 |
+
}
|
39 |
+
|
40 |
+
try {
|
41 |
+
$this->_connection = new Ampersand_Db_Test_Connection(
|
42 |
+
$dsn,
|
43 |
+
$this->_config['username'],
|
44 |
+
$this->_config['password'],
|
45 |
+
$this->_config['driver_options']
|
46 |
+
);
|
47 |
+
|
48 |
+
$this->_profiler->queryEnd($q);
|
49 |
+
|
50 |
+
// set the PDO connection to perform case-folding on array keys, or not
|
51 |
+
$this->_connection->setAttribute(PDO::ATTR_CASE, $this->_caseFolding);
|
52 |
+
|
53 |
+
// always use exceptions.
|
54 |
+
$this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
55 |
+
|
56 |
+
} catch (PDOException $e) {
|
57 |
+
/**
|
58 |
+
* @see Zend_Db_Adapter_Exception
|
59 |
+
*/
|
60 |
+
#require_once 'Zend/Db/Adapter/Exception.php';
|
61 |
+
throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
|
62 |
+
}
|
63 |
+
|
64 |
+
}
|
65 |
+
}
|
lib/Ampersand/Db/Test/Config.php
CHANGED
@@ -1,103 +1,257 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_Config
|
3 |
+
{
|
4 |
+
/** @var string */
|
5 |
+
protected static $_filePath;
|
6 |
+
|
7 |
+
/** @var bool */
|
8 |
+
protected static $_isCaptureEnabled = false;
|
9 |
+
|
10 |
+
/** @var bool */
|
11 |
+
protected static $_isFetchEnabled = false;
|
12 |
+
|
13 |
+
/** @var array */
|
14 |
+
protected static $_capturedOutputs = array();
|
15 |
+
|
16 |
+
/** @var array */
|
17 |
+
protected static $_fetchedOutputs;
|
18 |
+
|
19 |
+
/** @var int */
|
20 |
+
protected static $_nrOfFetchedOutputs;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Sets the file path which PDO outputs should be captured to and fetched from
|
24 |
+
*
|
25 |
+
* @param string $filePath
|
26 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
27 |
+
*/
|
28 |
+
public static function setFilePath($filePath)
|
29 |
+
{
|
30 |
+
self::$_filePath = $filePath;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Gets the file path which PDO outputs will be captured to and fetched from
|
35 |
+
*
|
36 |
+
* @return string
|
37 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
38 |
+
*/
|
39 |
+
public static function getFilePath()
|
40 |
+
{
|
41 |
+
return self::$_filePath;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Enables capturing of PDO outputs
|
46 |
+
*
|
47 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
48 |
+
*/
|
49 |
+
public static function enableCapture()
|
50 |
+
{
|
51 |
+
self::$_isCaptureEnabled = true;
|
52 |
+
self::disableFetch();
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Disables capturing of PDO outputs
|
57 |
+
*
|
58 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
59 |
+
*/
|
60 |
+
public static function disableCapture()
|
61 |
+
{
|
62 |
+
self::$_isCaptureEnabled = false;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Returns whether or not capturing of PDO outputs is currently enabled
|
67 |
+
*
|
68 |
+
* @return bool
|
69 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
70 |
+
*/
|
71 |
+
public static function getIsCaptureEnabled()
|
72 |
+
{
|
73 |
+
return self::$_isCaptureEnabled;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Saves to disk any PDO outputs which have been captured
|
78 |
+
*
|
79 |
+
* @param string $filePath OPTIONAL File path to save captured outputs to - defaults to
|
80 |
+
* Ampersand_Db_Test_Config::getFilePath
|
81 |
+
* @return void
|
82 |
+
* @throws Ampersand_Db_Test_Exception Thrown if no file path has been specified
|
83 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
84 |
+
*/
|
85 |
+
public static function saveCaptured($filePath = null)
|
86 |
+
{
|
87 |
+
if (!count(self::$_capturedOutputs)) {
|
88 |
+
return;
|
89 |
+
}
|
90 |
+
|
91 |
+
$filePath = self::_prepareFilePath($filePath);
|
92 |
+
|
93 |
+
$dirPath = dirname($filePath);
|
94 |
+
|
95 |
+
if ((!@file_exists($dirPath) && !mkdir($dirPath, 0777, true))
|
96 |
+
|| !$fileHandle = fopen($filePath, 'w')) {
|
97 |
+
throw new Ampersand_Db_Test_Exception('Specified file path is not writable.');
|
98 |
+
}
|
99 |
+
|
100 |
+
$serialized = serialize(self::$_capturedOutputs);
|
101 |
+
fwrite($fileHandle, $serialized);
|
102 |
+
|
103 |
+
self::$_capturedOutputs = null;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Disables capturing of PDO outputs and saves to disk any outputs which have been captured
|
108 |
+
*
|
109 |
+
* @param string $filePath OPTIONAL File path to save captured outputs to - defaults to
|
110 |
+
* Ampersand_Db_Test_Config::getFilePath
|
111 |
+
* @throws Ampersand_Db_Test_Exception Thrown if no file path has been specified
|
112 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
113 |
+
*/
|
114 |
+
public static function disableCaptureAndSave($filePath = null)
|
115 |
+
{
|
116 |
+
$filePath = self::_prepareFilePath($filePath);
|
117 |
+
|
118 |
+
self::disableCapture();
|
119 |
+
self::saveCaptured($filePath);
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Adds a value to the array of captured PDO outputs
|
124 |
+
*
|
125 |
+
* @param string $method
|
126 |
+
* @param mixed $output
|
127 |
+
* @param string $hash OPTIONAL
|
128 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
129 |
+
*/
|
130 |
+
public static function addCapturedOutput($method, $output, $hash = null)
|
131 |
+
{
|
132 |
+
self::$_capturedOutputs[] = array(
|
133 |
+
'method' => $method,
|
134 |
+
'output' => $output,
|
135 |
+
'hash' => $hash,
|
136 |
+
);
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Enables fetching of previously captured and saved PDO outputs instead of calling actual PDO
|
141 |
+
* methods
|
142 |
+
*
|
143 |
+
* @param string $filePath OPTIONAL File path to fetch captured outputs from - defaults to
|
144 |
+
* Ampersand_Db_Test_Config::getFilePath
|
145 |
+
* @throws Ampersand_Db_Test_Exception Thrown if no file path has been specified
|
146 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
147 |
+
*/
|
148 |
+
public static function enableFetch($filePath = null)
|
149 |
+
{
|
150 |
+
self::_fetchOutputs($filePath);
|
151 |
+
|
152 |
+
self::$_isFetchEnabled = true;
|
153 |
+
self::disableCapture();
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Disables fetching of PDO outputs - PDO methods will be called instead and database queries
|
158 |
+
* will be made where appropriate
|
159 |
+
*
|
160 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
161 |
+
*/
|
162 |
+
public static function disableFetch()
|
163 |
+
{
|
164 |
+
self::$_isFetchEnabled = false;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Returns whether or not fetching of PDO outputs is currently enabled
|
169 |
+
*
|
170 |
+
* @return bool
|
171 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
172 |
+
*/
|
173 |
+
public static function getIsFetchEnabled()
|
174 |
+
{
|
175 |
+
return self::$_isFetchEnabled;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Fetches the next previously captured PDO output from the data source
|
180 |
+
*
|
181 |
+
* @param string $method OPTIONAL
|
182 |
+
* @return mixed
|
183 |
+
* @throws Ampersand_Db_Test_Exception Thrown if no file path has been specified
|
184 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
185 |
+
*/
|
186 |
+
public static function fetchNextOutput($method = null, $hash = null)
|
187 |
+
{
|
188 |
+
if (is_null(self::$_fetchedOutputs)) {
|
189 |
+
self::_fetchOutputs();
|
190 |
+
}
|
191 |
+
|
192 |
+
$outputData = array_shift(self::$_fetchedOutputs);
|
193 |
+
|
194 |
+
if (!is_null($method) && $method !== $outputData['method']) {
|
195 |
+
throw new Ampersand_Db_Test_Exception(
|
196 |
+
'Method mismatch when fetching captured PDO output at index '
|
197 |
+
. self::$_nrOfFetchedOutputs . '. Next output in queue is for method '
|
198 |
+
. "'{$outputData['method']}' but call was made to method '$method'."
|
199 |
+
);
|
200 |
+
}
|
201 |
+
if ($hash !== $outputData['hash']) {
|
202 |
+
throw new Ampersand_Db_Test_Exception(
|
203 |
+
'Hash mismatch when fetching captured PDO output at index '
|
204 |
+
. self::$_nrOfFetchedOutputs . '. Next output in queue has hash '
|
205 |
+
. "'{$outputData['hash']}' but the call that was made had hash '$hash'."
|
206 |
+
);
|
207 |
+
}
|
208 |
+
|
209 |
+
self::$_nrOfFetchedOutputs++;
|
210 |
+
|
211 |
+
return $outputData['output'];
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Fetches all of the captured PDO outputs from the data source so that they can subsequently
|
216 |
+
* be fetched one at a time
|
217 |
+
*
|
218 |
+
* @param string $filePath OPTIONAL File path to fetch captured outputs from - defaults to
|
219 |
+
* Ampersand_Db_Test_Config::getFilePath
|
220 |
+
* @throws Ampersand_Db_Test_Exception Thrown if no file path has been specified
|
221 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
222 |
+
*/
|
223 |
+
protected static function _fetchOutputs($filePath = null)
|
224 |
+
{
|
225 |
+
$filePath = self::_prepareFilePath($filePath);
|
226 |
+
|
227 |
+
if (!is_readable($filePath)) {
|
228 |
+
throw new Ampersand_Db_Test_Exception('Specified file path is not readable.');
|
229 |
+
}
|
230 |
+
|
231 |
+
$serialized = file_get_contents($filePath);
|
232 |
+
self::$_fetchedOutputs = unserialize($serialized);
|
233 |
+
self::$_nrOfFetchedOutputs = 0;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Returns the passed file path if it is set, otherwise returns
|
238 |
+
* Ampersand_Db_Test_Config::getFilePath
|
239 |
+
*
|
240 |
+
* @param string $filePath
|
241 |
+
* @return string
|
242 |
+
* @throws Ampersand_Db_Test_Exception Thrown if no file path has been specified
|
243 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
244 |
+
*/
|
245 |
+
protected static function _prepareFilePath($filePath)
|
246 |
+
{
|
247 |
+
if (!strlen($filePath)) {
|
248 |
+
$filePath = self::getFilePath();
|
249 |
+
}
|
250 |
+
|
251 |
+
if (!strlen($filePath)) {
|
252 |
+
throw new Ampersand_Db_Test_Exception('No file path specified.');
|
253 |
+
}
|
254 |
+
|
255 |
+
return $filePath;
|
256 |
+
}
|
257 |
+
}
|
lib/Ampersand/Db/Test/Connection.php
CHANGED
@@ -1,33 +1,45 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_Connection extends Ampersand_Db_Test_Abstract
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Creates a PDO object so that we have a database connection. Calls to $this will then be
|
6 |
+
* proxied to that PDO object
|
7 |
+
*
|
8 |
+
* @param string $dsn Data source name
|
9 |
+
* @param string $username
|
10 |
+
* @param string $password OPTIONAL
|
11 |
+
* @param array $driverOptions OPTIONAL
|
12 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
13 |
+
*/
|
14 |
+
public function __construct($dsn, $username, $password = null, array $driverOptions = array())
|
15 |
+
{
|
16 |
+
$this->_pdoInstance = new PDO($dsn, $username, $password, $driverOptions);
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Produces a hash string based on a method and the arguments passed to it. When fetching
|
21 |
+
* captured PDO outputs from the data source this hash can be used to verify that the correct
|
22 |
+
* output is being returned
|
23 |
+
*
|
24 |
+
* @param string $method
|
25 |
+
* @param array $arguments
|
26 |
+
* @return string
|
27 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
28 |
+
*/
|
29 |
+
protected function _hashMethodCall($method, array $arguments)
|
30 |
+
{
|
31 |
+
switch ($method) {
|
32 |
+
case 'exec':
|
33 |
+
case 'prepare':
|
34 |
+
case 'query':
|
35 |
+
case 'quote':
|
36 |
+
$subject = $arguments[0];
|
37 |
+
break;
|
38 |
+
|
39 |
+
default:
|
40 |
+
return null;
|
41 |
+
}
|
42 |
+
|
43 |
+
return md5($subject);
|
44 |
+
}
|
45 |
+
}
|
lib/Ampersand/Db/Test/Exception.php
CHANGED
@@ -1,10 +1,5 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
1dds+UIt4iQJv+yLAFUagVeNCnEM3D+bnqgei3gargH/g92D2I4/G/iEuWyE3U7GlYWp/MplnD9z
|
7 |
-
DBCAbgpb2B/0Cvtf0cMm51WnSvpfT6WAcv8B4X/DW6ZDRaKQPXEKV9+9db5Ac2MdBbHuKjn6OC5u
|
8 |
-
9fgV4S5QwGX5UHodUq4bMHZplKkm+Qhz0dugWejE7Xnw2fzXRZXnGbZcv/poNtcbnMEcMlGX2tTa
|
9 |
-
e4CTURHFHQkYiQCq+d+6eVw1GP6gE1bs+65i+2ulEguMRXd3VdmCnFk1B/S3DVWUfiXcL7psPLH/
|
10 |
-
ZPvCh4C211JcMGNNk7hqHcjrX9uNTRoqvLhh1zDbVk+QjqrashgQAHlQLsct2r6dC0==
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_Exception extends Exception // Do not extend Ampersand_Exception!
|
3 |
+
{
|
4 |
+
|
5 |
+
}
|
|
|
|
|
|
|
|
|
|
lib/Ampersand/Db/Test/MageResource.php
CHANGED
@@ -1,17 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
fwMnYlLUoGem6D3IYxBIU6TFIDBj9dIOSjRP+pWURH37aEO9Eh56Op+5IMioPvlfEmp+ZWWAAyvh
|
17 |
-
s+MHKEarJulqETTSYUYZwIDMGkRxm7MZSyFiZmlIy4PrD+O4euQcFv2ha1Y0+0==
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_MageResource extends Mage_Core_Model_Resource_Type_Db_Pdo_Mysql
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Causes Magento to use our test database adapter instead of its standard PDO adapter. This
|
6 |
+
* will not have any affect unless capturing or fetching is enabled in the test adapter
|
7 |
+
*
|
8 |
+
* @return string
|
9 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
10 |
+
*/
|
11 |
+
protected function _getDbAdapterClassName()
|
12 |
+
{
|
13 |
+
return 'Ampersand_Db_Test_Adapter';
|
14 |
+
}
|
15 |
+
}
|
|
|
|
lib/Ampersand/Db/Test/Output/Abstract.php
CHANGED
@@ -1,10 +1,5 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
H+52qREPLrzohsNMNonizUw8sIqD9XXI1rgKhfSS/vl2hLqMdymOIAZpiWqHOeYmIqJ/WVEAFjCU
|
7 |
-
1cwTzAok+ni3GKqiKK6O51WnSvpfT6WAcv8B4X/DZrS4+80OSo7lEfzxTj1pbpEBAtCzpFA+SUdz
|
8 |
-
EK8Na/Zu0ml9gQeSVPHZledUOva6axR+tb4VNSgRpPQ0xf9MDlOndx6bpkCEQqIOzQe2rJ4j9Zxe
|
9 |
-
DYG/vQlm8jCeCbPuTv53kzN2anrUL9Ph4Ym+k3ip4jSKjVNyjkOXo/JjoUlfAejeULf05/ZLQmQE
|
10 |
-
XlCsGOl3DYpZIt6MytkBOxolI7z4
|
1 |
+
<?php
|
2 |
+
abstract class Ampersand_Db_Test_Output_Abstract
|
3 |
+
{
|
4 |
+
|
5 |
+
}
|
|
|
|
|
|
|
|
|
|
lib/Ampersand/Db/Test/Output/Statement.php
CHANGED
@@ -1,11 +1,5 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
Q+NRz0ReVPkozPs7BDJxVt08WSgbNhsUEHYoUADdEj1/CCrAAUlDQon7ia+jxs92VwLTVGlGCzXo
|
7 |
-
Z8I99/UwZs8HP5sZBlmW51WnSvpfT6WAcv8B4X/DLMBGxAwFU2wLGXpQTW1Zbtxd9M+YFX9bWVgH
|
8 |
-
1g+oX5Vpkw1+BQcEW7Nj4lVauEGdDpItW1S9ukWZwlOUyrIYzUiV6ecVKgpkaFKt5Y2HUy924Kfl
|
9 |
-
gaGHKDTxO/5hJcTqqjxs08CpJhV3+I+kp8KuMAyFzAoQfMuktnmkgq5AAg+BOF2qGddKoI7FBeJX
|
10 |
-
FchQwjPI7cC+rKCarW1qbMNW2SC8MjFX1e0gaVDeA4aPTebZmnBeIbq8B6q0nsZN11MnADxeZFsA
|
11 |
-
n4JmYfxLW4PyU2/f+wwNbBjS2CsmIMH17ANBiBYp3IEIWSE+r+VbbkAXLTjS5ejwWA5Jkh1sjn8=
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_Output_Statement extends Ampersand_Db_Test_Output_Abstract
|
3 |
+
{
|
4 |
+
|
5 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
lib/Ampersand/Db/Test/Output/This.php
CHANGED
@@ -1,11 +1,5 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
PuuWikMTJBkQuwraCBuF55Yw56/oifWvPMqi/12m2zx5ror2/jv4D8DhUCnGrs89tFappq195dNp
|
7 |
-
qp1cXL6S/c9AYc7aSa9k51WnSvpfT6WAcv8B4X/D1MDayQTilfrogW0dTgXFbnBNinKQKKvM6es3
|
8 |
-
hR5terhncjGTk4WetatCa8UnqOb6PIbkPagQFZ6WWdFZrOZ0Mk6MTjyYTeoQL12BhZ2B0b2TFeXj
|
9 |
-
4fDE7d4Jr8MmdPiF2MFGUK3oho9b5OZ2zVyV5pZfjOglqu7yTRdtGXHIWvP/ghMzMgCmjBR4j7s9
|
10 |
-
/WemCziYy+CS1qFVEgO/lM6FGAab7wfqs4uC1lLIPHt3Cxd48NzA2M9v8S/IAZ2oMVy5/V5u+9yU
|
11 |
-
pDzFQuxa6+TucnNpyTH/OSGBr2BA9Qx9bcrfNVxLxcIgPAsIq97GFWcgTnJ/XaQIDxUw07IzOm==
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_Output_This extends Ampersand_Db_Test_Output_Abstract
|
3 |
+
{
|
4 |
+
|
5 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
lib/Ampersand/Db/Test/Statement.php
CHANGED
@@ -1,36 +1,55 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Db_Test_Statement extends Ampersand_Db_Test_Abstract implements IteratorAggregate
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Creates a PDOStatement object so that we can make calls to the database. Calls to $this will
|
6 |
+
* then be proxied to that PDOStatement object
|
7 |
+
*
|
8 |
+
* @param PDOStatement $pdoStatement OPTIONAL Manually provide the PDOStatement instance to
|
9 |
+
* proxy to; necessary when PDO internally generates an instance of PDOStatement
|
10 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
11 |
+
*/
|
12 |
+
public function __construct(PDOStatement $pdoStatement = null)
|
13 |
+
{
|
14 |
+
$this->_pdoInstance = $pdoStatement ? $pdoStatement : new PDOStatement();
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Returns the PDOStatement instance to iterate over. This method is required by
|
19 |
+
* IteratorAggregate interface
|
20 |
+
*
|
21 |
+
* @return PDOStatement
|
22 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
23 |
+
*
|
24 |
+
* @todo Implement Iterator instead of IteratorAggregate and return capture statement instances
|
25 |
+
* instead of PDOStatement instances
|
26 |
+
*/
|
27 |
+
public function getIterator()
|
28 |
+
{
|
29 |
+
return $this->_pdoInstance;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Produces a hash string based on a method and the arguments passed to it. When fetching
|
34 |
+
* captured PDO outputs from the data source this hash can be used to verify that the correct
|
35 |
+
* output is being returned
|
36 |
+
*
|
37 |
+
* @param string $method
|
38 |
+
* @param array $arguments
|
39 |
+
* @return string
|
40 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
41 |
+
*/
|
42 |
+
protected function _hashMethodCall($method, array $arguments)
|
43 |
+
{
|
44 |
+
switch ($method) {
|
45 |
+
case 'bindParam':
|
46 |
+
$subject = $arguments[0] . ' : ' . (string) $arguments[1];
|
47 |
+
break;
|
48 |
+
|
49 |
+
default:
|
50 |
+
return null;
|
51 |
+
}
|
52 |
+
|
53 |
+
return md5($subject);
|
54 |
+
}
|
55 |
+
}
|
lib/Ampersand/Deprecate.php
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Deprecate
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Deprecate
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Deprecate
|
17 |
+
{
|
18 |
+
/* static functionality */
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Logs that a call was made to a deprecated method. Optionally allows for a custom message to
|
22 |
+
* be included in the logged data
|
23 |
+
*
|
24 |
+
* @param string $message OPTIONAL
|
25 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
26 |
+
*/
|
27 |
+
public static function log($message = null)
|
28 |
+
{
|
29 |
+
$singleton = self::getSingleton();
|
30 |
+
|
31 |
+
$description = $singleton->_getDescription();
|
32 |
+
|
33 |
+
$singleton->_mageLog(
|
34 |
+
$singleton->_getTextToLog($description, $message)
|
35 |
+
);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Sets a filename to be used when logging calls to Ampersand_Deprecate::log method
|
40 |
+
*
|
41 |
+
* @param string $filename
|
42 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
43 |
+
*/
|
44 |
+
public static function setLogFilename($filename)
|
45 |
+
{
|
46 |
+
self::getSingleton()->_logFilename = $filename;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Returns the current singleton instance of this class as stored in the registry
|
51 |
+
*
|
52 |
+
* @return Ampersand_Deprecate
|
53 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
54 |
+
*/
|
55 |
+
public static function getSingleton()
|
56 |
+
{
|
57 |
+
if (!Ampersand_Deprecate_Registry::has('singleton')) {
|
58 |
+
Ampersand_Deprecate_Registry::set(
|
59 |
+
'singleton', new Ampersand_Deprecate
|
60 |
+
);
|
61 |
+
}
|
62 |
+
|
63 |
+
return Ampersand_Deprecate_Registry::get('singleton');
|
64 |
+
}
|
65 |
+
|
66 |
+
/* non-static functionality */
|
67 |
+
|
68 |
+
protected $_logFilename = 'ampersand-deprecate.log';
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Passes the provided data structure to Mage::log together with the log filename which
|
72 |
+
* Ampersand_Deprecate is configured to use
|
73 |
+
*
|
74 |
+
* @param mixed $data
|
75 |
+
* @return void
|
76 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
77 |
+
*/
|
78 |
+
protected function _mageLog($data)
|
79 |
+
{
|
80 |
+
if (!class_exists('Mage')) {
|
81 |
+
return;
|
82 |
+
}
|
83 |
+
|
84 |
+
Mage::log($data, null, $this->_logFilename);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Gets a description of the call which was made to the deprecated method
|
89 |
+
*
|
90 |
+
* @param int $backtraceLevel OPTIONAL The number of backtrace elements to ignore when working
|
91 |
+
* out which class and method is referencing the deprecate class. If _getDescription is called
|
92 |
+
* from a public method within Ampersand_Deprecate which is itself called from the deprecated
|
93 |
+
* method then this parameter should be 1; if the backtrace contains two method calls between
|
94 |
+
* _getDescription and the deprecated method then this parameter should be 2, etc.
|
95 |
+
* @return string
|
96 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
97 |
+
*/
|
98 |
+
protected function _getDescription($backtraceLevel = 1)
|
99 |
+
{
|
100 |
+
$backtrace = debug_backtrace(false);
|
101 |
+
|
102 |
+
if (1 + $backtraceLevel >= count($backtrace)) {
|
103 |
+
return null;
|
104 |
+
}
|
105 |
+
|
106 |
+
return sprintf(
|
107 |
+
"%s::%s is deprecated according to %s(%s) but was called by %s(%s)",
|
108 |
+
$backtrace[1 + $backtraceLevel]['class'], $backtrace[1 + $backtraceLevel]['function'],
|
109 |
+
$backtrace[$backtraceLevel]['file'], $backtrace[$backtraceLevel]['line'],
|
110 |
+
$backtrace[1 + $backtraceLevel]['file'], $backtrace[1 + $backtraceLevel]['line']
|
111 |
+
);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Returns a single string based on a derived description of the call to the deprecated method
|
116 |
+
* and an optional custom message provided within the deprecated code
|
117 |
+
*
|
118 |
+
* @param string $description
|
119 |
+
* @param null|string $customMessage
|
120 |
+
* @return string
|
121 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
122 |
+
*/
|
123 |
+
protected function _getTextToLog($description, $customMessage)
|
124 |
+
{
|
125 |
+
if (!is_null($customMessage)) {
|
126 |
+
$description .= "\nCustom message: '$customMessage'";
|
127 |
+
}
|
128 |
+
|
129 |
+
$e = new Exception;
|
130 |
+
$description .= "\nTrace:\n{$e->getTraceAsString()}";
|
131 |
+
|
132 |
+
return $description;
|
133 |
+
}
|
134 |
+
}
|
lib/Ampersand/Deprecate/Registry.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Deprecate
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Deprecate
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Deprecate_Registry extends Ampersand_Registry_Abstract
|
17 |
+
{
|
18 |
+
const REGISTRY_NAMESPACE = 'Ampersand_Deprecate';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Resets the registry
|
22 |
+
*
|
23 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
24 |
+
*/
|
25 |
+
public static function reset()
|
26 |
+
{
|
27 |
+
Ampersand_Registry::reset(self::REGISTRY_NAMESPACE);
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Gets a value from the container instance
|
32 |
+
*
|
33 |
+
* @param string $key
|
34 |
+
* @return mixed
|
35 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
36 |
+
*/
|
37 |
+
public static function get($key)
|
38 |
+
{
|
39 |
+
return Ampersand_Registry::get($key, self::REGISTRY_NAMESPACE);
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Sets a value in the container instance
|
44 |
+
*
|
45 |
+
* @param string $key
|
46 |
+
* @param mixed $value
|
47 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
48 |
+
*/
|
49 |
+
public static function set($key, $value)
|
50 |
+
{
|
51 |
+
Ampersand_Registry::set($key, $value, self::REGISTRY_NAMESPACE);
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Returns whether or not a key exists in the container instance
|
56 |
+
*
|
57 |
+
* @param string $key
|
58 |
+
* @return bool
|
59 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
60 |
+
*/
|
61 |
+
public static function has($key)
|
62 |
+
{
|
63 |
+
return Ampersand_Registry::has($key, self::REGISTRY_NAMESPACE);
|
64 |
+
}
|
65 |
+
}
|
lib/Ampersand/Exception.php
CHANGED
@@ -1,12 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Exception extends Exception
|
17 |
+
{
|
18 |
+
|
19 |
+
}
|
lib/Ampersand/Filter/Compress.php
CHANGED
@@ -1,37 +1,44 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento 1.4.1.1 is missing Zend_Filter_Compress, so we include the
|
4 |
+
* Zend_Filter_Compress file and folder from Magento 1.6.0.0.
|
5 |
+
*/
|
6 |
+
if (!class_exists('Zend_Filter_Compress')) {
|
7 |
+
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__));
|
8 |
+
}
|
9 |
+
class Ampersand_Filter_Compress extends Zend_Filter_Compress
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Returns the current adapter, instantiating it if necessary
|
13 |
+
*
|
14 |
+
* Ampersand bugfix relating to errors:
|
15 |
+
* - Warning: include(Zip.php): failed to open stream: No such file or directory
|
16 |
+
* - Warning: include(): Failed opening 'Zip.php' for inclusion
|
17 |
+
*
|
18 |
+
* @return string
|
19 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
20 |
+
*/
|
21 |
+
public function getAdapter()
|
22 |
+
{
|
23 |
+
if ($this->_adapter instanceof Zend_Filter_Compress_CompressInterface) {
|
24 |
+
return $this->_adapter;
|
25 |
+
}
|
26 |
+
|
27 |
+
$adapter = $this->_adapter;
|
28 |
+
$options = $this->getAdapterOptions();
|
29 |
+
if (!class_exists($adapter, false)) { // autoload 'false' added by Ampersand
|
30 |
+
#require_once 'Zend/Loader.php';
|
31 |
+
if (Zend_Loader::isReadable('Zend/Filter/Compress/' . ucfirst($adapter) . '.php')) {
|
32 |
+
$adapter = 'Zend_Filter_Compress_' . ucfirst($adapter);
|
33 |
+
}
|
34 |
+
Zend_Loader::loadClass($adapter);
|
35 |
+
}
|
36 |
+
|
37 |
+
$this->_adapter = new $adapter($options);
|
38 |
+
if (!$this->_adapter instanceof Zend_Filter_Compress_CompressInterface) {
|
39 |
+
#require_once 'Zend/Filter/Exception.php';
|
40 |
+
throw new Zend_Filter_Exception("Compression adapter '" . $adapter . "' does not implement Zend_Filter_Compress_CompressInterface");
|
41 |
+
}
|
42 |
+
return $this->_adapter;
|
43 |
+
}
|
44 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress.php
CHANGED
@@ -1,81 +1,197 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: Compress.php 20096 2010-01-06 02:05:09Z bkarwin $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Interface
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Interface.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Compresses a given string
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
class Zend_Filter_Compress implements Zend_Filter_Interface
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Compression adapter
|
39 |
+
*/
|
40 |
+
protected $_adapter = 'Gz';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Compression adapter constructor options
|
44 |
+
*/
|
45 |
+
protected $_adapterOptions = array();
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Class constructor
|
49 |
+
*
|
50 |
+
* @param string|array $options (Optional) Options to set
|
51 |
+
*/
|
52 |
+
public function __construct($options = null)
|
53 |
+
{
|
54 |
+
if ($options instanceof Zend_Config) {
|
55 |
+
$options = $options->toArray();
|
56 |
+
}
|
57 |
+
if (is_string($options)) {
|
58 |
+
$this->setAdapter($options);
|
59 |
+
} elseif ($options instanceof Zend_Filter_Compress_CompressInterface) {
|
60 |
+
$this->setAdapter($options);
|
61 |
+
} elseif (is_array($options)) {
|
62 |
+
$this->setOptions($options);
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Set filter setate
|
68 |
+
*
|
69 |
+
* @param array $options
|
70 |
+
* @return Zend_Filter_Compress
|
71 |
+
*/
|
72 |
+
public function setOptions(array $options)
|
73 |
+
{
|
74 |
+
foreach ($options as $key => $value) {
|
75 |
+
if ($key == 'options') {
|
76 |
+
$key = 'adapterOptions';
|
77 |
+
}
|
78 |
+
$method = 'set' . ucfirst($key);
|
79 |
+
if (method_exists($this, $method)) {
|
80 |
+
$this->$method($value);
|
81 |
+
}
|
82 |
+
}
|
83 |
+
return $this;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Returns the current adapter, instantiating it if necessary
|
88 |
+
*
|
89 |
+
* @return string
|
90 |
+
*/
|
91 |
+
public function getAdapter()
|
92 |
+
{
|
93 |
+
if ($this->_adapter instanceof Zend_Filter_Compress_CompressInterface) {
|
94 |
+
return $this->_adapter;
|
95 |
+
}
|
96 |
+
|
97 |
+
$adapter = $this->_adapter;
|
98 |
+
$options = $this->getAdapterOptions();
|
99 |
+
if (!class_exists($adapter)) {
|
100 |
+
#require_once 'Zend/Loader.php';
|
101 |
+
if (Zend_Loader::isReadable('Zend/Filter/Compress/' . ucfirst($adapter) . '.php')) {
|
102 |
+
$adapter = 'Zend_Filter_Compress_' . ucfirst($adapter);
|
103 |
+
}
|
104 |
+
Zend_Loader::loadClass($adapter);
|
105 |
+
}
|
106 |
+
|
107 |
+
$this->_adapter = new $adapter($options);
|
108 |
+
if (!$this->_adapter instanceof Zend_Filter_Compress_CompressInterface) {
|
109 |
+
#require_once 'Zend/Filter/Exception.php';
|
110 |
+
throw new Zend_Filter_Exception("Compression adapter '" . $adapter . "' does not implement Zend_Filter_Compress_CompressInterface");
|
111 |
+
}
|
112 |
+
return $this->_adapter;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Retrieve adapter name
|
117 |
+
*
|
118 |
+
* @return string
|
119 |
+
*/
|
120 |
+
public function getAdapterName()
|
121 |
+
{
|
122 |
+
return $this->getAdapter()->toString();
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Sets compression adapter
|
127 |
+
*
|
128 |
+
* @param string|Zend_Filter_Compress_CompressInterface $adapter Adapter to use
|
129 |
+
* @return Zend_Filter_Compress
|
130 |
+
*/
|
131 |
+
public function setAdapter($adapter)
|
132 |
+
{
|
133 |
+
if ($adapter instanceof Zend_Filter_Compress_CompressInterface) {
|
134 |
+
$this->_adapter = $adapter;
|
135 |
+
return $this;
|
136 |
+
}
|
137 |
+
if (!is_string($adapter)) {
|
138 |
+
#require_once 'Zend/Filter/Exception.php';
|
139 |
+
throw new Zend_Filter_Exception('Invalid adapter provided; must be string or instance of Zend_Filter_Compress_CompressInterface');
|
140 |
+
}
|
141 |
+
$this->_adapter = $adapter;
|
142 |
+
|
143 |
+
return $this;
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Retrieve adapter options
|
148 |
+
*
|
149 |
+
* @return array
|
150 |
+
*/
|
151 |
+
public function getAdapterOptions()
|
152 |
+
{
|
153 |
+
return $this->_adapterOptions;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Set adapter options
|
158 |
+
*
|
159 |
+
* @param array $options
|
160 |
+
* @return void
|
161 |
+
*/
|
162 |
+
public function setAdapterOptions(array $options)
|
163 |
+
{
|
164 |
+
$this->_adapterOptions = $options;
|
165 |
+
return $this;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Calls adapter methods
|
170 |
+
*
|
171 |
+
* @param string $method Method to call
|
172 |
+
* @param string|array $options Options for this method
|
173 |
+
*/
|
174 |
+
public function __call($method, $options)
|
175 |
+
{
|
176 |
+
$adapter = $this->getAdapter();
|
177 |
+
if (!method_exists($adapter, $method)) {
|
178 |
+
#require_once 'Zend/Filter/Exception.php';
|
179 |
+
throw new Zend_Filter_Exception("Unknown method '{$method}'");
|
180 |
+
}
|
181 |
+
|
182 |
+
return call_user_func_array(array($adapter, $method), $options);
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Defined by Zend_Filter_Interface
|
187 |
+
*
|
188 |
+
* Compresses the content $value with the defined settings
|
189 |
+
*
|
190 |
+
* @param string $value Content to compress
|
191 |
+
* @return string The compressed content
|
192 |
+
*/
|
193 |
+
public function filter($value)
|
194 |
+
{
|
195 |
+
return $this->getAdapter()->compress($value);
|
196 |
+
}
|
197 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/Bz2.php
CHANGED
@@ -1,68 +1,188 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: Bz2.php 20096 2010-01-06 02:05:09Z bkarwin $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Compress_CompressAbstract
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Compress/CompressAbstract.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Compression adapter for Bz2
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
class Zend_Filter_Compress_Bz2 extends Zend_Filter_Compress_CompressAbstract
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Compression Options
|
39 |
+
* array(
|
40 |
+
* 'blocksize' => Blocksize to use from 0-9
|
41 |
+
* 'archive' => Archive to use
|
42 |
+
* )
|
43 |
+
*
|
44 |
+
* @var array
|
45 |
+
*/
|
46 |
+
protected $_options = array(
|
47 |
+
'blocksize' => 4,
|
48 |
+
'archive' => null,
|
49 |
+
);
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Class constructor
|
53 |
+
*
|
54 |
+
* @param array|Zend_Config $options (Optional) Options to set
|
55 |
+
*/
|
56 |
+
public function __construct($options = null)
|
57 |
+
{
|
58 |
+
if (!extension_loaded('bz2')) {
|
59 |
+
#require_once 'Zend/Filter/Exception.php';
|
60 |
+
throw new Zend_Filter_Exception('This filter needs the bz2 extension');
|
61 |
+
}
|
62 |
+
parent::__construct($options);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Returns the set blocksize
|
67 |
+
*
|
68 |
+
* @return integer
|
69 |
+
*/
|
70 |
+
public function getBlocksize()
|
71 |
+
{
|
72 |
+
return $this->_options['blocksize'];
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Sets a new blocksize
|
77 |
+
*
|
78 |
+
* @param integer $level
|
79 |
+
* @return Zend_Filter_Compress_Bz2
|
80 |
+
*/
|
81 |
+
public function setBlocksize($blocksize)
|
82 |
+
{
|
83 |
+
if (($blocksize < 0) || ($blocksize > 9)) {
|
84 |
+
#require_once 'Zend/Filter/Exception.php';
|
85 |
+
throw new Zend_Filter_Exception('Blocksize must be between 0 and 9');
|
86 |
+
}
|
87 |
+
|
88 |
+
$this->_options['blocksize'] = (int) $blocksize;
|
89 |
+
return $this;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Returns the set archive
|
94 |
+
*
|
95 |
+
* @return string
|
96 |
+
*/
|
97 |
+
public function getArchive()
|
98 |
+
{
|
99 |
+
return $this->_options['archive'];
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Sets the archive to use for de-/compression
|
104 |
+
*
|
105 |
+
* @param string $archive Archive to use
|
106 |
+
* @return Zend_Filter_Compress_Bz2
|
107 |
+
*/
|
108 |
+
public function setArchive($archive)
|
109 |
+
{
|
110 |
+
$this->_options['archive'] = (string) $archive;
|
111 |
+
return $this;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Compresses the given content
|
116 |
+
*
|
117 |
+
* @param string $content
|
118 |
+
* @return string
|
119 |
+
*/
|
120 |
+
public function compress($content)
|
121 |
+
{
|
122 |
+
$archive = $this->getArchive();
|
123 |
+
if (!empty($archive)) {
|
124 |
+
$file = bzopen($archive, 'w');
|
125 |
+
if (!$file) {
|
126 |
+
#require_once 'Zend/Filter/Exception.php';
|
127 |
+
throw new Zend_Filter_Exception("Error opening the archive '" . $archive . "'");
|
128 |
+
}
|
129 |
+
|
130 |
+
bzwrite($file, $content);
|
131 |
+
bzclose($file);
|
132 |
+
$compressed = true;
|
133 |
+
} else {
|
134 |
+
$compressed = bzcompress($content, $this->getBlocksize());
|
135 |
+
}
|
136 |
+
|
137 |
+
if (is_int($compressed)) {
|
138 |
+
#require_once 'Zend/Filter/Exception.php';
|
139 |
+
throw new Zend_Filter_Exception('Error during compression');
|
140 |
+
}
|
141 |
+
|
142 |
+
return $compressed;
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Decompresses the given content
|
147 |
+
*
|
148 |
+
* @param string $content
|
149 |
+
* @return string
|
150 |
+
*/
|
151 |
+
public function decompress($content)
|
152 |
+
{
|
153 |
+
$archive = $this->getArchive();
|
154 |
+
if (file_exists($content)) {
|
155 |
+
$archive = $content;
|
156 |
+
}
|
157 |
+
|
158 |
+
if (file_exists($archive)) {
|
159 |
+
$file = bzopen($archive, 'r');
|
160 |
+
if (!$file) {
|
161 |
+
#require_once 'Zend/Filter/Exception.php';
|
162 |
+
throw new Zend_Filter_Exception("Error opening the archive '" . $content . "'");
|
163 |
+
}
|
164 |
+
|
165 |
+
$compressed = bzread($file);
|
166 |
+
bzclose($file);
|
167 |
+
} else {
|
168 |
+
$compressed = bzdecompress($content);
|
169 |
+
}
|
170 |
+
|
171 |
+
if (is_int($compressed)) {
|
172 |
+
#require_once 'Zend/Filter/Exception.php';
|
173 |
+
throw new Zend_Filter_Exception('Error during decompression');
|
174 |
+
}
|
175 |
+
|
176 |
+
return $compressed;
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Returns the adapter name
|
181 |
+
*
|
182 |
+
* @return string
|
183 |
+
*/
|
184 |
+
public function toString()
|
185 |
+
{
|
186 |
+
return 'Bz2';
|
187 |
+
}
|
188 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/CompressAbstract.php
CHANGED
@@ -1,38 +1,89 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: CompressAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Compress_CompressInterface
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Compress/CompressInterface.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Abstract compression adapter
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
abstract class Zend_Filter_Compress_CompressAbstract implements Zend_Filter_Compress_CompressInterface
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Class constructor
|
39 |
+
*
|
40 |
+
* @param array|Zend_Config $options (Optional) Options to set
|
41 |
+
*/
|
42 |
+
public function __construct($options = null)
|
43 |
+
{
|
44 |
+
if ($options instanceof Zend_Config) {
|
45 |
+
$options = $options->toArray();
|
46 |
+
}
|
47 |
+
|
48 |
+
if (is_array($options)) {
|
49 |
+
$this->setOptions($options);
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Returns one or all set options
|
55 |
+
*
|
56 |
+
* @param string $option (Optional) Option to return
|
57 |
+
* @return mixed
|
58 |
+
*/
|
59 |
+
public function getOptions($option = null)
|
60 |
+
{
|
61 |
+
if ($option === null) {
|
62 |
+
return $this->_options;
|
63 |
+
}
|
64 |
+
|
65 |
+
if (!array_key_exists($option, $this->_options)) {
|
66 |
+
return null;
|
67 |
+
}
|
68 |
+
|
69 |
+
return $this->_options[$option];
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Sets all or one option
|
74 |
+
*
|
75 |
+
* @param array $options
|
76 |
+
* @return Zend_Filter_Compress_Bz2
|
77 |
+
*/
|
78 |
+
public function setOptions(array $options)
|
79 |
+
{
|
80 |
+
foreach ($options as $key => $option) {
|
81 |
+
$method = 'set' . $key;
|
82 |
+
if (method_exists($this, $method)) {
|
83 |
+
$this->$method($option);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/CompressInterface.php
CHANGED
@@ -1,20 +1,54 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: CompressInterface.php 20096 2010-01-06 02:05:09Z bkarwin $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Compression interface
|
24 |
+
*
|
25 |
+
* @category Zend
|
26 |
+
* @package Zend_Filter
|
27 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
28 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
29 |
+
*/
|
30 |
+
interface Zend_Filter_Compress_CompressInterface
|
31 |
+
{
|
32 |
+
/**
|
33 |
+
* Compresses $value with the defined settings
|
34 |
+
*
|
35 |
+
* @param string $value Data to compress
|
36 |
+
* @return string The compressed data
|
37 |
+
*/
|
38 |
+
public function compress($value);
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Decompresses $value with the defined settings
|
42 |
+
*
|
43 |
+
* @param string $value Data to decompress
|
44 |
+
* @return string The decompressed data
|
45 |
+
*/
|
46 |
+
public function decompress($value);
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Return the adapter name
|
50 |
+
*
|
51 |
+
* @return string
|
52 |
+
*/
|
53 |
+
public function toString();
|
54 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/Gz.php
CHANGED
@@ -1,89 +1,228 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: Gz.php 20096 2010-01-06 02:05:09Z bkarwin $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Compress_CompressAbstract
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Compress/CompressAbstract.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Compression adapter for Gzip (ZLib)
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
class Zend_Filter_Compress_Gz extends Zend_Filter_Compress_CompressAbstract
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Compression Options
|
39 |
+
* array(
|
40 |
+
* 'level' => Compression level 0-9
|
41 |
+
* 'mode' => Compression mode, can be 'compress', 'deflate'
|
42 |
+
* 'archive' => Archive to use
|
43 |
+
* )
|
44 |
+
*
|
45 |
+
* @var array
|
46 |
+
*/
|
47 |
+
protected $_options = array(
|
48 |
+
'level' => 9,
|
49 |
+
'mode' => 'compress',
|
50 |
+
'archive' => null,
|
51 |
+
);
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Class constructor
|
55 |
+
*
|
56 |
+
* @param array|Zend_Config|null $options (Optional) Options to set
|
57 |
+
*/
|
58 |
+
public function __construct($options = null)
|
59 |
+
{
|
60 |
+
if (!extension_loaded('zlib')) {
|
61 |
+
#require_once 'Zend/Filter/Exception.php';
|
62 |
+
throw new Zend_Filter_Exception('This filter needs the zlib extension');
|
63 |
+
}
|
64 |
+
parent::__construct($options);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Returns the set compression level
|
69 |
+
*
|
70 |
+
* @return integer
|
71 |
+
*/
|
72 |
+
public function getLevel()
|
73 |
+
{
|
74 |
+
return $this->_options['level'];
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Sets a new compression level
|
79 |
+
*
|
80 |
+
* @param integer $level
|
81 |
+
* @return Zend_Filter_Compress_Gz
|
82 |
+
*/
|
83 |
+
public function setLevel($level)
|
84 |
+
{
|
85 |
+
if (($level < 0) || ($level > 9)) {
|
86 |
+
#require_once 'Zend/Filter/Exception.php';
|
87 |
+
throw new Zend_Filter_Exception('Level must be between 0 and 9');
|
88 |
+
}
|
89 |
+
|
90 |
+
$this->_options['level'] = (int) $level;
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Returns the set compression mode
|
96 |
+
*
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
public function getMode()
|
100 |
+
{
|
101 |
+
return $this->_options['mode'];
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Sets a new compression mode
|
106 |
+
*
|
107 |
+
* @param string $mode Supported are 'compress', 'deflate' and 'file'
|
108 |
+
*/
|
109 |
+
public function setMode($mode)
|
110 |
+
{
|
111 |
+
if (($mode != 'compress') && ($mode != 'deflate')) {
|
112 |
+
#require_once 'Zend/Filter/Exception.php';
|
113 |
+
throw new Zend_Filter_Exception('Given compression mode not supported');
|
114 |
+
}
|
115 |
+
|
116 |
+
$this->_options['mode'] = $mode;
|
117 |
+
return $this;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Returns the set archive
|
122 |
+
*
|
123 |
+
* @return string
|
124 |
+
*/
|
125 |
+
public function getArchive()
|
126 |
+
{
|
127 |
+
return $this->_options['archive'];
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Sets the archive to use for de-/compression
|
132 |
+
*
|
133 |
+
* @param string $archive Archive to use
|
134 |
+
* @return Zend_Filter_Compress_Gz
|
135 |
+
*/
|
136 |
+
public function setArchive($archive)
|
137 |
+
{
|
138 |
+
$this->_options['archive'] = (string) $archive;
|
139 |
+
return $this;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Compresses the given content
|
144 |
+
*
|
145 |
+
* @param string $content
|
146 |
+
* @return string
|
147 |
+
*/
|
148 |
+
public function compress($content)
|
149 |
+
{
|
150 |
+
$archive = $this->getArchive();
|
151 |
+
if (!empty($archive)) {
|
152 |
+
$file = gzopen($archive, 'w' . $this->getLevel());
|
153 |
+
if (!$file) {
|
154 |
+
#require_once 'Zend/Filter/Exception.php';
|
155 |
+
throw new Zend_Filter_Exception("Error opening the archive '" . $this->_options['archive'] . "'");
|
156 |
+
}
|
157 |
+
|
158 |
+
gzwrite($file, $content);
|
159 |
+
gzclose($file);
|
160 |
+
$compressed = true;
|
161 |
+
} else if ($this->_options['mode'] == 'deflate') {
|
162 |
+
$compressed = gzdeflate($content, $this->getLevel());
|
163 |
+
} else {
|
164 |
+
$compressed = gzcompress($content, $this->getLevel());
|
165 |
+
}
|
166 |
+
|
167 |
+
if (!$compressed) {
|
168 |
+
#require_once 'Zend/Filter/Exception.php';
|
169 |
+
throw new Zend_Filter_Exception('Error during compression');
|
170 |
+
}
|
171 |
+
|
172 |
+
return $compressed;
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Decompresses the given content
|
177 |
+
*
|
178 |
+
* @param string $content
|
179 |
+
* @return string
|
180 |
+
*/
|
181 |
+
public function decompress($content)
|
182 |
+
{
|
183 |
+
$archive = $this->getArchive();
|
184 |
+
$mode = $this->getMode();
|
185 |
+
if (file_exists($content)) {
|
186 |
+
$archive = $content;
|
187 |
+
}
|
188 |
+
|
189 |
+
if (file_exists($archive)) {
|
190 |
+
$handler = fopen($archive, "rb");
|
191 |
+
if (!$handler) {
|
192 |
+
#require_once 'Zend/Filter/Exception.php';
|
193 |
+
throw new Zend_Filter_Exception("Error opening the archive '" . $archive . "'");
|
194 |
+
}
|
195 |
+
|
196 |
+
fseek($handler, -4, SEEK_END);
|
197 |
+
$packet = fread($handler, 4);
|
198 |
+
$bytes = unpack("V", $packet);
|
199 |
+
$size = end($bytes);
|
200 |
+
fclose($handler);
|
201 |
+
|
202 |
+
$file = gzopen($archive, 'r');
|
203 |
+
$compressed = gzread($file, $size);
|
204 |
+
gzclose($file);
|
205 |
+
} else if ($mode == 'deflate') {
|
206 |
+
$compressed = gzinflate($content);
|
207 |
+
} else {
|
208 |
+
$compressed = gzuncompress($content);
|
209 |
+
}
|
210 |
+
|
211 |
+
if (!$compressed) {
|
212 |
+
#require_once 'Zend/Filter/Exception.php';
|
213 |
+
throw new Zend_Filter_Exception('Error during compression');
|
214 |
+
}
|
215 |
+
|
216 |
+
return $compressed;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Returns the adapter name
|
221 |
+
*
|
222 |
+
* @return string
|
223 |
+
*/
|
224 |
+
public function toString()
|
225 |
+
{
|
226 |
+
return 'Gz';
|
227 |
+
}
|
228 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/Lzf.php
CHANGED
@@ -1,32 +1,91 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: Lzf.php 20096 2010-01-06 02:05:09Z bkarwin $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Compress_CompressInterface
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Compress/CompressInterface.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Compression adapter for Lzf
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
class Zend_Filter_Compress_Lzf implements Zend_Filter_Compress_CompressInterface
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Class constructor
|
39 |
+
*/
|
40 |
+
public function __construct()
|
41 |
+
{
|
42 |
+
if (!extension_loaded('lzf')) {
|
43 |
+
#require_once 'Zend/Filter/Exception.php';
|
44 |
+
throw new Zend_Filter_Exception('This filter needs the lzf extension');
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Compresses the given content
|
50 |
+
*
|
51 |
+
* @param string $content
|
52 |
+
* @return string
|
53 |
+
*/
|
54 |
+
public function compress($content)
|
55 |
+
{
|
56 |
+
$compressed = lzf_compress($content);
|
57 |
+
if (!$compressed) {
|
58 |
+
#require_once 'Zend/Filter/Exception.php';
|
59 |
+
throw new Zend_Filter_Exception('Error during compression');
|
60 |
+
}
|
61 |
+
|
62 |
+
return $compressed;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Decompresses the given content
|
67 |
+
*
|
68 |
+
* @param string $content
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
public function decompress($content)
|
72 |
+
{
|
73 |
+
$compressed = lzf_decompress($content);
|
74 |
+
if (!$compressed) {
|
75 |
+
#require_once 'Zend/Filter/Exception.php';
|
76 |
+
throw new Zend_Filter_Exception('Error during compression');
|
77 |
+
}
|
78 |
+
|
79 |
+
return $compressed;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Returns the adapter name
|
84 |
+
*
|
85 |
+
* @return string
|
86 |
+
*/
|
87 |
+
public function toString()
|
88 |
+
{
|
89 |
+
return 'Lzf';
|
90 |
+
}
|
91 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/Rar.php
CHANGED
@@ -1,93 +1,252 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: Rar.php 22662 2010-07-24 17:37:36Z mabe $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Compress_CompressAbstract
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Compress/CompressAbstract.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Compression adapter for Rar
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
class Zend_Filter_Compress_Rar extends Zend_Filter_Compress_CompressAbstract
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Compression Options
|
39 |
+
* array(
|
40 |
+
* 'callback' => Callback for compression
|
41 |
+
* 'archive' => Archive to use
|
42 |
+
* 'password' => Password to use
|
43 |
+
* 'target' => Target to write the files to
|
44 |
+
* )
|
45 |
+
*
|
46 |
+
* @var array
|
47 |
+
*/
|
48 |
+
protected $_options = array(
|
49 |
+
'callback' => null,
|
50 |
+
'archive' => null,
|
51 |
+
'password' => null,
|
52 |
+
'target' => '.',
|
53 |
+
);
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Class constructor
|
57 |
+
*
|
58 |
+
* @param array $options (Optional) Options to set
|
59 |
+
*/
|
60 |
+
public function __construct($options = null)
|
61 |
+
{
|
62 |
+
if (!extension_loaded('rar')) {
|
63 |
+
#require_once 'Zend/Filter/Exception.php';
|
64 |
+
throw new Zend_Filter_Exception('This filter needs the rar extension');
|
65 |
+
}
|
66 |
+
parent::__construct($options);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Returns the set callback for compression
|
71 |
+
*
|
72 |
+
* @return string
|
73 |
+
*/
|
74 |
+
public function getCallback()
|
75 |
+
{
|
76 |
+
return $this->_options['callback'];
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Sets the callback to use
|
81 |
+
*
|
82 |
+
* @param string $callback
|
83 |
+
* @return Zend_Filter_Compress_Rar
|
84 |
+
*/
|
85 |
+
public function setCallback($callback)
|
86 |
+
{
|
87 |
+
if (!is_callable($callback)) {
|
88 |
+
#require_once 'Zend/Filter/Exception.php';
|
89 |
+
throw new Zend_Filter_Exception('Callback can not be accessed');
|
90 |
+
}
|
91 |
+
|
92 |
+
$this->_options['callback'] = $callback;
|
93 |
+
return $this;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Returns the set archive
|
98 |
+
*
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function getArchive()
|
102 |
+
{
|
103 |
+
return $this->_options['archive'];
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Sets the archive to use for de-/compression
|
108 |
+
*
|
109 |
+
* @param string $archive Archive to use
|
110 |
+
* @return Zend_Filter_Compress_Rar
|
111 |
+
*/
|
112 |
+
public function setArchive($archive)
|
113 |
+
{
|
114 |
+
$archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive);
|
115 |
+
$this->_options['archive'] = (string) $archive;
|
116 |
+
|
117 |
+
return $this;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Returns the set password
|
122 |
+
*
|
123 |
+
* @return string
|
124 |
+
*/
|
125 |
+
public function getPassword()
|
126 |
+
{
|
127 |
+
return $this->_options['password'];
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Sets the password to use
|
132 |
+
*
|
133 |
+
* @param string $password
|
134 |
+
* @return Zend_Filter_Compress_Rar
|
135 |
+
*/
|
136 |
+
public function setPassword($password)
|
137 |
+
{
|
138 |
+
$this->_options['password'] = (string) $password;
|
139 |
+
return $this;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Returns the set targetpath
|
144 |
+
*
|
145 |
+
* @return string
|
146 |
+
*/
|
147 |
+
public function getTarget()
|
148 |
+
{
|
149 |
+
return $this->_options['target'];
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Sets the targetpath to use
|
154 |
+
*
|
155 |
+
* @param string $target
|
156 |
+
* @return Zend_Filter_Compress_Rar
|
157 |
+
*/
|
158 |
+
public function setTarget($target)
|
159 |
+
{
|
160 |
+
if (!file_exists(dirname($target))) {
|
161 |
+
#require_once 'Zend/Filter/Exception.php';
|
162 |
+
throw new Zend_Filter_Exception("The directory '$target' does not exist");
|
163 |
+
}
|
164 |
+
|
165 |
+
$target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target);
|
166 |
+
$this->_options['target'] = (string) $target;
|
167 |
+
return $this;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Compresses the given content
|
172 |
+
*
|
173 |
+
* @param string|array $content
|
174 |
+
* @return string
|
175 |
+
*/
|
176 |
+
public function compress($content)
|
177 |
+
{
|
178 |
+
$callback = $this->getCallback();
|
179 |
+
if ($callback === null) {
|
180 |
+
#require_once 'Zend/Filter/Exception.php';
|
181 |
+
throw new Zend_Filter_Exception('No compression callback available');
|
182 |
+
}
|
183 |
+
|
184 |
+
$options = $this->getOptions();
|
185 |
+
unset($options['callback']);
|
186 |
+
|
187 |
+
$result = call_user_func($callback, $options, $content);
|
188 |
+
if ($result !== true) {
|
189 |
+
#require_once 'Zend/Filter/Exception.php';
|
190 |
+
throw new Zend_Filter_Exception('Error compressing the RAR Archive');
|
191 |
+
}
|
192 |
+
|
193 |
+
return $this->getArchive();
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Decompresses the given content
|
198 |
+
*
|
199 |
+
* @param string $content
|
200 |
+
* @return boolean
|
201 |
+
*/
|
202 |
+
public function decompress($content)
|
203 |
+
{
|
204 |
+
$archive = $this->getArchive();
|
205 |
+
if (file_exists($content)) {
|
206 |
+
$archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
|
207 |
+
} elseif (empty($archive) || !file_exists($archive)) {
|
208 |
+
#require_once 'Zend/Filter/Exception.php';
|
209 |
+
throw new Zend_Filter_Exception('RAR Archive not found');
|
210 |
+
}
|
211 |
+
|
212 |
+
$password = $this->getPassword();
|
213 |
+
if ($password !== null) {
|
214 |
+
$archive = rar_open($archive, $password);
|
215 |
+
} else {
|
216 |
+
$archive = rar_open($archive);
|
217 |
+
}
|
218 |
+
|
219 |
+
if (!$archive) {
|
220 |
+
#require_once 'Zend/Filter/Exception.php';
|
221 |
+
throw new Zend_Filter_Exception("Error opening the RAR Archive");
|
222 |
+
}
|
223 |
+
|
224 |
+
$target = $this->getTarget();
|
225 |
+
if (!is_dir($target)) {
|
226 |
+
$target = dirname($target);
|
227 |
+
}
|
228 |
+
|
229 |
+
$filelist = rar_list($archive);
|
230 |
+
if (!$filelist) {
|
231 |
+
#require_once 'Zend/Filter/Exception.php';
|
232 |
+
throw new Zend_Filter_Exception("Error reading the RAR Archive");
|
233 |
+
}
|
234 |
+
|
235 |
+
foreach($filelist as $file) {
|
236 |
+
$file->extract($target);
|
237 |
+
}
|
238 |
+
|
239 |
+
rar_close($archive);
|
240 |
+
return true;
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Returns the adapter name
|
245 |
+
*
|
246 |
+
* @return string
|
247 |
+
*/
|
248 |
+
public function toString()
|
249 |
+
{
|
250 |
+
return 'Rar';
|
251 |
+
}
|
252 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/Tar.php
CHANGED
@@ -1,106 +1,245 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: Tar.php 20096 2010-01-06 02:05:09Z bkarwin $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Compress_CompressAbstract
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Compress/CompressAbstract.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Compression adapter for Tar
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
class Zend_Filter_Compress_Tar extends Zend_Filter_Compress_CompressAbstract
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Compression Options
|
39 |
+
* array(
|
40 |
+
* 'archive' => Archive to use
|
41 |
+
* 'target' => Target to write the files to
|
42 |
+
* )
|
43 |
+
*
|
44 |
+
* @var array
|
45 |
+
*/
|
46 |
+
protected $_options = array(
|
47 |
+
'archive' => null,
|
48 |
+
'target' => '.',
|
49 |
+
'mode' => null,
|
50 |
+
);
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Class constructor
|
54 |
+
*
|
55 |
+
* @param array $options (Optional) Options to set
|
56 |
+
*/
|
57 |
+
public function __construct($options = null)
|
58 |
+
{
|
59 |
+
if (!class_exists('Archive_Tar')) {
|
60 |
+
#require_once 'Zend/Loader.php';
|
61 |
+
try {
|
62 |
+
Zend_Loader::loadClass('Archive_Tar');
|
63 |
+
} catch (Zend_Exception $e) {
|
64 |
+
#require_once 'Zend/Filter/Exception.php';
|
65 |
+
throw new Zend_Filter_Exception('This filter needs PEARs Archive_Tar', 0, $e);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
parent::__construct($options);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Returns the set archive
|
74 |
+
*
|
75 |
+
* @return string
|
76 |
+
*/
|
77 |
+
public function getArchive()
|
78 |
+
{
|
79 |
+
return $this->_options['archive'];
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Sets the archive to use for de-/compression
|
84 |
+
*
|
85 |
+
* @param string $archive Archive to use
|
86 |
+
* @return Zend_Filter_Compress_Tar
|
87 |
+
*/
|
88 |
+
public function setArchive($archive)
|
89 |
+
{
|
90 |
+
$archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive);
|
91 |
+
$this->_options['archive'] = (string) $archive;
|
92 |
+
|
93 |
+
return $this;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Returns the set targetpath
|
98 |
+
*
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function getTarget()
|
102 |
+
{
|
103 |
+
return $this->_options['target'];
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Sets the targetpath to use
|
108 |
+
*
|
109 |
+
* @param string $target
|
110 |
+
* @return Zend_Filter_Compress_Tar
|
111 |
+
*/
|
112 |
+
public function setTarget($target)
|
113 |
+
{
|
114 |
+
if (!file_exists(dirname($target))) {
|
115 |
+
#require_once 'Zend/Filter/Exception.php';
|
116 |
+
throw new Zend_Filter_Exception("The directory '$target' does not exist");
|
117 |
+
}
|
118 |
+
|
119 |
+
$target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target);
|
120 |
+
$this->_options['target'] = (string) $target;
|
121 |
+
return $this;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Returns the set compression mode
|
126 |
+
*/
|
127 |
+
public function getMode()
|
128 |
+
{
|
129 |
+
return $this->_options['mode'];
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Compression mode to use
|
134 |
+
* Eighter Gz or Bz2
|
135 |
+
*
|
136 |
+
* @param string $mode
|
137 |
+
*/
|
138 |
+
public function setMode($mode)
|
139 |
+
{
|
140 |
+
$mode = ucfirst(strtolower($mode));
|
141 |
+
if (($mode != 'Bz2') && ($mode != 'Gz')) {
|
142 |
+
#require_once 'Zend/Filter/Exception.php';
|
143 |
+
throw new Zend_Filter_Exception("The mode '$mode' is unknown");
|
144 |
+
}
|
145 |
+
|
146 |
+
if (($mode == 'Bz2') && (!extension_loaded('bz2'))) {
|
147 |
+
#require_once 'Zend/Filter/Exception.php';
|
148 |
+
throw new Zend_Filter_Exception('This mode needs the bz2 extension');
|
149 |
+
}
|
150 |
+
|
151 |
+
if (($mode == 'Gz') && (!extension_loaded('zlib'))) {
|
152 |
+
#require_once 'Zend/Filter/Exception.php';
|
153 |
+
throw new Zend_Filter_Exception('This mode needs the zlib extension');
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Compresses the given content
|
159 |
+
*
|
160 |
+
* @param string $content
|
161 |
+
* @return string
|
162 |
+
*/
|
163 |
+
public function compress($content)
|
164 |
+
{
|
165 |
+
$archive = new Archive_Tar($this->getArchive(), $this->getMode());
|
166 |
+
if (!file_exists($content)) {
|
167 |
+
$file = $this->getTarget();
|
168 |
+
if (is_dir($file)) {
|
169 |
+
$file .= DIRECTORY_SEPARATOR . "tar.tmp";
|
170 |
+
}
|
171 |
+
|
172 |
+
$result = file_put_contents($file, $content);
|
173 |
+
if ($result === false) {
|
174 |
+
#require_once 'Zend/Filter/Exception.php';
|
175 |
+
throw new Zend_Filter_Exception('Error creating the temporary file');
|
176 |
+
}
|
177 |
+
|
178 |
+
$content = $file;
|
179 |
+
}
|
180 |
+
|
181 |
+
if (is_dir($content)) {
|
182 |
+
// collect all file infos
|
183 |
+
foreach (new RecursiveIteratorIterator(
|
184 |
+
new RecursiveDirectoryIterator($content, RecursiveDirectoryIterator::KEY_AS_PATHNAME),
|
185 |
+
RecursiveIteratorIterator::SELF_FIRST
|
186 |
+
) as $directory => $info
|
187 |
+
) {
|
188 |
+
if ($info->isFile()) {
|
189 |
+
$file[] = $directory;
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
+
$content = $file;
|
194 |
+
}
|
195 |
+
|
196 |
+
$result = $archive->create($content);
|
197 |
+
if ($result === false) {
|
198 |
+
#require_once 'Zend/Filter/Exception.php';
|
199 |
+
throw new Zend_Filter_Exception('Error creating the Tar archive');
|
200 |
+
}
|
201 |
+
|
202 |
+
return $this->getArchive();
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Decompresses the given content
|
207 |
+
*
|
208 |
+
* @param string $content
|
209 |
+
* @return boolean
|
210 |
+
*/
|
211 |
+
public function decompress($content)
|
212 |
+
{
|
213 |
+
$archive = $this->getArchive();
|
214 |
+
if (file_exists($content)) {
|
215 |
+
$archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
|
216 |
+
} elseif (empty($archive) || !file_exists($archive)) {
|
217 |
+
#require_once 'Zend/Filter/Exception.php';
|
218 |
+
throw new Zend_Filter_Exception('Tar Archive not found');
|
219 |
+
}
|
220 |
+
|
221 |
+
$archive = new Archive_Tar($archive, $this->getMode());
|
222 |
+
$target = $this->getTarget();
|
223 |
+
if (!is_dir($target)) {
|
224 |
+
$target = dirname($target);
|
225 |
+
}
|
226 |
+
|
227 |
+
$result = $archive->extract($target);
|
228 |
+
if ($result === false) {
|
229 |
+
#require_once 'Zend/Filter/Exception.php';
|
230 |
+
throw new Zend_Filter_Exception('Error while extracting the Tar archive');
|
231 |
+
}
|
232 |
+
|
233 |
+
return true;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Returns the adapter name
|
238 |
+
*
|
239 |
+
* @return string
|
240 |
+
*/
|
241 |
+
public function toString()
|
242 |
+
{
|
243 |
+
return 'Tar';
|
244 |
+
}
|
245 |
+
}
|
lib/Ampersand/Filter/Zend/Filter/Compress/Zip.php
CHANGED
@@ -1,177 +1,355 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Zend Framework
|
4 |
+
*
|
5 |
+
* LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the new BSD license that is bundled
|
8 |
+
* with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://framework.zend.com/license/new-bsd
|
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@zend.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* @category Zend
|
16 |
+
* @package Zend_Filter
|
17 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
18 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
19 |
+
* @version $Id: Zip.php 20126 2010-01-07 18:10:58Z ralph $
|
20 |
+
*/
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @see Zend_Filter_Compress_CompressAbstract
|
24 |
+
*/
|
25 |
+
#require_once 'Zend/Filter/Compress/CompressAbstract.php';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Compression adapter for zip
|
29 |
+
*
|
30 |
+
* @category Zend
|
31 |
+
* @package Zend_Filter
|
32 |
+
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
33 |
+
* @license http://framework.zend.com/license/new-bsd New BSD License
|
34 |
+
*/
|
35 |
+
class Zend_Filter_Compress_Zip extends Zend_Filter_Compress_CompressAbstract
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Compression Options
|
39 |
+
* array(
|
40 |
+
* 'archive' => Archive to use
|
41 |
+
* 'password' => Password to use
|
42 |
+
* 'target' => Target to write the files to
|
43 |
+
* )
|
44 |
+
*
|
45 |
+
* @var array
|
46 |
+
*/
|
47 |
+
protected $_options = array(
|
48 |
+
'archive' => null,
|
49 |
+
'target' => null,
|
50 |
+
);
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Class constructor
|
54 |
+
*
|
55 |
+
* @param string|array $options (Optional) Options to set
|
56 |
+
*/
|
57 |
+
public function __construct($options = null)
|
58 |
+
{
|
59 |
+
if (!extension_loaded('zip')) {
|
60 |
+
#require_once 'Zend/Filter/Exception.php';
|
61 |
+
throw new Zend_Filter_Exception('This filter needs the zip extension');
|
62 |
+
}
|
63 |
+
parent::__construct($options);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Returns the set archive
|
68 |
+
*
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
public function getArchive()
|
72 |
+
{
|
73 |
+
return $this->_options['archive'];
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Sets the archive to use for de-/compression
|
78 |
+
*
|
79 |
+
* @param string $archive Archive to use
|
80 |
+
* @return Zend_Filter_Compress_Rar
|
81 |
+
*/
|
82 |
+
public function setArchive($archive)
|
83 |
+
{
|
84 |
+
$archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive);
|
85 |
+
$this->_options['archive'] = (string) $archive;
|
86 |
+
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Returns the set targetpath
|
92 |
+
*
|
93 |
+
* @return string
|
94 |
+
*/
|
95 |
+
public function getTarget()
|
96 |
+
{
|
97 |
+
return $this->_options['target'];
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Sets the target to use
|
102 |
+
*
|
103 |
+
* @param string $target
|
104 |
+
* @return Zend_Filter_Compress_Rar
|
105 |
+
*/
|
106 |
+
public function setTarget($target)
|
107 |
+
{
|
108 |
+
if (!file_exists(dirname($target))) {
|
109 |
+
#require_once 'Zend/Filter/Exception.php';
|
110 |
+
throw new Zend_Filter_Exception("The directory '$target' does not exist");
|
111 |
+
}
|
112 |
+
|
113 |
+
$target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target);
|
114 |
+
$this->_options['target'] = (string) $target;
|
115 |
+
return $this;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Compresses the given content
|
120 |
+
*
|
121 |
+
* @param string $content
|
122 |
+
* @return string Compressed archive
|
123 |
+
*/
|
124 |
+
public function compress($content)
|
125 |
+
{
|
126 |
+
$zip = new ZipArchive();
|
127 |
+
$res = $zip->open($this->getArchive(), ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
128 |
+
|
129 |
+
if ($res !== true) {
|
130 |
+
#require_once 'Zend/Filter/Exception.php';
|
131 |
+
throw new Zend_Filter_Exception($this->_errorString($res));
|
132 |
+
}
|
133 |
+
|
134 |
+
if (file_exists($content)) {
|
135 |
+
$content = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
|
136 |
+
$basename = substr($content, strrpos($content, DIRECTORY_SEPARATOR) + 1);
|
137 |
+
if (is_dir($content)) {
|
138 |
+
$index = strrpos($content, DIRECTORY_SEPARATOR) + 1;
|
139 |
+
$content .= DIRECTORY_SEPARATOR;
|
140 |
+
$stack = array($content);
|
141 |
+
while (!empty($stack)) {
|
142 |
+
$current = array_pop($stack);
|
143 |
+
$files = array();
|
144 |
+
|
145 |
+
$dir = dir($current);
|
146 |
+
while (false !== ($node = $dir->read())) {
|
147 |
+
if (($node == '.') || ($node == '..')) {
|
148 |
+
continue;
|
149 |
+
}
|
150 |
+
|
151 |
+
if (is_dir($current . $node)) {
|
152 |
+
array_push($stack, $current . $node . DIRECTORY_SEPARATOR);
|
153 |
+
}
|
154 |
+
|
155 |
+
if (is_file($current . $node)) {
|
156 |
+
$files[] = $node;
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
$local = substr($current, $index);
|
161 |
+
$zip->addEmptyDir(substr($local, 0, -1));
|
162 |
+
|
163 |
+
foreach ($files as $file) {
|
164 |
+
$zip->addFile($current . $file, $local . $file);
|
165 |
+
if ($res !== true) {
|
166 |
+
#require_once 'Zend/Filter/Exception.php';
|
167 |
+
throw new Zend_Filter_Exception($this->_errorString($res));
|
168 |
+
}
|
169 |
+
}
|
170 |
+
}
|
171 |
+
} else {
|
172 |
+
$res = $zip->addFile($content, $basename);
|
173 |
+
if ($res !== true) {
|
174 |
+
#require_once 'Zend/Filter/Exception.php';
|
175 |
+
throw new Zend_Filter_Exception($this->_errorString($res));
|
176 |
+
}
|
177 |
+
}
|
178 |
+
} else {
|
179 |
+
$file = $this->getTarget();
|
180 |
+
if (!is_dir($file)) {
|
181 |
+
$file = basename($file);
|
182 |
+
} else {
|
183 |
+
$file = "zip.tmp";
|
184 |
+
}
|
185 |
+
|
186 |
+
$res = $zip->addFromString($file, $content);
|
187 |
+
if ($res !== true) {
|
188 |
+
#require_once 'Zend/Filter/Exception.php';
|
189 |
+
throw new Zend_Filter_Exception($this->_errorString($res));
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
+
$zip->close();
|
194 |
+
return $this->_options['archive'];
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Decompresses the given content
|
199 |
+
*
|
200 |
+
* @param string $content
|
201 |
+
* @return string
|
202 |
+
*/
|
203 |
+
public function decompress($content)
|
204 |
+
{
|
205 |
+
$archive = $this->getArchive();
|
206 |
+
if (file_exists($content)) {
|
207 |
+
$archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
|
208 |
+
} elseif (empty($archive) || !file_exists($archive)) {
|
209 |
+
#require_once 'Zend/Filter/Exception.php';
|
210 |
+
throw new Zend_Filter_Exception('ZIP Archive not found');
|
211 |
+
}
|
212 |
+
|
213 |
+
$zip = new ZipArchive();
|
214 |
+
$res = $zip->open($archive);
|
215 |
+
|
216 |
+
$target = $this->getTarget();
|
217 |
+
|
218 |
+
if (!empty($target) && !is_dir($target)) {
|
219 |
+
$target = dirname($target);
|
220 |
+
}
|
221 |
+
|
222 |
+
if (!empty($target)) {
|
223 |
+
$target = rtrim($target, '/\\') . DIRECTORY_SEPARATOR;
|
224 |
+
}
|
225 |
+
|
226 |
+
if (empty($target) || !is_dir($target)) {
|
227 |
+
#require_once 'Zend/Filter/Exception.php';
|
228 |
+
throw new Zend_Filter_Exception('No target for ZIP decompression set');
|
229 |
+
}
|
230 |
+
|
231 |
+
if ($res !== true) {
|
232 |
+
#require_once 'Zend/Filter/Exception.php';
|
233 |
+
throw new Zend_Filter_Exception($this->_errorString($res));
|
234 |
+
}
|
235 |
+
|
236 |
+
if (version_compare(PHP_VERSION, '5.2.8', '<')) {
|
237 |
+
for ($i = 0; $i < $zip->numFiles; $i++) {
|
238 |
+
$statIndex = $zip->statIndex($i);
|
239 |
+
$currName = $statIndex['name'];
|
240 |
+
if (($currName{0} == '/') ||
|
241 |
+
(substr($currName, 0, 2) == '..') ||
|
242 |
+
(substr($currName, 0, 4) == './..')
|
243 |
+
)
|
244 |
+
{
|
245 |
+
#require_once 'Zend/Filter/Exception.php';
|
246 |
+
throw new Zend_Filter_Exception('Upward directory traversal was detected inside ' . $archive
|
247 |
+
. ' please use PHP 5.2.8 or greater to take advantage of path resolution features of '
|
248 |
+
. 'the zip extension in this decompress() method.'
|
249 |
+
);
|
250 |
+
}
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
$res = @$zip->extractTo($target);
|
255 |
+
if ($res !== true) {
|
256 |
+
#require_once 'Zend/Filter/Exception.php';
|
257 |
+
throw new Zend_Filter_Exception($this->_errorString($res));
|
258 |
+
}
|
259 |
+
|
260 |
+
$zip->close();
|
261 |
+
return $target;
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Returns the proper string based on the given error constant
|
266 |
+
*
|
267 |
+
* @param string $error
|
268 |
+
*/
|
269 |
+
protected function _errorString($error)
|
270 |
+
{
|
271 |
+
switch($error) {
|
272 |
+
case ZipArchive::ER_MULTIDISK :
|
273 |
+
return 'Multidisk ZIP Archives not supported';
|
274 |
+
|
275 |
+
case ZipArchive::ER_RENAME :
|
276 |
+
return 'Failed to rename the temporary file for ZIP';
|
277 |
+
|
278 |
+
case ZipArchive::ER_CLOSE :
|
279 |
+
return 'Failed to close the ZIP Archive';
|
280 |
+
|
281 |
+
case ZipArchive::ER_SEEK :
|
282 |
+
return 'Failure while seeking the ZIP Archive';
|
283 |
+
|
284 |
+
case ZipArchive::ER_READ :
|
285 |
+
return 'Failure while reading the ZIP Archive';
|
286 |
+
|
287 |
+
case ZipArchive::ER_WRITE :
|
288 |
+
return 'Failure while writing the ZIP Archive';
|
289 |
+
|
290 |
+
case ZipArchive::ER_CRC :
|
291 |
+
return 'CRC failure within the ZIP Archive';
|
292 |
+
|
293 |
+
case ZipArchive::ER_ZIPCLOSED :
|
294 |
+
return 'ZIP Archive already closed';
|
295 |
+
|
296 |
+
case ZipArchive::ER_NOENT :
|
297 |
+
return 'No such file within the ZIP Archive';
|
298 |
+
|
299 |
+
case ZipArchive::ER_EXISTS :
|
300 |
+
return 'ZIP Archive already exists';
|
301 |
+
|
302 |
+
case ZipArchive::ER_OPEN :
|
303 |
+
return 'Can not open ZIP Archive';
|
304 |
+
|
305 |
+
case ZipArchive::ER_TMPOPEN :
|
306 |
+
return 'Failure creating temporary ZIP Archive';
|
307 |
+
|
308 |
+
case ZipArchive::ER_ZLIB :
|
309 |
+
return 'ZLib Problem';
|
310 |
+
|
311 |
+
case ZipArchive::ER_MEMORY :
|
312 |
+
return 'Memory allocation problem while working on a ZIP Archive';
|
313 |
+
|
314 |
+
case ZipArchive::ER_CHANGED :
|
315 |
+
return 'ZIP Entry has been changed';
|
316 |
+
|
317 |
+
case ZipArchive::ER_COMPNOTSUPP :
|
318 |
+
return 'Compression method not supported within ZLib';
|
319 |
+
|
320 |
+
case ZipArchive::ER_EOF :
|
321 |
+
return 'Premature EOF within ZIP Archive';
|
322 |
+
|
323 |
+
case ZipArchive::ER_INVAL :
|
324 |
+
return 'Invalid argument for ZLIB';
|
325 |
+
|
326 |
+
case ZipArchive::ER_NOZIP :
|
327 |
+
return 'Given file is no zip archive';
|
328 |
+
|
329 |
+
case ZipArchive::ER_INTERNAL :
|
330 |
+
return 'Internal error while working on a ZIP Archive';
|
331 |
+
|
332 |
+
case ZipArchive::ER_INCONS :
|
333 |
+
return 'Inconsistent ZIP archive';
|
334 |
+
|
335 |
+
case ZipArchive::ER_REMOVE :
|
336 |
+
return 'Can not remove ZIP Archive';
|
337 |
+
|
338 |
+
case ZipArchive::ER_DELETED :
|
339 |
+
return 'ZIP Entry has been deleted';
|
340 |
+
|
341 |
+
default :
|
342 |
+
return 'Unknown error within ZIP Archive';
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Returns the adapter name
|
348 |
+
*
|
349 |
+
* @return string
|
350 |
+
*/
|
351 |
+
public function toString()
|
352 |
+
{
|
353 |
+
return 'Zip';
|
354 |
+
}
|
355 |
+
}
|
lib/Ampersand/License.php
CHANGED
@@ -1,161 +1,162 @@
|
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
-
4+
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
+
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
/
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
/
|
159 |
-
|
160 |
-
|
161 |
-
|
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
+
4+oV53lEpg7lYJEMuXLRWeSmZuC/XDc8B50Q0+w9Db+nG853FWFX/GgsAa8jUIZ6gB9jembQenf3
|
5 |
+
0QMAxNZMqJCfheJH5pTMWk6gPw79/RGLo1aFGwq/nYFfo5ngNgTKQOWAbbDbUDsXMK7avdKsFN4U
|
6 |
+
gs2wWr4f0w1cCjeBmxSla6uApUaU+8POTJZeSiTvqxNTB/PL/us7rvU9OCqz7yj9WdlOsF2J8kR+
|
7 |
+
XazCxNcOvsm/rohF4/4ntF/HaqfOxcQlytQDUUlUL+EoPNXY8RbGIwBNLhymHbo97FzDu5zz6SIQ
|
8 |
+
AeGxmsF9CMhjVXriN8hIQ9eKqTZpW3PO4jj33kQM1apQzxjRkAd3LXgiVz/7epqmHTNwX+UJ2M30
|
9 |
+
ItacDn0117jFdBqcA1q2YoOCLQV2myCnuSl1NBk4hbiP4IZX7ZMejHvogIQb8afI26dv/xg03vq2
|
10 |
+
fKO+qrdjlvnFJL7CbQ7VhfwaJHOccbpiIpWco3kbi52oT+J2iJ0ELRVvEG5zwZg01Hm0+4Rmatvh
|
11 |
+
Xi6jKTsCfSY8KszXmglqsl2qe64UlTk6jhphohxbHhtLIMBoU/ZDwktxvljaHpkLyKU/PbBFxdf1
|
12 |
+
DmgWeD957C4QgyQ8c0Xtx6i6uuf4s+Gpv2jO/5IKmYUuPhsF5UdSAXxxISHyp9jx0NgnpB5U64SK
|
13 |
+
BgY6GH+Wv8y/tuj5D+Olcx8bM8udXhQ8LaD7+xRKTwTzxIIYQrZ62Ji/0CdDad9ietAUk7RFtkKU
|
14 |
+
4f+tzuHlmtzdUR9igWtZHXCkxTbH0oPIB/NVTkSiZ6zkudEWYnl/3Dnd417PWoLYNYJFTXJ293B1
|
15 |
+
eHKsyePQDlt8zcCC+bsKkuSPwQR7+gaqk+e+ODkuSU5YmRoKCV/LX47r5WpJ0uSVwNYAbcgcCqNS
|
16 |
+
i1fexsTLDUX74ORhOeJr9oCOCOySTQBDglZyynZjoJWpD3SjUVQw7NOdbJsD9YYFasSgSrx/+xip
|
17 |
+
dDF8iqZlEMhZ9KEu8MzqDcKHqtvZSVw014VGmAIZny8XGPGpqvHZptUjt4HTEGBZb2h0Qjgc+bjS
|
18 |
+
+vs0CdUpk4rdcQgOJurbRRp0YNvye7DIubZg8PqQP1hhZHVG/qODfYFvFXadsN9Voo3680toZOX2
|
19 |
+
+UHBEbimIQ2+aYbnh1S43YAEqW/YtxzGe90asglGGjIm4p9vaWHaXviemhS52cgbzD2/EgG3kZ0r
|
20 |
+
3QGEYXzfyx+NUgPKPN9ustfiCbd2MUHzBMJevb+F+AST9SsbvgWumH4biB+blPy43uPTzmiYOuhh
|
21 |
+
QlFI2rXnPHIR6JH/Rld2b81CqcWxkoeI9ZEqpGvk70YzrvD2vw1LyNEN4qepcKBMZuuMeaC3F+uW
|
22 |
+
b2jedRr9rqz++E8atDJQYNXSsRM6pXNB8c8PfiIlbAqUWCv6aIhzagId8F4znkD7zqiOOtrsAFGQ
|
23 |
+
0Tefr/as5wUAfxBKg6UPsOBZo2bSifFjNDdYzYF9rFqF/XoxH6p9xymNxc6/4foCdXa9YV2smXtj
|
24 |
+
e2y7Rvv0IKqo4vY58Qf/6O6BXJJSWxGlu6K5/HKOa72wncyejbVyii9dXimTbx8S2o9PT4EX65LK
|
25 |
+
4/yJgUaqZyTnMamO5+llR7S3cTo9DKoB8utbFgeV9Z8zda3l4b/i6L2HDUO6E38dZcz+kjTvSTSI
|
26 |
+
/t/xI/jbqB2yfh4lhJkeq5sB4Wh2aQsutWOzgn28d9HEZaLubHcTgt1XMDsZXy+TCKQAB4L3pnXT
|
27 |
+
ww+LjkvODK8en+YtNatW/5sthcP+2maJpx7N4vmwTOaGIvQ8jhh0E0RdaO+fEDYNc/AjBFGglLYp
|
28 |
+
tRxizOijKxqruxRiLqJuOl8CSSdGJtW6PF7ghgvNW3uhIk/Xm5gg4UPB+X7RzE6ZRhkn/AnKpV9f
|
29 |
+
61Ed2KWeQseSgBYJJymr8rsTnJ2+UllwY3QDWrvLwJ3uJxO41CTMC7BIFL8ZbGLl/M50xQrC2/lt
|
30 |
+
wLY35iUUn5gO4JfKfmWmmsUgdBCXQnIhYKGgka3GvW1eEtwEwN2RMIIfeZVX93CfO2lg6BQrGHn8
|
31 |
+
CHbY6l2nSvrQCK5lEerr0lfCH41DAQB/hcIszBX403AH+IFba7WKQYRxRZA+TYsi2NE0Iyx6iXgL
|
32 |
+
U/VusHyjgmDtQeZzho3FlIybBF11CJiTYPPvIKbDkcNlxmJ4U1DAL5U85J4+z8PBb2EQii/ES+Bx
|
33 |
+
pY4COQ1u8FHQGcQPyjB6URxAL5Nm01gtb4pHnYm2pZbq2/SjHal8qh0KrKd6MYfv3tpIg8YcRDJv
|
34 |
+
qdI4ZMSxM2MiLu0VVIwgOUgOsU63A8+FLky/6mnmI+BGHjWI+SdVj42r41RSQRdu2j9YmvAAEbas
|
35 |
+
sbCANaiXKp6a104M877dyRDrFunwzk3PdDoYcueDA+c0fQDmZ1zVUyMTqeR+IoT5nNJ4U+2qxYES
|
36 |
+
WHq3b61PfIeWiLNzTmAMyfxOYbKq3+wU9W0DuJj1LRpC+9q2Cugb+u1D7pifFQtadMa/BkSWop6N
|
37 |
+
NK62umpvtkvcVfolSXyH7jMkO6rdaUIMnZYAd6ot90EIY60YdNwQEKgFUvdZR9zxNaV7/ExC1VIU
|
38 |
+
RM+Owjbq9p/Z3JjjssONfqlXSFbQCFdBspOrkHONeA1U1Z1YtB2eFMGie5zy+oRvSkebcevsClYR
|
39 |
+
m4o70Xwr0vx6NI5dZUSNNjNDfAH75w5bRAKg2CH+o6cdWGWek9gGIuw0u+rN/zRjpficD2SgwZ5f
|
40 |
+
wXhiwRg07gJGzAGRkRYQu34I9+u1rZsIPVsG/nWwYhRf01ojVsTjyfOz4Yvv+2OO9mG+syzLnvwH
|
41 |
+
jkohGiqq2rweqarQ61NkEquniyuAgOiqxxAh/ZdZPq+EYj3GQBLaGCQdOOxENQgOma/kR0SWSdxH
|
42 |
+
Ln27kQjB2Ae/pOw0BzW0Dp2A+VvTmKGwTEGGlQRCwFJOyBDv2trZ10mWl9yunXXqp0SQWX8rXkCk
|
43 |
+
5tuYhcycrW0wigOTEXEiVABGCc/zM1dFAk3Nmp43EmDZMT70OtVUcUU6C094232HTvXYZuQQitWm
|
44 |
+
6iZzxJZbNaq36UL6kW/ev2uj+wD/Mu/pHNelnYHzEpGsUfZ7CmOm1E/Zhmqd5ToU8dfQ3TFF2QpY
|
45 |
+
ctUgFeibZg5EEcmu7aR6nvHAdbNieoJHUxbFba8mR6H1ibRjmmpTfOp7cXT3TpxYwdabwC9/kaJA
|
46 |
+
XNuaSoPLjxqRSBwE/q+M7EvPhmG+HR+SP/uJd+iok0gu/py6KI4lmfdgZZiXt1XzbT87yWEvlguM
|
47 |
+
+O7+7z9sI0YQTJ3Phjqdw10mnI41A6ONy31wawl/of6e+VU8/KMLt/csh/c9nig8f2bceM4xDvbp
|
48 |
+
G3xGQlmse2vtB2a5M1BD69p/dCmCXf5G+rKN6b8vi7vwIcEpsMTXqaUEk6z4UTs1CWXl9VM8YEMV
|
49 |
+
8OuwcOcmGYCzI7cegIA764s4dpN435ELP+Q8ET19VqYiKCQFsPsb311yX+5yuRgSTZf+H//Ow7F3
|
50 |
+
pnwvx6pYiHj5+VMtosyFcmqd62FZzOVCbfvqbqJyMtpTzqImYKb1HRo6ClOF7GJqvO99acYut1cJ
|
51 |
+
07bzZEpjTnkROwmVfNc4SsAWaKsxBbCggAQUWP87Vj+SSkJyNHoFSexA2SkjjslDvvyuSko8IZcZ
|
52 |
+
RKpDOQ2rVGQnsLQCawHNPwRCxtpzAuE1b+ZcWKFuL8MvS/vTWKsojdmSZyUo9w+LQOz2UBb+FxOU
|
53 |
+
DW7p9z9MTvOBFIyoqON5HGdf8s2MlMxjeMaH4cKTqt2fCG3546LWBWdYmR50kP7J5KWraCm7c4Dq
|
54 |
+
WNUj4Ihh0CvZqymwH+Ny19dHsH8OXGq94RVUfWuJ76cZMaGWD16PE9OBkyEHK+KJ0MlqKzB2wJhM
|
55 |
+
sLjMcJwj0FkLkscZmchBy70565UvGtSlSGQoAT7eeInjTxWezisJHOYnAFT7Az15GMYIvXVQLwgl
|
56 |
+
P26b6kgkSbG2nUO3YHL94icDigdCr0l5jvD0MhcL1CxvX0+fEueMwdPUE2XkAQK1iKFKdW/fV3BL
|
57 |
+
7Gjopen6zEIDAC+eQk1S2TB9CPcPb5sBjx/cLNezZJrF/8C8wMPaIhcAdWqU8Wlp5Rr4TltVCpWG
|
58 |
+
zVEf6J0hFV85l6jxulSZBfEtzK1OJLYQNQT//nkmD9D48B/Hz/v+/xFOleQtoFY/3P2D65G4aTKY
|
59 |
+
XviHyWd7dD017vbh//qe28KWPhjfQf9bOYDxMPlj63smVXce6a8OwOb/cHeJS0LGevCXalLb5Hft
|
60 |
+
l2typMqgTTD0qqwnelTVLHtTqOBMiBQOiWH+gnY5jcIlinZXy366EpQ0VLEwRpkhN8ul24RZivXa
|
61 |
+
ajeJLAbUAbpLWGiCEV+ToX2YY89qd4WQxm97Uwc2LWowCe+EmwislZShh4tP2KcsVmK2vt0HUCCg
|
62 |
+
y6J6nor+bdm00oaCEnjqL+Qmmb+hT3N/wwRGLm5eUL61lkB+4k6Q6V/QbCk19ftmjU+K8reAJAYm
|
63 |
+
DrwGJC4ViFZHPdatPSvRcGzfgXjv1sF3sUbN2hqQdJaNT5dP6O5K7LfMdjgFQRM9757KR8Hy3hwK
|
64 |
+
wHbTe9xe402jBzRFbQ2sidj+n58ubtFR94D3sff3O5F/cB578p/hEAHFRAcCM97y/F1M4Wu8XegL
|
65 |
+
gd5msDcOuEX38Udg63GYWjN/dyvpfqh+mqtrnVDejaniDCwcEciSOEeH92w39d0q0lc2xEdwfEsu
|
66 |
+
EN1I2X8/Udg6vUuBu5MZC8Enb/VhWdsCT7EoPwNrNGU1GS2y/gpjiNz6/R4fo59JDqKNfYyUG5/x
|
67 |
+
gSt4uUb+nxnSDvbbvXnsvCkl30PT+jATC+TiJxb2vHmIsLvraabWPDde7ElxZbhEt7uLPt1Gl4sO
|
68 |
+
AoB9jyWCmDd51GBi+9evQzcgFqTrNR6q2Ndhi7ZaSVgKKFKK8TokgIHeif6fpX+ZdcHKYUTA4D/4
|
69 |
+
cpZ8MtPPqo5wkKXRC5VnC2MonlPCdYsczXpPiZ5DN4C0taXt7zahUPnssQo4V+g3083DKL86EbPo
|
70 |
+
kfoqUQiBWveaDPD7LzKOwGN7gylf0JUjI25j4mSKWD+kHmdjvlFbQJsUrvOfS9Uc0qKrBa2GqyBF
|
71 |
+
eZ5Z42DmhLMi7DbbX12XXOb/65NfE39/kxOORDMgJ7pdnRpzyXUBY9jQfYsNCGgPBwKCzeb0B4LD
|
72 |
+
iqdlYamaFHFEqaNLuG1VxZr4XMGOZAZ5YZPXayBH2PXhc/eSaRLnooQQKgEequftplKInM5Nh0FV
|
73 |
+
AwRtKUHeHsbeTqfVshQFkMQbo746g5UDiY4ph7tf5H8XIy5mUxfEBU6KZF/WQujntj04j0hg3Mjh
|
74 |
+
12qdQpD0OB1M0o2zeH5n0n6Q6U2zlmhzkOsvH6TUhdlLOsghP2Ohs3ef1yWZDoosUNPtZSICkUgD
|
75 |
+
aIC/ojDQek5ckSqbIWS9EPvxU82OzeDri/9EF/9ukmDN17fDGbP0iiIJT3O/Tz0NYHF7NnqYPVVO
|
76 |
+
Mn/0NdqQncZD8oCmW1qJHJ1A4xHivdHkdEBYV1FN8CIEEfpV0R/HS8LIiT3mUteWN1JHFRwYSAdG
|
77 |
+
4AB6OD52zQwbxeJlApvRzYmMKAXlJDXDwbTsGxXsPPW4G/yQ+1PXKM1mNeM/BlewnyfEFKlw1CCG
|
78 |
+
qoTHIkHTCV6j++kKG/JtGt9Xf5aNLSDwxCW1oZCMbl9SuaMTXhgKjZ0cOEqo0hjIXGZt2cT+lSkx
|
79 |
+
flZk+HNUx6TouvtJL/+HkqgvLeRg9nfQASAPtTkJkW5AmiovKV91kql9w0hP++PD2DFy8DOCkMWH
|
80 |
+
VnD7t/R8cT7Zi+2E7gFyfRSzJ3FQKhkPnr1uaoBrk/VwkRo1xMSi5Qk7NHOhqPh/T1eV/pjf7k2l
|
81 |
+
nge3NoMjqO66sWvgnVs274Hz3pgPUhC+fX3U9Ohz+LBzzJWN5Qf//E1oaZyCT1U01LL0wLYtoIcN
|
82 |
+
2PMAVryWWbBPIY7r/XLrciacgpSRy6gvryWxMdHhBd6gKQyRa1fce/4Vm3D5ztrOO3wuwqnzspGQ
|
83 |
+
KnnuyT5X7OBqcYVbIV/gxiZclPrXRXJLu/kFIrXs7VAAnIQS/rdt0zPVDzTnci3u1qoFIb5jcU65
|
84 |
+
moXoclNGxwP+OwTGVFxmii+7Eom7vI6id+LTAdz9iYFU3OMk1BQlyar8zaUdY5HnkWrt/2Be39ZA
|
85 |
+
YpCCR/gb+RrQiCsU+162rDZnU9zaCdBoD7hRyCn4xQRbteFJ2pe0ZLQn3H7lKRh+8mY2L6INgz2K
|
86 |
+
keALvvx/EocW47V9NJ/5mMvKovDp3WOarbKQhG82WZ9qKEV8kaxV+bIT+drfBlJBlGXwmJuJr6j+
|
87 |
+
aNA5XPS9KfZMHetebVQBRBB9CYnU/3Y6iPOVzNlikyUuV42wmy8VYgiD7dkdcwOEfxdqxVvFBESo
|
88 |
+
wcPp5XJTUOhEB/oSTUZ8y1RR2oDnCiYT9RiYHQ/0hUQnQtlsPsq1P4EwNG5ZwOBo1wLk+Tw9Nmqc
|
89 |
+
bAkzLBAnTgwQWr86Sq4nR2fepviBopzvJybVGOv4PR9n0SBYJLEIEMyCXkE5BrWt5sThkaohIF+S
|
90 |
+
Kd64T+q2SDG/4Z07yWyQiOlO2RkqahYJR7rIqd/uWVsfOPffLk+zpj9HuIEwk0J0SyxTrKT9lWYo
|
91 |
+
UpNyG/o/4j+XsEzUa3ZASnU+AKxQjnfMbsRCAtuPDYHlJzSxfvrKceAMT+EwcFdqjtJBU77KwuHH
|
92 |
+
PZ/8SlOqMvcP3DsimLRJBt+Mw3xLrkmk1wWACpaVoX1p9UN+o8/XraQPAVPli8oUdMlaXZt+gpVU
|
93 |
+
UBCheuMpxnlE7bWed8oQFHc75ZFzePBDSggO1k3haz1oM1uN3cc0lgLdLYQ/+e3pG3TtwnwPZQtn
|
94 |
+
VWrQLf24kdc2bZw3KMPc3RG5AtmjKA8hU9KJdJZqW2uPp6LOKCw6OHWv6nkCGZxeQ32D5uCejBMG
|
95 |
+
IDNKiaZbn9mgFLbPWNRAHvOEsnDsuThGMh4qok0dZNroTzF37hNJEWzpConIiPuJ2aSMJPBpqOuC
|
96 |
+
WYk9o5JodEqBBy2oFb2MliRaEhW+ZJa3xoufxFs6WdyCzLZMsjZ+JZE9Jp3551UP0y16mfzTD2J5
|
97 |
+
szwHN0dZ7WvQt00OW1oJEpLULCzaeZjxKsclZsWJH4h5nwT/X73VQa6DjBlZ/c/TH4WuA/tckWgi
|
98 |
+
V+zEvkKW0ng8RrDl6snFXFoa1c5RcX7RJO+J24snn5qOtaXX6ruCRTI5z5pzlkKSr2N3Z8GOlvLT
|
99 |
+
P0Aztr7/tYav27Uug5Gezv+WLdI1GhIMvTj41IxnmvhC4HQl1aTpceUEAP8vv9C9562mi4mQGP5v
|
100 |
+
ZUVcfQPABOoH6idBfbh1PEQ2OSrFsFBX8MqFpIcJJbzJxuCTfT8TWhINHb73+3Yc7PvOGIG17mla
|
101 |
+
PfBm9L/LPZ3kqPOb0OLulsXUSr8BiRfMiaHhvOH/c6xK+Dq13kApCodRJoP0mqdhsLzblqhyhmuq
|
102 |
+
YgLVUgJ9TkQRd1TFoKNUlkybUVd3++CgMGruFWYSHHMqYPH5JsSXw8fjfAq4wh7cZ3hdXm57LY7n
|
103 |
+
b9EsRabCbksolUiVKbDXftRCdXO/dZ5d8DWgjxQD4UVz4Fzo0BPlar1cWe7NsEdDLNSqEQ/BoDeL
|
104 |
+
YPrIGsMXD4lsOA+lQTlPdq0bOcpJmMJiHl3JLheb/J9qILRdyF/u3WS9seAP7QBtmaBidEu0Fpjw
|
105 |
+
GJ+3BJ93y0nLMHFX4pBUUeJrPnVf3LWgy2eaTIUAd6Z2Xska0b1LRKCxifbnDhYyiZMytsRPXvxv
|
106 |
+
cGkxEIOpBDjkVnX+ZwchIC/rhfNOmldAg+Qj1Sd+xCwKkNSnr1fEJPb/sqK7rMIHB7m0E/bNxf1g
|
107 |
+
2FrbHVNEBpVO+mDy+Cu8T4oKY/3vsRTvTp/nkEkruDMFLwk6BDnytU+0dmu0g7dpI2DXN8aw4hTE
|
108 |
+
3IO3zx8rchsM3hlKx8KUsZ6DHzw8K3fSA38qXF+ea/gWuuQ1cA7GC8NK4js4KdeZ2Y1cxVSPAyIz
|
109 |
+
RkLtMajKoYBNn6Zxt2F+S1MzIxq58Kki6cg6qcOMu88q+YtF2UJZAdfRwGEq17GdBhl5LfPgyxcD
|
110 |
+
LgRdjxAxhfIMPUD4b4nxAerj2WjiXqPGLOsWcvUdP8IUrPlcD7Wkek+GWucjhf6LKsDaQIPFLfzv
|
111 |
+
ThX4s0DhN28T/bxwWdie0ZGPQc6sceYMMtRG0hYp+8PzYX12V/rTPBrT+9agCr303GxF2Qpr5eZN
|
112 |
+
O3SpdAqo7bh1lfFHnyFDjxM/d1ijOH5of6ynLJxt9MdKfd/EMIF/j/bk3mkNuBCNnVFFKhJclAc9
|
113 |
+
SQL0OvrmPBIpa3v/DsJKQbkSiOcMgwkveMO7HJusSEulEBaLjuSu4og9rtCc2Mc7ASb2njeng0Ar
|
114 |
+
T7vIn6Q1i/289wKzt7xfKQc3iVM7xLyhhx+bZSRVUJNeKskJM7AtcmVS6tpY/MY64rxn7FaumaSV
|
115 |
+
BLByiwXeIuWzH6qTdlgwWhnGTUmAdRMFzQ1aYB+xC66l4bCXEf/iEioizohuced5m9SKDmuJJ8iM
|
116 |
+
topnhmOARrOrefOnhFdvJ7yLCjykdlBfkMepRmwUUsEmmKnKj8rYLUOlOzIa0V9zgYuYhLNt58s9
|
117 |
+
lpJI6tJT7ZQ9QH6EkmS4Dk4VT6moNl1QaGoKt8bzTUqfPxgJf5VC+3KvlrY6uQVm6u8+H17fCaQM
|
118 |
+
u5MMvSYjSi1uQJLbgOrN/IdqSoDgsjDLUzShyokaSI3vkFdQny6U8bL2Fshbi4WMMCMKyHvh5pkE
|
119 |
+
sGotgYewky09Kc5amg88LLncb/7Ga92a6FfgnljpdFkNN0g126RsN+34OUezSSF3Oh9b/T3seWhW
|
120 |
+
lkxl3MwuujY3jNyrqrfKX2dTEw79wh4pUL/wBvINmNetBAkYC5Pmb6H+ynF4iaZ0klBfVTvmQL4Z
|
121 |
+
panzsMpPU6jLPP6Krih7JLo9u/WCTSeZaVS5jkg3PT9C1EDvStxRQ/zGAZtbKx1bJ2hCEuWRBDlC
|
122 |
+
Qb2i7/wAK2NsIP+iH1pN7k/Ztm8XGtGi7fZiaP2/8SSEoMIYTyLdz4g4mUH4ZrFSiBnUOnWwY7xl
|
123 |
+
Bl/bApzjUDnW8Y8FenRtdOS1Ztzf5gd453PSGGPepwx+WSYi3RmJikzzxfDMqv01IS5SzPhI1cr1
|
124 |
+
Bmwh5mk0X9P/dtYQmVSLqEE5qTmjlICY2y+13mBi5WUWC4SkkDktRlHjERoNoq+NpbAonoCAPbeM
|
125 |
+
KkgQ2asYb75VG3DQK1ylDXpFnEob6E5zVpIghkWo+TkGa+ispV7mW5+8Yw+9A/L3Dy6NB4runm3H
|
126 |
+
ijihWTmJ38vBkluiD+CG1uUueGimueFYgXiECVAwEWhWrTkInYD2TfEREw2P0wzU5irF4f8++HBO
|
127 |
+
13sZnGwePyr1wFSvYqeopft1bHLpMs03vQ2Sb9eL3+Shf8d8Rdt7yEqqS7Yt5I5qyukoi//ZwdEU
|
128 |
+
XwJipVhc371bICtqc9nGSue/knlIuYs3qhJAr94lhvmquGDxn1d7Wf6fAWuDCYaQZSkMQuoUs64x
|
129 |
+
H6rEJ9smd8vCQ/r5hIqaTdc42t/wObhytNWAO1Sa6Ws1WUSxRBvSmSfxm2o6H2Dv+gX6liI/JkJi
|
130 |
+
IRHye6VOJilknsos96oJ1KyKwWZjI5rjdwGO3fDimRx1ZxZPzBoA8od/w5ZRM/cj1QFb0//xbPTK
|
131 |
+
UY49twKfNriVIQi/rDKmtMMlbvuTK0F/eMXbRW8LJMlpmv6Q7o1PIVwGvmWjIvxjQidvqWDycndo
|
132 |
+
riRL4Mcn4ykXFYTNPvK4CV2i6eaYEj9FKAHmLMk7bWUIUAuL8I1T+zZZgnCV2xSzFvA7YkmToIR5
|
133 |
+
49/IxHPChLSqUob0yK4zK6EVhQzAgFwG5u66jiatuXuQMyrDscYDwZJPlhuAmp0uW5IPoEuQQ0Hn
|
134 |
+
2VpPyVDeXF75MFptPm0aIskZLNR9+9E35OTdCjfVi1l3uq+jmZI1w4A8T5U74RtXftDO6VBM3LrO
|
135 |
+
T0C0GZFLEdBPq+8hwcwu76pWDxJVRRig4A8/KLzyWh3o2dY3nTVg1cQAVqR5+vBOTGVpSyAVx6MS
|
136 |
+
yRvCQBrWIqs6Z/wCsJduPhtKH8/ceAXSE12uSIqI0oFf+NGR2qEDJl4wqV/LpPreF/OImPcr/tnh
|
137 |
+
MmQBVXP15dIUHXV+/eADUVXoPTNk8ZWavlx5vg7Z1V0YykYO0XI7qQ+/+wwWQreYIjLJA6Rufk0T
|
138 |
+
3NQOFt50Ea/b9rLSJZPNoiJu6+K6HUGK1TiVmfQv0jiDG4jc3q2MmY7/CCyw3MDhODvPRWsuV86A
|
139 |
+
PW/SmRlnTs/l3x7cV8w6MpieaMS6x6zYgOzJ/s3uh50KPReHkk+diQSuFbrjFt3a2N7ScBURXNz0
|
140 |
+
OnN/HrkmE5AczWJdwVV+vLCitA/mjfPgThZtyLDS1+3F5J4We2yohokRj/KqkuHHxOGTU9sc7QKH
|
141 |
+
JoUApQxv0+3DEAQnrL0sa0eHQI3LDDeeQ12q6M74jD/nNDtinVSGc7bbOyRn0ht05+dhcDmBVnPd
|
142 |
+
Sx/aRqnfWJjDxWN495rLCz3+Rzqwybup88+yr64ew4KImknsyTBG6dcfk/fCvqdrLbYnR8zExW7q
|
143 |
+
ArG49KwApbes83GzxNnkubAAJZj9ZR4LA4dRu5q9tESL4FlGM8Z98mVX8g9fe60b7CZ6IiKsVk7w
|
144 |
+
Ryg7I+akaCcHrSRdI/NVlwtevZIq1TljS/jsqNrqAC/s20Hcgn1sXUHQAPk5rHjVAdBGIkdgIwHX
|
145 |
+
EjAVhpC6AWO30OqJ36bYSZk+QnhyaecXg0gsEe3fQGoXP4THDAMlRQBql+0ouC0SLMazZ/nXdk6C
|
146 |
+
DKDRy0R/KBUwuBLSf47MZICfVCw0CfnlsansEfXcyoUP4gP5qqzuSygb3rBGLRpEu9KTf90IqKZl
|
147 |
+
V1nIrQYqZqMaP4w5CF5P8H4U2CUfy81bNA0ACbPBrq6h1u04+9/PXhEhzZOk/LfV0Nk7rsRYyOck
|
148 |
+
1ItCN6u9+DTktok8jtulZeS6SIphEljrkkwTmChOC7/k7X2GyZ7QLBYxQSu4zqzPS8pjfFp2726m
|
149 |
+
zSZ7D02n0BMA6roF3kax8tqZVcmz9ry66BBQE/mGZdIWPrSc1DCkJ5/uaw9lV2wMv3hW3Gy5TvsY
|
150 |
+
WO/HQQtUwMLHIN5FhrRfm7DH6SjZZmqDzEQfxplAVNzwnvV/GRgUhx9DbG573QsagcMM+u0jFWkd
|
151 |
+
LxsYQh+uh4xTZTI8uSeZcZD4C6poU6ZNKv6iFHt/WrYRhrQh1Wk1rZESE3yMA5BphwPvdaBepgOr
|
152 |
+
i5em8q4p0nUT1v/+4rXLAPtjHBdzlGDiJyU3li1pksS3mZOzYI92zsymnJ3BlvdqUKTbXtEiAoQK
|
153 |
+
PNjRhTBFWqX3lIOpoA0e9VS3Gexj/+LFZ5Gf+GKuTX1Pc1jKiunxJMkLQecZFYLp3+S/Bdv9ek0e
|
154 |
+
ZhfndA16NDIDKGkW3MxGCRwl3V+TzsMWbo2pdkGEDxGPStMMBw2pVRTr/r3ZNUIYMbg8f4utBvJ0
|
155 |
+
7Ej3X3TxQ61Z53RkZTC2Uar+zubheOmCKQ6BKU6ErmUXMXA7IK8uHTvb0TLUMCaCXHDmnO2MVSxa
|
156 |
+
CZRnh/kYCdxiG8eI2ayri9AT1MBG1MD0yLkinYDQ7r+th+uIvWG2r1oIya12t6lXv9UocnFtcqf4
|
157 |
+
RR9w2k+LFM7bACcjKGJXw83rqRlkJ1JY/pQr/HjqQLA1uPOdpOslMF6RVknJ/W4UDMNa+vq+F+Yc
|
158 |
+
CZBFddlzpttOXB/kPA25tG9S4ajZ/TKApwVFW4ba6LWFdOpfa7N03cKKeWluyfjwHLhwXhyAHGnF
|
159 |
+
L/kaamPWlnJKpGZvm5DtlY112wJIq6txfQ5MOH+1k8eqO9QLTJfQedlEwBTKDwZOjXA6FngU7XUc
|
160 |
+
NWrx/JZWie42nsQQlGq33j2yftSA/2Kl2b4WGaOltwTDpvNHzblqXdZwTfWp6g34mRsra37evJYA
|
161 |
+
pL8YrNTsWIBaCwNgHICPbj2KuZDFOZIEmaoH8+AALlFsI3el7sLTrGtiLvR9dAsHJ8rs+ZtEbqeg
|
162 |
+
q5LOPBR174zC
|
lib/Ampersand/License/Helper.php
CHANGED
@@ -1,155 +1,157 @@
|
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
-
4+
|
5 |
-
/
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
+
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
/
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
/
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
/
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
/
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
/
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
|
|
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
+
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
|
lib/Ampersand/License/Remote.php
CHANGED
@@ -1,226 +1,225 @@
|
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
-
4+
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
/
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
Lj1G4MxCeWuTBtS=
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
+
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
|
225 |
+
e/qogVwpGOn0eAX8Hfu=
|
|
lib/Ampersand/License/ResourceRegistry.php
CHANGED
@@ -1,77 +1,76 @@
|
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
-
4+
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
OHuhe/Qzp0W=
|
1 |
<?php //003ab
|
2 |
if(!extension_loaded('ionCube Loader')){$__oc=strtolower(substr(php_uname(),0,3));$__ln='ioncube_loader_'.$__oc.'_'.substr(phpversion(),0,3).(($__oc=='win')?'.dll':'.so');@dl($__ln);if(function_exists('_il_exec')){return _il_exec();}$__ln='/ioncube/'.$__ln;$__oid=$__id=realpath(ini_get('extension_dir'));$__here=dirname(__FILE__);if(strlen($__id)>1&&$__id[1]==':'){$__id=str_replace('\\','/',substr($__id,2));$__here=str_replace('\\','/',substr($__here,2));}$__rd=str_repeat('/..',substr_count($__id,'/')).$__here.'/';$__i=strlen($__rd);while($__i--){if($__rd[$__i]=='/'){$__lp=substr($__rd,0,$__i).$__ln;if(file_exists($__oid.$__lp)){$__ln=$__lp;break;}}}@dl($__ln);}else{die('The file '.__FILE__." is corrupted.\n");}if(function_exists('_il_exec')){return _il_exec();}echo('Site error: the file <b>'.__FILE__.'</b> requires the ionCube PHP Loader '.basename($__ln).' to be installed by the site administrator.');exit(199);
|
3 |
?>
|
4 |
+
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
|
|
lib/Ampersand/Object.php
CHANGED
@@ -1,123 +1,246 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Object extends Varien_Object
|
17 |
+
{
|
18 |
+
protected static $_singleton = null;
|
19 |
+
|
20 |
+
public function getDataUnset($name = null)
|
21 |
+
{
|
22 |
+
$value = $this->getData($name);
|
23 |
+
$this->unsetData($name);
|
24 |
+
|
25 |
+
return $value;
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getDataSet($name, $value = null)
|
29 |
+
{
|
30 |
+
$value = $this->getData($name);
|
31 |
+
$this->setData($name, $value);
|
32 |
+
|
33 |
+
return $value;
|
34 |
+
}
|
35 |
+
|
36 |
+
/*
|
37 |
+
* Had to disable as completely different params to parent method causing E_STRICT errors.
|
38 |
+
* - Joseph McDermott <joseph.mcdermott@ampersandcommerce.com
|
39 |
+
*
|
40 |
+
public function toXml($rootName = 'item', $addCdata = true, $formatted = false)
|
41 |
+
{
|
42 |
+
return Ampersand_Xml::dataToXml($this->getData(), $rootName, $addCdata, $formatted);
|
43 |
+
}
|
44 |
+
*/
|
45 |
+
|
46 |
+
public function setDataUsingMethod($key, $args = array())
|
47 |
+
{
|
48 |
+
if (is_array($key)) {
|
49 |
+
foreach ($key as $_key => $_args) {
|
50 |
+
$this->setDataUsingMethod($_key, $_args);
|
51 |
+
}
|
52 |
+
} else {
|
53 |
+
self::setDataAtPath($this, $key, $args);
|
54 |
+
}
|
55 |
+
|
56 |
+
return $this;
|
57 |
+
}
|
58 |
+
|
59 |
+
public static function camelize($name)
|
60 |
+
{
|
61 |
+
$name = str_replace('_', ' ', $name);
|
62 |
+
$name = ucwords($name);
|
63 |
+
|
64 |
+
return str_replace(' ', '', $name);
|
65 |
+
}
|
66 |
+
|
67 |
+
protected function _camelize($name)
|
68 |
+
{
|
69 |
+
return self::camelize($name);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Proxy method to Varien_Object _underscore.
|
74 |
+
*
|
75 |
+
* @param string $name
|
76 |
+
* @return string
|
77 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
78 |
+
*/
|
79 |
+
public static function underscore($name)
|
80 |
+
{
|
81 |
+
$object = self::getSingleton();
|
82 |
+
|
83 |
+
return $object->_underscore($name);
|
84 |
+
}
|
85 |
+
|
86 |
+
public static function getDataAtPath($container, $fieldPath)
|
87 |
+
{
|
88 |
+
$fieldParts = explode('/', $fieldPath, 2);
|
89 |
+
$firstField = $fieldParts[0];
|
90 |
+
$fieldPath = array_key_exists(1, $fieldParts) ? $fieldParts[1] : null;
|
91 |
+
|
92 |
+
$value = null;
|
93 |
+
|
94 |
+
if (is_array($container) && array_key_exists($firstField, $container)) {
|
95 |
+
$value = $container[$firstField];
|
96 |
+
}
|
97 |
+
|
98 |
+
if (is_object($container)) {
|
99 |
+
$methodName = 'get' . self::camelize($firstField);
|
100 |
+
$value = call_user_func(array($container, $methodName));
|
101 |
+
}
|
102 |
+
|
103 |
+
if ($fieldPath) {
|
104 |
+
$value = self::getDataAtPath($value, $fieldPath);
|
105 |
+
}
|
106 |
+
|
107 |
+
return $value;
|
108 |
+
}
|
109 |
+
|
110 |
+
public static function setDataAtPath($container, $fieldPath, $value)
|
111 |
+
{
|
112 |
+
$fields = explode('/', $fieldPath);
|
113 |
+
|
114 |
+
$containers = array(&$container);
|
115 |
+
foreach ($fields as $_field) {
|
116 |
+
$_container = &$containers[count($containers) - 1];
|
117 |
+
|
118 |
+
if (is_object($_container)) {
|
119 |
+
$containers[] = self::getDataAtPath($_container, $_field);
|
120 |
+
} else {
|
121 |
+
if (!is_array($_container)) {
|
122 |
+
array_pop($containers);
|
123 |
+
$containers[] = array();
|
124 |
+
$_container = &$containers[count($containers) - 1];
|
125 |
+
}
|
126 |
+
|
127 |
+
if (!array_key_exists($_field, $_container)
|
128 |
+
|| (!is_object($_container[$_field]) && !is_array($_container[$_field]))) {
|
129 |
+
$_container[$_field] = array();
|
130 |
+
}
|
131 |
+
|
132 |
+
$containers[] = &$_container[$_field];
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
$container = &$containers[0];
|
137 |
+
|
138 |
+
/*
|
139 |
+
* The last container is actually the current value of the field which we want to set --
|
140 |
+
* disregard this container
|
141 |
+
*/
|
142 |
+
array_pop($containers);
|
143 |
+
$reversedFields = array_reverse($fields);
|
144 |
+
|
145 |
+
foreach ($reversedFields as $_key => $_field) {
|
146 |
+
$_container = &$containers[count($containers) - 1];
|
147 |
+
array_pop($containers);
|
148 |
+
|
149 |
+
if (is_object($_container)) {
|
150 |
+
if ($_key) {
|
151 |
+
$value = $lastContainer;
|
152 |
+
}
|
153 |
+
|
154 |
+
$methodName = 'set' . self::camelize($_field);
|
155 |
+
call_user_func(array($_container, $methodName), $value);
|
156 |
+
break;
|
157 |
+
} else if (!$_key) {
|
158 |
+
$_container[$_field] = $value;
|
159 |
+
}
|
160 |
+
|
161 |
+
$lastContainer = &$_container;
|
162 |
+
}
|
163 |
+
|
164 |
+
return $container;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Convert a nested array in to a nested Varien Object.
|
169 |
+
*
|
170 |
+
* @param array $data
|
171 |
+
* @param string $class OPTIONAL Object class to be returned.
|
172 |
+
* @return Ampersand_Object Unless different class specified.
|
173 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
174 |
+
*/
|
175 |
+
public static function arrayToObject(array $data, $class = 'Ampersand_Object')
|
176 |
+
{
|
177 |
+
foreach ($data as $_key => $_value) {
|
178 |
+
if (is_array($_value)) {
|
179 |
+
$data[$_key] = self::arrayToObject($_value);
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
return new $class($data);
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Recursively merge two arrays (and their children arrays)
|
188 |
+
*
|
189 |
+
* @param array $array1
|
190 |
+
* @param array $array2
|
191 |
+
* @return array
|
192 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
193 |
+
*/
|
194 |
+
public static function arrayMergeRecursive($array1, $array2)
|
195 |
+
{
|
196 |
+
if (!is_array($array2)) {
|
197 |
+
return $array1;
|
198 |
+
}
|
199 |
+
|
200 |
+
foreach ($array1 as $_field => $_value) {
|
201 |
+
if (!array_key_exists($_field, $array2)) {
|
202 |
+
continue;
|
203 |
+
}
|
204 |
+
|
205 |
+
if (is_array($_value)) {
|
206 |
+
$array1[$_field] = self::arrayMergeRecursive($_value, $array2[$_field]);
|
207 |
+
} else {
|
208 |
+
$array1[$_field] = $array2[$_field];
|
209 |
+
}
|
210 |
+
|
211 |
+
unset($array2[$_field]);
|
212 |
+
}
|
213 |
+
|
214 |
+
$array1 = array_merge($array1, $array2);
|
215 |
+
|
216 |
+
return $array1;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Recursively merges data to the instance's data array
|
221 |
+
*
|
222 |
+
* @param array $data
|
223 |
+
* @return Ampersand_Object
|
224 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
225 |
+
*/
|
226 |
+
public function addDataRecursive($data)
|
227 |
+
{
|
228 |
+
$this->_data = self::arrayMergeRecursive($this->_data, $data);
|
229 |
+
return $this;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Retreive singleton object of self.
|
234 |
+
*
|
235 |
+
* @return Ampersand_Object
|
236 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
237 |
+
*/
|
238 |
+
public static function getSingleton()
|
239 |
+
{
|
240 |
+
if (is_null(self::$_singleton)) {
|
241 |
+
self::$_singleton = new Ampersand_Object;
|
242 |
+
}
|
243 |
+
|
244 |
+
return self::$_singleton;
|
245 |
+
}
|
246 |
+
}
|
lib/Ampersand/Pairs.php
CHANGED
@@ -1,63 +1,134 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Pairs implements Iterator
|
17 |
+
{
|
18 |
+
protected $_keys = array();
|
19 |
+
protected $_values = array();
|
20 |
+
|
21 |
+
protected $_position = 0;
|
22 |
+
|
23 |
+
public function __construct(array $keys = array(), array $values = array())
|
24 |
+
{
|
25 |
+
if (count($keys) !== count($values)) {
|
26 |
+
throw new Ampersand_Exception('Values array and keys array are not the same size');
|
27 |
+
}
|
28 |
+
|
29 |
+
foreach ($keys as $_key) {
|
30 |
+
$this->addPair($_key, current($values));
|
31 |
+
|
32 |
+
next($values);
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
public function addPair($key, $value = null)
|
37 |
+
{
|
38 |
+
if (is_array($key)) {
|
39 |
+
$this->_validatePair($key);
|
40 |
+
list($key, $value) = $key;
|
41 |
+
}
|
42 |
+
|
43 |
+
$this->_validateKey($key);
|
44 |
+
|
45 |
+
$this->_keys[] = $key;
|
46 |
+
$this->_values[] = $value;
|
47 |
+
|
48 |
+
return $this;
|
49 |
+
}
|
50 |
+
|
51 |
+
protected function _validatePair(array $pair)
|
52 |
+
{
|
53 |
+
if (count($pair) !== 2) {
|
54 |
+
throw new Ampersand_Exception('Pair must be an array with two elements (key, value)');
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
protected function _validateKey($key)
|
59 |
+
{
|
60 |
+
if (!is_int($key) && !is_string($key)) {
|
61 |
+
throw new Ampersand_Exception('Key values must be one either int or string');
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
public function toArray()
|
66 |
+
{
|
67 |
+
if ($this->_keys) {
|
68 |
+
return array_combine($this->_keys, $this->_values);
|
69 |
+
}
|
70 |
+
|
71 |
+
return array();
|
72 |
+
}
|
73 |
+
|
74 |
+
public function count()
|
75 |
+
{
|
76 |
+
return count($this->_keys);
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Return the current element
|
81 |
+
*
|
82 |
+
* @return mixed Can return any type.
|
83 |
+
*/
|
84 |
+
public function current()
|
85 |
+
{
|
86 |
+
if ($this->valid()) {
|
87 |
+
return $this->_values[$this->_position];
|
88 |
+
}
|
89 |
+
|
90 |
+
return false;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Move forward to next element
|
95 |
+
*
|
96 |
+
* @return void Any returned value is ignored.
|
97 |
+
*/
|
98 |
+
public function next()
|
99 |
+
{
|
100 |
+
$this->_position++;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Return the key of the current element
|
105 |
+
*
|
106 |
+
* @return scalar scalar on success, integer
|
107 |
+
* 0 on failure.
|
108 |
+
*/
|
109 |
+
public function key()
|
110 |
+
{
|
111 |
+
return $this->_keys[$this->_position];
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Checks if current position is valid
|
116 |
+
*
|
117 |
+
* @return boolean The return value will be casted to boolean and then evaluated.
|
118 |
+
* Returns true on success or false on failure.
|
119 |
+
*/
|
120 |
+
public function valid()
|
121 |
+
{
|
122 |
+
return array_key_exists($this->_position, $this->_values);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Rewind the Iterator to the first element
|
127 |
+
*
|
128 |
+
* @return void Any returned value is ignored.
|
129 |
+
*/
|
130 |
+
public function rewind()
|
131 |
+
{
|
132 |
+
$this->_position = 0;
|
133 |
+
}
|
134 |
+
}
|
lib/Ampersand/Random.php
ADDED
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Random
|
3 |
+
{
|
4 |
+
/** @var array */
|
5 |
+
protected static $_firstnames = array(
|
6 |
+
'Oliver',
|
7 |
+
'Jack',
|
8 |
+
'Harry',
|
9 |
+
'Alfie',
|
10 |
+
'Charlie',
|
11 |
+
'Thomas',
|
12 |
+
'William',
|
13 |
+
'Joshua',
|
14 |
+
'George',
|
15 |
+
'James',
|
16 |
+
'Daniel',
|
17 |
+
'Jacob',
|
18 |
+
'Ethan',
|
19 |
+
'Samuel',
|
20 |
+
'Joseph',
|
21 |
+
'Dylan',
|
22 |
+
'Mohammed',
|
23 |
+
'Noah',
|
24 |
+
'Lucas',
|
25 |
+
'Oscar',
|
26 |
+
'Alexander',
|
27 |
+
'Benjamin',
|
28 |
+
'Max',
|
29 |
+
'Archie',
|
30 |
+
'Riley',
|
31 |
+
'Jayden',
|
32 |
+
'Lewis',
|
33 |
+
'Logan',
|
34 |
+
'Jake',
|
35 |
+
'Ryan',
|
36 |
+
'Muhammad',
|
37 |
+
'Tyler',
|
38 |
+
'Liam',
|
39 |
+
'Henry',
|
40 |
+
'Finley',
|
41 |
+
'Leo',
|
42 |
+
'Isaac',
|
43 |
+
'Luke',
|
44 |
+
'Adam',
|
45 |
+
'Callum',
|
46 |
+
'Olivia',
|
47 |
+
'Sophie',
|
48 |
+
'Emily',
|
49 |
+
'Lily',
|
50 |
+
'Amelia',
|
51 |
+
'Jessica',
|
52 |
+
'Ruby',
|
53 |
+
'Chloe',
|
54 |
+
'Grace',
|
55 |
+
'Evie',
|
56 |
+
'Ava',
|
57 |
+
'Isabella',
|
58 |
+
'Mia',
|
59 |
+
'Maisie',
|
60 |
+
'Daisy',
|
61 |
+
'Poppy',
|
62 |
+
'Isabelle',
|
63 |
+
'Ella',
|
64 |
+
'Freya',
|
65 |
+
'Charlotte',
|
66 |
+
'Lucy',
|
67 |
+
'Isla',
|
68 |
+
'Megan',
|
69 |
+
'Scarlett',
|
70 |
+
'Holly',
|
71 |
+
'Imogen',
|
72 |
+
'Sophia',
|
73 |
+
'Phoebe',
|
74 |
+
'Ellie',
|
75 |
+
'Summer',
|
76 |
+
'Hannah',
|
77 |
+
'Millie',
|
78 |
+
'Lola',
|
79 |
+
'Abigail',
|
80 |
+
'Erin',
|
81 |
+
'Lacey',
|
82 |
+
'Eva',
|
83 |
+
'Amy',
|
84 |
+
'Lilly',
|
85 |
+
'Katie',
|
86 |
+
);
|
87 |
+
|
88 |
+
/** @var array */
|
89 |
+
protected static $_lastnames = array(
|
90 |
+
'Smith',
|
91 |
+
'Jones',
|
92 |
+
'Taylor',
|
93 |
+
'Brown',
|
94 |
+
'Williams',
|
95 |
+
'Wilson',
|
96 |
+
'Johnson',
|
97 |
+
'Davies',
|
98 |
+
'Robinson',
|
99 |
+
'Wright',
|
100 |
+
'Thompson',
|
101 |
+
'Evans',
|
102 |
+
'Walker',
|
103 |
+
'White',
|
104 |
+
'Roberts',
|
105 |
+
'Green',
|
106 |
+
'Hall',
|
107 |
+
'Wood',
|
108 |
+
'Jackson',
|
109 |
+
'Clarke',
|
110 |
+
'Brown',
|
111 |
+
'Smith',
|
112 |
+
'Patel',
|
113 |
+
'Jones',
|
114 |
+
'Williams',
|
115 |
+
'Johnson',
|
116 |
+
'Taylor',
|
117 |
+
'Thomas',
|
118 |
+
'Roberts',
|
119 |
+
'Khan',
|
120 |
+
'Lewis',
|
121 |
+
'Jackson',
|
122 |
+
'Clarke',
|
123 |
+
'James',
|
124 |
+
'Phillips',
|
125 |
+
'Wilson',
|
126 |
+
'Ali',
|
127 |
+
'Mason',
|
128 |
+
'Mitchell',
|
129 |
+
'Rose',
|
130 |
+
'Davis',
|
131 |
+
'Davies',
|
132 |
+
'Rodríguez',
|
133 |
+
'Cox',
|
134 |
+
'Alexander',
|
135 |
+
);
|
136 |
+
|
137 |
+
/** @var array */
|
138 |
+
protected static $_emailDomains = array(
|
139 |
+
'hotmail.com',
|
140 |
+
'hotmail.co.uk',
|
141 |
+
'gmail.com',
|
142 |
+
'yahoo.com',
|
143 |
+
);
|
144 |
+
|
145 |
+
/**
|
146 |
+
* @return string
|
147 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
148 |
+
*/
|
149 |
+
public static function getFirstname()
|
150 |
+
{
|
151 |
+
$key = array_rand(self::$_firstnames);
|
152 |
+
|
153 |
+
return self::$_firstnames[$key];
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* @return string
|
158 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
159 |
+
*/
|
160 |
+
public static function getLastname()
|
161 |
+
{
|
162 |
+
$key = array_rand(self::$_lastnames);
|
163 |
+
|
164 |
+
return self::$_lastnames[$key];
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* @return string
|
169 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
170 |
+
*/
|
171 |
+
public static function getEmailDomain()
|
172 |
+
{
|
173 |
+
$key = array_rand(self::$_emailDomains);
|
174 |
+
|
175 |
+
return self::$_emailDomains[$key];
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* @param string $include OPTIONAL
|
180 |
+
* @return string
|
181 |
+
* @author Josh Di Fabio <josh.difabio@ampersandcommerce.com>
|
182 |
+
*/
|
183 |
+
public static function getEmail($include = null)
|
184 |
+
{
|
185 |
+
$name = self::getFirstname() . '.' . self::getLastname();
|
186 |
+
|
187 |
+
return ($name . $include . '@' . self::getEmailDomain());
|
188 |
+
}
|
189 |
+
}
|
lib/Ampersand/Registry.php
CHANGED
@@ -1,49 +1,119 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Registry
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Registry
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Registry
|
17 |
+
{
|
18 |
+
/** @var Ampersand_Registry_Container */
|
19 |
+
protected static $_globalContainer;
|
20 |
+
/** @var array */
|
21 |
+
protected static $_namespacedContainers = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Resets the specified registry. Resets all registries if no namespace is provided
|
25 |
+
*
|
26 |
+
* @param string $namespace OPTIONAL The namespace of the container to reset
|
27 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
28 |
+
*/
|
29 |
+
public static function reset($namespace = null)
|
30 |
+
{
|
31 |
+
if (is_null($namespace)) {
|
32 |
+
self::getInstance()->reset();
|
33 |
+
self::$_globalContainer = null;
|
34 |
+
|
35 |
+
foreach (self::$_namespacedContainers as $_container) {
|
36 |
+
$_container->reset();
|
37 |
+
}
|
38 |
+
self::$_namespacedContainers = array();
|
39 |
+
} else {
|
40 |
+
self::getInstance($namespace)->reset();
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Gets a value from the container instance for the specified namespace
|
46 |
+
*
|
47 |
+
* @param string $key
|
48 |
+
* @param string $namespace OPTIONAL The namespace of the container to access
|
49 |
+
* @return mixed
|
50 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
51 |
+
*/
|
52 |
+
public static function get($key, $namespace = null)
|
53 |
+
{
|
54 |
+
return self::getInstance($namespace)->get($key);
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Sets a value in the container instance for the specified namespace
|
59 |
+
*
|
60 |
+
* @param string $key
|
61 |
+
* @param mixed $value
|
62 |
+
* @param string $namespace OPTIONAL The namespace of the container to update
|
63 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
64 |
+
*/
|
65 |
+
public static function set($key, $value, $namespace = null)
|
66 |
+
{
|
67 |
+
self::getInstance($namespace)->set($key, $value);
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Returns whether or not a key exists in the container instance for the specified namespace
|
72 |
+
*
|
73 |
+
* @param string $key
|
74 |
+
* @param string $namespace OPTIONAL The namespace of the container to check
|
75 |
+
* @return bool
|
76 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
77 |
+
*/
|
78 |
+
public static function has($key, $namespace = null)
|
79 |
+
{
|
80 |
+
return self::getInstance($namespace)->has($key);
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Gets the container instance for the specified namespace
|
85 |
+
*
|
86 |
+
* @param string $namespace OPTIONAL
|
87 |
+
* @return Ampersand_Registry_Container
|
88 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
89 |
+
*/
|
90 |
+
public static function getInstance($namespace = null)
|
91 |
+
{
|
92 |
+
if (is_null($namespace)) {
|
93 |
+
if (is_null(self::$_globalContainer)) {
|
94 |
+
self::$_globalContainer = new Ampersand_Registry_Container();
|
95 |
+
}
|
96 |
+
|
97 |
+
return self::$_globalContainer;
|
98 |
+
}
|
99 |
+
|
100 |
+
if (!array_key_exists($namespace, self::$_namespacedContainers)) {
|
101 |
+
new Ampersand_Registry_Container($namespace);
|
102 |
+
}
|
103 |
+
|
104 |
+
return self::$_namespacedContainers[$namespace];
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Stores a static reference to the provided namespaced container instance
|
109 |
+
*
|
110 |
+
* @param Ampersand_Registry_Container $container
|
111 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
112 |
+
*/
|
113 |
+
public static function addInstance(Ampersand_Registry_Container $container)
|
114 |
+
{
|
115 |
+
if ($namespace = $container->getNamespace()) {
|
116 |
+
self::$_namespacedContainers[$namespace] = $container;
|
117 |
+
}
|
118 |
+
}
|
119 |
+
}
|
lib/Ampersand/Registry/Abstract.php
CHANGED
@@ -1,28 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
xStdg3050ARL8Oaidfk145Zi+nrxz9Wpq+BRMky0sHeC8Jqljfd75tz2SBgRINwuUhufw//BNUyA
|
21 |
-
IivadGWEPy3zh1RCqfsWrNq981qTnNLUDivgSPFYtOR+xyIqYM0ESkkOw1l416gRgxkb1wAlIpr6
|
22 |
-
nbH3bSXW82iKSUiiZBhrUKkcQHFawpEMT1ETmKar2FKAkev/AWZGoxIM0dzgiKWtbEHFix17r8km
|
23 |
-
0lKqUS9uNwp9VfQO6LJV2bj43B4gqO0iEBLsYdG8ZSRzCXsFtYpUymZ6ubHIX0EOWxAd7m2bfFWL
|
24 |
-
Ae0DKkr9bXt87l/wOJNCvsi3QtYloHfE49pp/gFW29If5eAS4xo+KqXGB7zs96+zMi+tJa/3PJ16
|
25 |
-
+Lo4v5EVl0Qh8zArdabClJYD1nIJjKkZhahAj/QZe9ibkU3/0BSwGsrtiNA+Qq2E99QXNbbMRlJ+
|
26 |
-
7WvTynhYbOV0eCJ7wPE5IuB2xJInnaL/RWzG5qphVcPyIuXO1atwb/vMip4vLWtjzH2bRihIfcyH
|
27 |
-
3TBTjNknH3x+oUyCCZTSWDqj80jL4P4KaNabWzw7inDfeVSjm0SKZabxEyY48RtIeBcRmNqdP5/m
|
28 |
-
sRzAm1MEPEVfLwITRXvhSwYCFQ+t/8DEblb0oQwXKZukmngwP+U7snd/po2bj0LP6jG=
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Registry
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Registry
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
abstract class Ampersand_Registry_Abstract implements Ampersand_Registry_Interface
|
17 |
+
{
|
18 |
+
|
19 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/Ampersand/Registry/Container.php
CHANGED
@@ -1,38 +1,107 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Registry
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Registry
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Registry_Container
|
17 |
+
{
|
18 |
+
/** @var string */
|
19 |
+
protected $_namespace;
|
20 |
+
/** @var array */
|
21 |
+
protected $_values = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Stores the provided namespace against this container and adds this container instance to
|
25 |
+
* the global registry
|
26 |
+
*
|
27 |
+
* @param string $namespace OPTIONAL
|
28 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
29 |
+
*/
|
30 |
+
public function __construct($namespace = null)
|
31 |
+
{
|
32 |
+
if (!is_null($namespace)) {
|
33 |
+
$this->_namespace = $namespace;
|
34 |
+
}
|
35 |
+
|
36 |
+
if (!is_null($this->_namespace)) {
|
37 |
+
Ampersand_Registry::addInstance($this);
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Returns the namespace of this registry container
|
43 |
+
*
|
44 |
+
* @return string
|
45 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
46 |
+
*/
|
47 |
+
public function getNamespace()
|
48 |
+
{
|
49 |
+
return $this->_namespace;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Resets this container to its original state. Values are wiped, etc.
|
54 |
+
*
|
55 |
+
* @return Ampersand_Registry_Container
|
56 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
57 |
+
*/
|
58 |
+
public function reset()
|
59 |
+
{
|
60 |
+
$this->_values = array();
|
61 |
+
|
62 |
+
return $this;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Gets a value from this container
|
67 |
+
*
|
68 |
+
* @param string $key
|
69 |
+
* @return mixed
|
70 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
71 |
+
*/
|
72 |
+
public function get($key)
|
73 |
+
{
|
74 |
+
if (!array_key_exists($key, $this->_values)) {
|
75 |
+
return null;
|
76 |
+
}
|
77 |
+
|
78 |
+
return $this->_values[$key];
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Sets a value in this container
|
83 |
+
*
|
84 |
+
* @param string $key
|
85 |
+
* @param mixed $value
|
86 |
+
* @return Ampersand_Registry_Container
|
87 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
88 |
+
*/
|
89 |
+
public function set($key, $value)
|
90 |
+
{
|
91 |
+
$this->_values[$key] = $value;
|
92 |
+
|
93 |
+
return $this;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Returns whether or not a key exists in this container
|
98 |
+
*
|
99 |
+
* @param string $key
|
100 |
+
* @return bool
|
101 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
102 |
+
*/
|
103 |
+
public function has($key)
|
104 |
+
{
|
105 |
+
return array_key_exists($key, $this->_values);
|
106 |
+
}
|
107 |
+
}
|
lib/Ampersand/Registry/Interface.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Registry
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Registry
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
interface Ampersand_Registry_Interface
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* Resets the registry
|
20 |
+
*
|
21 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
22 |
+
*/
|
23 |
+
public static function reset();
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Gets a value from the container instance
|
27 |
+
*
|
28 |
+
* @param string $key
|
29 |
+
* @return mixed
|
30 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
31 |
+
*/
|
32 |
+
public static function get($key);
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Sets a value in the container instance
|
36 |
+
*
|
37 |
+
* @param string $key
|
38 |
+
* @param mixed $value
|
39 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
40 |
+
*/
|
41 |
+
public static function set($key, $value);
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Returns whether or not a key exists in the container instance
|
45 |
+
*
|
46 |
+
* @param string $key
|
47 |
+
* @return bool
|
48 |
+
* @author Josh Di fabio <josh.difabio@ampersandit.co.uk>
|
49 |
+
*/
|
50 |
+
public static function has($key);
|
51 |
+
}
|
lib/Ampersand/Stack.php
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Ampersand_Stack extends Ampersand_Object
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* Key to be used to set data against the object.
|
6 |
+
*
|
7 |
+
* @var string $_stackKey
|
8 |
+
*/
|
9 |
+
protected $_stackKey = 'stack';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Define the key to be used to set data against the object.
|
13 |
+
*
|
14 |
+
* @param string $key
|
15 |
+
* @return Ampersand_Stack
|
16 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
17 |
+
*/
|
18 |
+
public function setStackKey($key)
|
19 |
+
{
|
20 |
+
$this->_stackKey = $key;
|
21 |
+
|
22 |
+
return $this;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Retrieve the key to be used to set data against the object.
|
27 |
+
*
|
28 |
+
* @return string
|
29 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
30 |
+
*/
|
31 |
+
public function getStackKey()
|
32 |
+
{
|
33 |
+
if ($this->_stackKey == '') {
|
34 |
+
throw new Exception('Stack key cannot be empty.');
|
35 |
+
}
|
36 |
+
|
37 |
+
return $this->_stackKey;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Add data to the stack.
|
42 |
+
*
|
43 |
+
* @param mixed $value
|
44 |
+
* @param string $key
|
45 |
+
* @return Ampersand_Stack
|
46 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
47 |
+
*/
|
48 |
+
public function addToStack($value, $key = null)
|
49 |
+
{
|
50 |
+
$stack = $this->getStack();
|
51 |
+
|
52 |
+
if (!is_null($key)) {
|
53 |
+
$stack[$key] = $value;
|
54 |
+
} else {
|
55 |
+
$stack[] = $value;
|
56 |
+
}
|
57 |
+
|
58 |
+
$this->setData($this->getStackKey(), $stack);
|
59 |
+
|
60 |
+
return $this;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Set the stack data.
|
65 |
+
*
|
66 |
+
* @param array $value
|
67 |
+
* @return Ampersand_Stack
|
68 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
69 |
+
*/
|
70 |
+
public function setStack($value)
|
71 |
+
{
|
72 |
+
$this->setData($this->getStackKey(), $value);
|
73 |
+
|
74 |
+
return $this;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Empty the stack data.
|
79 |
+
*
|
80 |
+
* @return Ampersand_Stack
|
81 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
82 |
+
*/
|
83 |
+
public function emptyStack()
|
84 |
+
{
|
85 |
+
$this->setData($this->getStackKey(), array());
|
86 |
+
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Retrieve the stack data.
|
92 |
+
*
|
93 |
+
* @return array
|
94 |
+
* @author Joseph McDermott <joseph.mcdermott@ampersandcommerce.com>
|
95 |
+
*/
|
96 |
+
public function getStack()
|
97 |
+
{
|
98 |
+
$stack = $this->getData($this->getStackKey());
|
99 |
+
if (!is_array($stack)) {
|
100 |
+
$stack = array();
|
101 |
+
}
|
102 |
+
|
103 |
+
return $stack;
|
104 |
+
}
|
105 |
+
}
|
lib/Ampersand/Xml.php
CHANGED
@@ -1,228 +1,411 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Xml
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Xml
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Xml
|
17 |
+
{
|
18 |
+
const NULL_NAMESPACE = 'http://null/';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Creates a new XML element without creating warnings if invalid XML is provided.
|
22 |
+
* Invalid XML will cause an exception to be thrown
|
23 |
+
*
|
24 |
+
* @param string $source XML string or url to a file containing XML
|
25 |
+
* @param bool $isUrl OPTIONAL true => the source is a URL, false => source is XML
|
26 |
+
* @param string $class OPTIONAL Class to instantiate
|
27 |
+
* @return mixed The new XML element
|
28 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
29 |
+
*/
|
30 |
+
public static function factory($source, $isUrl = false, $class = null)
|
31 |
+
{
|
32 |
+
if (is_null($class)) {
|
33 |
+
$class = 'Ampersand_Xml_Element';
|
34 |
+
}
|
35 |
+
|
36 |
+
return @new $class($source, null, $isUrl);
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Checks whether the argument is a valid XML name
|
41 |
+
*
|
42 |
+
* @param mixed $name
|
43 |
+
* @return bool
|
44 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
45 |
+
*/
|
46 |
+
public static function isValidName($name)
|
47 |
+
{
|
48 |
+
if (!is_string($name)) {
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
|
52 |
+
$namePattern = self::getNamePattern();
|
53 |
+
|
54 |
+
return (bool) preg_match("/^$namePattern$/i", $name);
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Checks whether the argument is a valid compound
|
59 |
+
*
|
60 |
+
* @param mixed $compound
|
61 |
+
* @return bool
|
62 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
63 |
+
*/
|
64 |
+
public static function isValidCompound($compound)
|
65 |
+
{
|
66 |
+
if (!is_string($compound)) {
|
67 |
+
return false;
|
68 |
+
}
|
69 |
+
|
70 |
+
$namePattern = self::getNamePattern();
|
71 |
+
|
72 |
+
return (bool) preg_match("/^$namePattern(#[0-9]+)?$/i", $compound);
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Builds a compound string using an element name, a namespace prefix and an
|
77 |
+
* index. This can be used to ensure a unique key per element when retrieving
|
78 |
+
* an array of child elements for a given element
|
79 |
+
*
|
80 |
+
* @param string $name An element name. If $prefix is provided then this
|
81 |
+
* variable should not include a namespace prefix
|
82 |
+
* @param string $prefix OPTIONAL A namespace prefix
|
83 |
+
* @param int $index OPTIONAL If an element has siblings which share the same
|
84 |
+
* name and prefix then an index can be used to differentiate between them
|
85 |
+
* @return string
|
86 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
87 |
+
*/
|
88 |
+
public static function buildCompound($name, $prefix = null, $index = null)
|
89 |
+
{
|
90 |
+
if (!is_null($prefix)) {
|
91 |
+
$name = "$prefix:$name";
|
92 |
+
}
|
93 |
+
if (!is_null($index)) {
|
94 |
+
$name = "$name#$index";
|
95 |
+
}
|
96 |
+
|
97 |
+
return $name;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Extracts the name part from a compound string
|
102 |
+
*
|
103 |
+
* @param string $compound
|
104 |
+
* @param bool $includePrefix OPTIONAL Include the namespace prefix in the
|
105 |
+
* returned name
|
106 |
+
* @return string
|
107 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
108 |
+
*/
|
109 |
+
public static function getNameFromCompound($compound, $includePrefix = true)
|
110 |
+
{
|
111 |
+
if (!$includePrefix) {
|
112 |
+
// Strip prefix
|
113 |
+
if (false !== ($needlePos = strpos($compound, ':'))) {
|
114 |
+
$compound = substr($compound, 1 + $needlePos);
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
// Strip index
|
119 |
+
if (false !== ($needlePos = strpos($compound, '#'))) {
|
120 |
+
$compound = substr($compound, 0, $needlePos);
|
121 |
+
}
|
122 |
+
|
123 |
+
return $compound;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Extracts the prefix part from a compound string
|
128 |
+
*
|
129 |
+
* @param string $compound
|
130 |
+
* @return mixed Prefix as string; null if no prefix in the compound
|
131 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
132 |
+
*/
|
133 |
+
public static function getPrefixFromCompound($compound)
|
134 |
+
{
|
135 |
+
$prefix = null;
|
136 |
+
|
137 |
+
if (false !== ($needlePos = strpos($compound, ':'))) {
|
138 |
+
$prefix = substr($compound, 0, $needlePos);
|
139 |
+
}
|
140 |
+
|
141 |
+
return $prefix;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Extracts the index part from a compound string
|
146 |
+
*
|
147 |
+
* @param string $compound
|
148 |
+
* @return mixed Index as an int; null if no index is in the compound
|
149 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
150 |
+
*/
|
151 |
+
public static function getIndexFromCompound($compound)
|
152 |
+
{
|
153 |
+
$index = null;
|
154 |
+
|
155 |
+
if (false !== ($needlePos = strpos($compound, '#'))) {
|
156 |
+
$index = substr($compound, 1 + $needlePos);
|
157 |
+
}
|
158 |
+
|
159 |
+
return $index;
|
160 |
+
}
|
161 |
+
|
162 |
+
public static function removeDeclaration($xml)
|
163 |
+
{
|
164 |
+
$declaration = self::getDeclarationPattern();
|
165 |
+
|
166 |
+
return preg_replace("#^(\s*)(?:$declaration)#", "$1", $xml);
|
167 |
+
}
|
168 |
+
|
169 |
+
public static function addDoctype($xml, $doctype)
|
170 |
+
{
|
171 |
+
$declaration = self::getDeclarationPattern();
|
172 |
+
|
173 |
+
return preg_replace("#^(\s*{$declaration})#", '$1' . PHP_EOL . $doctype, $xml);
|
174 |
+
}
|
175 |
+
|
176 |
+
public static function getDeclarationPattern()
|
177 |
+
{
|
178 |
+
return '<\?xml[^>]+\?>';
|
179 |
+
}
|
180 |
+
|
181 |
+
public static function getNodePattern()
|
182 |
+
{
|
183 |
+
$namePattern = self::getNamePattern();
|
184 |
+
|
185 |
+
$attribute = $namePattern . '\s*=\s*"[^"]*"';
|
186 |
+
$attributes = "(?:\s*$attribute)*";
|
187 |
+
|
188 |
+
return "<(?P<node>(?P<name>$namePattern)\s*(?P<attributes>$attributes)\s*)(?P<self_close>/)?>";
|
189 |
+
}
|
190 |
+
|
191 |
+
public static function getRootNode($xml, $part = 'node')
|
192 |
+
{
|
193 |
+
$declaration = self::getDeclarationPattern();
|
194 |
+
$element = self::getNodePattern();
|
195 |
+
preg_match("#^\s*(?:$declaration)?\s*$element#i", $xml, $matches);
|
196 |
+
|
197 |
+
if (isset($matches[$part])) {
|
198 |
+
return $matches[$part];
|
199 |
+
}
|
200 |
+
|
201 |
+
return null;
|
202 |
+
}
|
203 |
+
|
204 |
+
public static function removeNamespaces($xml, array $namespacesToRemove = null)
|
205 |
+
{
|
206 |
+
$attributesString = '';
|
207 |
+
|
208 |
+
$attributes = self::getAttributes($xml);
|
209 |
+
foreach ($attributes as $_name => $_value) {
|
210 |
+
if (self::_shouldKeepAttribute($_name, $_value, $namespacesToRemove)) {
|
211 |
+
$attributesString .= " $_name=\"$_value\"";
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
$declaration = self::getDeclarationPattern();
|
216 |
+
$element = self::getNodePattern();
|
217 |
+
$nodeName = self::getRootNode($xml, 'name');
|
218 |
+
$node = self::getRootNode($xml);
|
219 |
+
$suffix = self::getRootNode($xml, 'self_close');
|
220 |
+
|
221 |
+
return preg_replace("#^(\s*(?:$declaration)?\s*)$element#", "$1<{$nodeName}{$attributesString}{$suffix}>", $xml);
|
222 |
+
}
|
223 |
+
|
224 |
+
protected static function _shouldKeepAttribute($fullName, $value, array $namespacesToRemove = null)
|
225 |
+
{
|
226 |
+
$prefix = self::getPrefixFromCompound($fullName);
|
227 |
+
|
228 |
+
if ('xmlns' === $fullName) {
|
229 |
+
return $value !== Ampersand_XML::NULL_NAMESPACE;
|
230 |
+
}
|
231 |
+
if ('xmlns' !== $prefix) {
|
232 |
+
return true;
|
233 |
+
}
|
234 |
+
|
235 |
+
if ($namespacesToRemove) {
|
236 |
+
$name = !$prefix ? '' : self::getNameFromCompound($fullName, false);
|
237 |
+
if (!in_array($name, $namespacesToRemove) && !in_array($value, $namespacesToRemove)) {
|
238 |
+
return true;
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
return false;
|
243 |
+
}
|
244 |
+
|
245 |
+
public static function getNamePattern($prefix = null)
|
246 |
+
{
|
247 |
+
if ($prefix) {
|
248 |
+
return "$prefix:[-_:\.a-zA-Z0-9]*";
|
249 |
+
}
|
250 |
+
|
251 |
+
return '[_:a-zA-Z][-_:\.a-zA-Z0-9]*';
|
252 |
+
}
|
253 |
+
|
254 |
+
public static function getAttributes($xml, $prefix = null)
|
255 |
+
{
|
256 |
+
$attributes = array();
|
257 |
+
|
258 |
+
if ($attributesString = self::getRootNode($xml, 'attributes')) {
|
259 |
+
$namePattern = self::getNamePattern($prefix);
|
260 |
+
$attributePattern = "(?P<names>$namePattern)\s*=\s*\"(?P<values>[^\"]*)\"";
|
261 |
+
|
262 |
+
preg_match_all("#$attributePattern#", $attributesString, $matches);
|
263 |
+
|
264 |
+
if ($matches['names']) {
|
265 |
+
$attributes = array_combine($matches['names'], $matches['values']);
|
266 |
+
}
|
267 |
+
}
|
268 |
+
|
269 |
+
return $attributes;
|
270 |
+
}
|
271 |
+
|
272 |
+
public static function rebuildElement(Ampersand_Xml_Element $element, array $children)
|
273 |
+
{
|
274 |
+
$name = $element->getName();
|
275 |
+
$attributes = $element->getAttributes();
|
276 |
+
|
277 |
+
foreach ($element->getNamespaces(true) as $_prefix => $_namespace) {
|
278 |
+
if ($_prefix) {
|
279 |
+
$attributes["xmlns:$_prefix"] = $_namespace;
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
$filteredChildren = array();
|
284 |
+
|
285 |
+
foreach ($children as $_child) {
|
286 |
+
$_filtered = self::removeDeclaration($_child);
|
287 |
+
if (strlen($_filtered)) {
|
288 |
+
if ($_childNamespaces = self::getAttributes($_filtered, 'xmlns')) {
|
289 |
+
$_filtered = self::removeNamespaces($_filtered);
|
290 |
+
$attributes = array_merge($_childNamespaces, $attributes);
|
291 |
+
}
|
292 |
+
|
293 |
+
$filteredChildren[] = $_filtered;
|
294 |
+
}
|
295 |
+
}
|
296 |
+
|
297 |
+
$attributesString = self::attributesToString($attributes);
|
298 |
+
$innerXml = implode("\n", $filteredChildren);
|
299 |
+
|
300 |
+
$xml = "<{$name}{$attributesString}>$innerXml</$name>";
|
301 |
+
|
302 |
+
return $element->getNewInstance($xml);
|
303 |
+
}
|
304 |
+
|
305 |
+
public static function attributesToString($attributes)
|
306 |
+
{
|
307 |
+
$attributesString = '';
|
308 |
+
|
309 |
+
foreach ($attributes as $_name => $_value) {
|
310 |
+
$attributesString .= " $_name=\"$_value\"";
|
311 |
+
}
|
312 |
+
|
313 |
+
return $attributesString;
|
314 |
+
}
|
315 |
+
|
316 |
+
public static function dataToXml($data, $rootName = null, $addCdata = true, $formatted = false)
|
317 |
+
{
|
318 |
+
$xml = self::_dataToXml($data, $rootName, $addCdata, $formatted);
|
319 |
+
|
320 |
+
if (!empty($rootName) && $formatted) {
|
321 |
+
try {
|
322 |
+
$xmlObject = Ampersand_Xml::factory($xml);
|
323 |
+
$xml = $xmlObject->asFormattedXml();
|
324 |
+
} catch (Exception $e) {
|
325 |
+
// $xml does not contain a valid XML string
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
return $xml;
|
330 |
+
}
|
331 |
+
|
332 |
+
protected static function _dataToXml($data, $rootName, $addCdata)
|
333 |
+
{
|
334 |
+
if (!$data) {
|
335 |
+
if (!empty($rootName)) {
|
336 |
+
return "<$rootName/>\n";
|
337 |
+
}
|
338 |
+
|
339 |
+
return '';
|
340 |
+
}
|
341 |
+
|
342 |
+
if (!is_array($data)) {
|
343 |
+
if ($addCdata) {
|
344 |
+
$xml = "<![CDATA[$data]]>";
|
345 |
+
} else {
|
346 |
+
$xml = self::escape($data);
|
347 |
+
}
|
348 |
+
|
349 |
+
if (!empty($rootName)) {
|
350 |
+
$xml = "<$rootName>$xml</$rootName>"."\n";
|
351 |
+
}
|
352 |
+
|
353 |
+
return $xml;
|
354 |
+
}
|
355 |
+
|
356 |
+
$_unnamedFields = array();
|
357 |
+
$_namedFields = array();
|
358 |
+
|
359 |
+
foreach ($data as $_fieldName => $_fieldValue) {
|
360 |
+
if (preg_match('/^\d+$/', $_fieldName)) {
|
361 |
+
$_unnamedFields[] = $_fieldValue;
|
362 |
+
} else {
|
363 |
+
$_namedFields[$_fieldName] = $_fieldValue;
|
364 |
+
}
|
365 |
+
}
|
366 |
+
|
367 |
+
$xml = '';
|
368 |
+
|
369 |
+
if ($_namedFields) {
|
370 |
+
if (!empty($rootName)) {
|
371 |
+
$xml.= "<$rootName>\n";
|
372 |
+
}
|
373 |
+
|
374 |
+
foreach ($_namedFields as $_fieldName => $_fieldValue) {
|
375 |
+
$xml .= self::dataToXml($_fieldValue, $_fieldName, $addCdata);
|
376 |
+
}
|
377 |
+
|
378 |
+
if (!empty($rootName)) {
|
379 |
+
$xml.= "</$rootName>\n";
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
if ($_unnamedFields && !empty($rootName)) {
|
384 |
+
foreach ($_unnamedFields as $_fieldValue) {
|
385 |
+
$xml .= self::dataToXml($_fieldValue, $rootName, $addCdata);
|
386 |
+
}
|
387 |
+
}
|
388 |
+
|
389 |
+
return $xml;
|
390 |
+
}
|
391 |
+
|
392 |
+
public static function escape($string)
|
393 |
+
{
|
394 |
+
return str_replace(
|
395 |
+
array('&', '"', "'", '<', '>'),
|
396 |
+
array('&', '"', ''', '<', '>'),
|
397 |
+
$string
|
398 |
+
);
|
399 |
+
}
|
400 |
+
|
401 |
+
public static function isValidXml($string)
|
402 |
+
{
|
403 |
+
try {
|
404 |
+
self::factory($string);
|
405 |
+
} catch (Exception $e) {
|
406 |
+
return false;
|
407 |
+
}
|
408 |
+
|
409 |
+
return true;
|
410 |
+
}
|
411 |
+
}
|
lib/Ampersand/Xml/Config.php
CHANGED
@@ -1,26 +1,31 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Xml
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Xml
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Xml_Config extends Ampersand_Xml_Element
|
17 |
+
{
|
18 |
+
public function extend($source, $overwrite = true, array $compoundsToAppend = array())
|
19 |
+
{
|
20 |
+
if (!is_object($source)) {
|
21 |
+
$source = $this->getNewInstance($source);
|
22 |
+
}
|
23 |
+
|
24 |
+
foreach ($compoundsToAppend as $_compound) {
|
25 |
+
$this->appendChild($source->getChildren($_compound));
|
26 |
+
$source->removeChildren($_compound);
|
27 |
+
}
|
28 |
+
|
29 |
+
return parent::extend($source, $overwrite);
|
30 |
+
}
|
31 |
+
}
|
lib/Ampersand/Xml/Element.php
CHANGED
@@ -1,629 +1,1267 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Xml
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* For php version >= 5.2.4
|
13 |
+
*
|
14 |
+
* @category Ampersand_Library
|
15 |
+
* @package Ampersand_Xml
|
16 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
17 |
+
*/
|
18 |
+
class Ampersand_Xml_Element extends Varien_Simplexml_Element
|
19 |
+
{
|
20 |
+
const NODE_ID_FIELD = '__ampersand_NODE_IDENTIFIER';
|
21 |
+
const NULL_PREFIX = '__ampersand_NULL_PREFIX';
|
22 |
+
const COMPOUND_WILDCARD = '*';
|
23 |
+
|
24 |
+
protected static $_nextNodeId = 0;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Gets the name of this element including the namespace prefix if set
|
28 |
+
*
|
29 |
+
* @param bool $includePrefix OPTIONAL Include the namespace prefix in the return value
|
30 |
+
* @return string
|
31 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
32 |
+
*/
|
33 |
+
public function getName($includePrefix = true)
|
34 |
+
{
|
35 |
+
$name = parent::getName();
|
36 |
+
if ($includePrefix) {
|
37 |
+
$prefix = $this->getPrefix();
|
38 |
+
if (!is_null($prefix)) {
|
39 |
+
$name = "$prefix:$name";
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
return $name;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Gets the string value of this element
|
48 |
+
*
|
49 |
+
* @return string
|
50 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
51 |
+
*/
|
52 |
+
public function getValue()
|
53 |
+
{
|
54 |
+
if (Ampersand_Xml_Resource::elementHasResource($this)) {
|
55 |
+
return Ampersand_Xml_Resource::getElementValue($this);
|
56 |
+
}
|
57 |
+
|
58 |
+
return (string) $this;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Sets the string value of this element
|
63 |
+
*
|
64 |
+
* @param string $value
|
65 |
+
* @return Ampersand_Xml_Element
|
66 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
67 |
+
*/
|
68 |
+
public function setValue($value, $forceResource = false)
|
69 |
+
{
|
70 |
+
if ($forceResource || (!is_null($value) && !is_scalar($value))) {
|
71 |
+
Ampersand_Xml_Resource::factory($value, $this);
|
72 |
+
} else {
|
73 |
+
$this[0] = (string) $value;
|
74 |
+
Ampersand_Xml_Resource::clearElement($this);
|
75 |
+
}
|
76 |
+
|
77 |
+
return $this;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Unset the value of this element
|
82 |
+
*
|
83 |
+
* @return Ampersand_Xml_Element
|
84 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
85 |
+
*/
|
86 |
+
public function unsetValue()
|
87 |
+
{
|
88 |
+
$this->setValue('');
|
89 |
+
|
90 |
+
return $this;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Gets the namespace prefix which is prepended to the name of this element
|
95 |
+
*
|
96 |
+
* @param string $sourceXml OPTIONAL If specified, get the prefix for an element
|
97 |
+
* specified as an XML string instead of using this element
|
98 |
+
* @return mixed Prefix as string; null if no prefix is set
|
99 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
100 |
+
*/
|
101 |
+
public function getPrefix($sourceXml = null)
|
102 |
+
{
|
103 |
+
$prefix = null;
|
104 |
+
|
105 |
+
if (is_null($sourceXml)) {
|
106 |
+
$sourceXml = $this->asXml();
|
107 |
+
}
|
108 |
+
if (preg_match('#^\s*(?:<\?.*\?>\s*)?<(?P<prefix>[^/\s>]*):#', $this->asXml(), $matches)) {
|
109 |
+
$prefix = $matches['prefix'];
|
110 |
+
}
|
111 |
+
|
112 |
+
return $prefix;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Checks whether this element is aware of a particular namespace prefix
|
117 |
+
*
|
118 |
+
* @param string $prefix
|
119 |
+
* @return bool
|
120 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
121 |
+
*/
|
122 |
+
public function hasPrefix($prefix)
|
123 |
+
{
|
124 |
+
$namespaces = $this->getDocNamespaces(true);
|
125 |
+
foreach ($namespaces as $_prefix => $_namespace) {
|
126 |
+
if ($prefix == $_prefix) {
|
127 |
+
return true;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
return false;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Checks whether this element is aware of a particular namespace
|
136 |
+
*
|
137 |
+
* @param string $namespace
|
138 |
+
* @return bool
|
139 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
140 |
+
*/
|
141 |
+
public function hasNamespace($namespace)
|
142 |
+
{
|
143 |
+
$namespaces = $this->getDocNamespaces(true);
|
144 |
+
foreach ($namespaces as $_namespace) {
|
145 |
+
if ($namespace == $_namespace) {
|
146 |
+
return true;
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
return false;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Gets the namespace associated with the prefix which is prepended to the
|
155 |
+
* name of this element
|
156 |
+
*
|
157 |
+
* @param string $sourceXml OPTIONAL If specified, get the namespace for an
|
158 |
+
* element specified as an XML string instead of using this element
|
159 |
+
* @return mixed Namespace as string; null if no namespace found
|
160 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
161 |
+
*/
|
162 |
+
public function getNamespace($sourceXml = null)
|
163 |
+
{
|
164 |
+
$namespace = null;
|
165 |
+
|
166 |
+
$prefix = $this->getPrefix($sourceXml);
|
167 |
+
if (!is_null($prefix)) {
|
168 |
+
$namespace = $this->getNamespaceByPrefix($prefix);
|
169 |
+
}
|
170 |
+
|
171 |
+
return $namespace;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Converts a namespace prefix to a namespace
|
176 |
+
*
|
177 |
+
* @param string $prefix
|
178 |
+
* @return mixed Namespace as string; null if no namespace found for prefix
|
179 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
180 |
+
*/
|
181 |
+
public function getNamespaceByPrefix($prefix)
|
182 |
+
{
|
183 |
+
$namespaces = $this->getDocNamespaces(true);
|
184 |
+
foreach ($namespaces as $_prefix => $_namespace) {
|
185 |
+
if ($prefix == $_prefix) {
|
186 |
+
return $_namespace;
|
187 |
+
}
|
188 |
+
}
|
189 |
+
|
190 |
+
return null;
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Checks whether another XML element or XML string is equal to this object,
|
195 |
+
* ignoring irrelevant whitespace
|
196 |
+
*
|
197 |
+
* @param mixed $xml XML element or XML string
|
198 |
+
* @param bool $ignoreChildOrder OPTIONAL Ignore order of children in comparison
|
199 |
+
* @param bool $ignoreAttributeOrder OPTIONAL Ignore order of attributes in comparison
|
200 |
+
* @return bool
|
201 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
202 |
+
*/
|
203 |
+
public function equals($target, $ignoreChildOrder = true, $ignoreAttributeOrder = true)
|
204 |
+
{
|
205 |
+
if (!is_object($target)) {
|
206 |
+
$target = $this->getNewInstance($target);
|
207 |
+
} else if ($this === $target) {
|
208 |
+
return true;
|
209 |
+
}
|
210 |
+
|
211 |
+
if ($this->getName() !== $target->getName()) {
|
212 |
+
return false;
|
213 |
+
}
|
214 |
+
|
215 |
+
if (!$this->attributesEqual($target, $ignoreAttributeOrder)) {
|
216 |
+
return false;
|
217 |
+
}
|
218 |
+
|
219 |
+
if (!$this->hasChildren() && !$target->hasChildren()) {
|
220 |
+
return $this->getValue() == $target->getValue();
|
221 |
+
}
|
222 |
+
|
223 |
+
return $this->childrenEqual($target, $ignoreChildOrder);
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Checks whether the attributes of this element are equal to those within
|
228 |
+
* an array or to those of another XML element which can be passed by reference
|
229 |
+
* or specified as a valid XML string
|
230 |
+
*
|
231 |
+
* @param mixed $target Array of attribute (name => value) or XML element
|
232 |
+
* containing attributes or XML string to be converted to such an element
|
233 |
+
* @param bool $ignoreOrder OPTIONAL Ignore order of attributes in comparison
|
234 |
+
* @return bool
|
235 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
236 |
+
*/
|
237 |
+
public function attributesEqual($target, $ignoreOrder = true)
|
238 |
+
{
|
239 |
+
if (is_string($target)) {
|
240 |
+
$target = $this->getNewInstance($target);
|
241 |
+
}
|
242 |
+
if (is_object($target)) {
|
243 |
+
$targetAttributes = $target->getAttributes();
|
244 |
+
} else {
|
245 |
+
$targetAttributes = $target;
|
246 |
+
}
|
247 |
+
|
248 |
+
$localAttributes = $this->getAttributes();
|
249 |
+
|
250 |
+
if (count($localAttributes) != count($targetAttributes)) {
|
251 |
+
return false;
|
252 |
+
}
|
253 |
+
|
254 |
+
if ($ignoreOrder) {
|
255 |
+
return $targetAttributes == $localAttributes;
|
256 |
+
}
|
257 |
+
|
258 |
+
return $targetAttributes === $localAttributes;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Checks whether the children of this element are equal to a set of elements
|
263 |
+
* within an array or the children of another XML element which can be passed
|
264 |
+
* by reference or specified as a valid XML string
|
265 |
+
*
|
266 |
+
* @param mixed $target Array of elements, an XML element containing
|
267 |
+
* children to compare or an XML string to be converted to such an element
|
268 |
+
* @param bool $ignoreOrder OPTIONAL Ignore order of children in comparison
|
269 |
+
* @return bool
|
270 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
271 |
+
*/
|
272 |
+
public function childrenEqual($target, $ignoreOrder = true)
|
273 |
+
{
|
274 |
+
if (is_string($target)) {
|
275 |
+
$target = $this->getNewInstance($target);
|
276 |
+
}
|
277 |
+
if (is_object($target)) {
|
278 |
+
$targetElements = $target->getChildren();
|
279 |
+
} else {
|
280 |
+
$targetElements = $target;
|
281 |
+
}
|
282 |
+
|
283 |
+
$children = $this->getChildren();
|
284 |
+
|
285 |
+
if (count($children) != count($targetElements)) {
|
286 |
+
return false;
|
287 |
+
}
|
288 |
+
|
289 |
+
if ($ignoreOrder) {
|
290 |
+
while (null !== ($_localChild = array_pop($children))) {
|
291 |
+
foreach ($targetElements as $_key => $_foreignChild) {
|
292 |
+
if ($_localChild->equals($_foreignChild)) {
|
293 |
+
unset($targetElements[$_key]);
|
294 |
+
break;
|
295 |
+
}
|
296 |
+
}
|
297 |
+
|
298 |
+
// Check that one of the foreign nodes was matched in this loop
|
299 |
+
if (count($children) != count($targetElements)) {
|
300 |
+
return false;
|
301 |
+
}
|
302 |
+
}
|
303 |
+
} else {
|
304 |
+
while (null !== ($_localChild = array_pop($children))) {
|
305 |
+
$_foreignChild = array_pop($targetElements);
|
306 |
+
if (!$_localChild->equals($_foreignChild)) {
|
307 |
+
return false;
|
308 |
+
}
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
return true;
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Checks whether this element contains any attributes
|
317 |
+
*
|
318 |
+
* @return bool
|
319 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
320 |
+
*/
|
321 |
+
public function hasAttributes()
|
322 |
+
{
|
323 |
+
foreach ($this->getNamespaces() as $_prefix => $_namespace) {
|
324 |
+
if ($this->attributes($_namespace)) {
|
325 |
+
return true;
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
return (bool) $this->attributes();
|
330 |
+
}
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Checks whether this element contains a given attribute
|
334 |
+
*
|
335 |
+
* @param string $name The name of the attribute to check
|
336 |
+
* @return bool
|
337 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
338 |
+
*/
|
339 |
+
public function hasAttribute($name)
|
340 |
+
{
|
341 |
+
return !is_null($this->getAttribute($name));
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Gets all attribute values in this element
|
346 |
+
*
|
347 |
+
* @return array (string) name => (string) value
|
348 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
349 |
+
*/
|
350 |
+
public function getAttributes()
|
351 |
+
{
|
352 |
+
$attributes = array();
|
353 |
+
foreach ($this->attributes() as $_key => $_value) {
|
354 |
+
$attributes[$_key] = (string) $_value;
|
355 |
+
}
|
356 |
+
foreach ($this->getNamespaces() as $_prefix => $_namespace) {
|
357 |
+
foreach ($this->attributes($_namespace) as $_key => $_value) {
|
358 |
+
$attributes["$_prefix:$_key"] = (string) $_value;
|
359 |
+
}
|
360 |
+
}
|
361 |
+
|
362 |
+
return $attributes;
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Gets the value of an attribute from this element
|
367 |
+
*
|
368 |
+
* @param string $name The name of the attribute to access
|
369 |
+
* @return mixed String if attribute exists, null otherwise
|
370 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
371 |
+
*/
|
372 |
+
public function getAttribute($name)
|
373 |
+
{
|
374 |
+
$prefix = Ampersand_Xml::getPrefixFromCompound($name);
|
375 |
+
$name = Ampersand_Xml::getNameFromCompound($name, false);
|
376 |
+
|
377 |
+
@$value = $this->attributes($prefix, true)->$name;
|
378 |
+
if (!is_null($value)) {
|
379 |
+
$value = (string) $value;
|
380 |
+
}
|
381 |
+
|
382 |
+
return $value;
|
383 |
+
}
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Sets the value of an attribute within this element. If the attribute is not
|
387 |
+
* yet set then this method will call appendAttribute
|
388 |
+
*
|
389 |
+
* @param string $name The name of the attribute to set
|
390 |
+
* @param mixed $value The value to set against the attribute
|
391 |
+
* @param string $namespace OPTIONAL If attribute uses a namespace which is
|
392 |
+
* new to this element then it needs to be passed in here
|
393 |
+
* @return Ampersand_Xml_Element
|
394 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
395 |
+
*/
|
396 |
+
public function setAttribute($name, $value, $namespace = null)
|
397 |
+
{
|
398 |
+
if (!$this->hasAttribute($name)) {
|
399 |
+
$this->appendAttribute($name, $value, $namespace);
|
400 |
+
} else {
|
401 |
+
$namespace = $this->getNamespaceFromCompound($name);
|
402 |
+
$name = Ampersand_Xml::getNameFromCompound($name, false);
|
403 |
+
|
404 |
+
$this->attributes($namespace)->$name = (string) $value;
|
405 |
+
}
|
406 |
+
|
407 |
+
return $this;
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Adds an attribute & value to the end of this element's opening node if it
|
412 |
+
* doesn't already exist
|
413 |
+
*
|
414 |
+
* @param string $name The name of the attribute to set
|
415 |
+
* @param mixed $value The value to set against the attribute
|
416 |
+
* @param string $namespace OPTIONAL If attribute uses a namespace which is
|
417 |
+
* new to this element then it needs to be passed in here
|
418 |
+
* @return Ampersand_Xml_Element
|
419 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
420 |
+
*/
|
421 |
+
public function appendAttribute($name, $value, $namespace = null)
|
422 |
+
{
|
423 |
+
if (!$this->hasAttribute($name)) {
|
424 |
+
$compound = $name;
|
425 |
+
if (!$namespace) {
|
426 |
+
$namespace = $this->getNamespaceFromCompound($compound);
|
427 |
+
}
|
428 |
+
$name = Ampersand_Xml::getNameFromCompound($compound);
|
429 |
+
|
430 |
+
$this->addAttribute($compound, $value, $namespace);
|
431 |
+
}
|
432 |
+
|
433 |
+
return $this;
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* @todo IMPLEMENT ME
|
438 |
+
*/
|
439 |
+
public function prependAttribute($name, $value, $namespace = null)
|
440 |
+
{
|
441 |
+
return $this;
|
442 |
+
}
|
443 |
+
|
444 |
+
/**
|
445 |
+
* Removes an attribute from this element
|
446 |
+
*
|
447 |
+
* @param string $name The name of the attribute to remove
|
448 |
+
* @return Ampersand_Xml_Element
|
449 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
450 |
+
*/
|
451 |
+
public function removeAttribute($name)
|
452 |
+
{
|
453 |
+
if ($this->hasAttribute($name)) {
|
454 |
+
$prefix = Ampersand_Xml::getPrefixFromCompound($name);
|
455 |
+
$name = Ampersand_Xml::getNameFromCompound($name, false);
|
456 |
+
|
457 |
+
unset($this->attributes($prefix, true)->$name);
|
458 |
+
}
|
459 |
+
|
460 |
+
return $this;
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Removes all attributes from this element
|
465 |
+
*
|
466 |
+
* @return Ampersand_Xml_Element
|
467 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
468 |
+
*/
|
469 |
+
public function removeAttributes()
|
470 |
+
{
|
471 |
+
foreach ($this->getAttributes() as $_name => $_value) {
|
472 |
+
$this->removeAttribute($_name);
|
473 |
+
}
|
474 |
+
|
475 |
+
return $this;
|
476 |
+
}
|
477 |
+
|
478 |
+
/**
|
479 |
+
* Checks whether this element has any child elements
|
480 |
+
*
|
481 |
+
* @return bool
|
482 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
483 |
+
*/
|
484 |
+
public function hasChildren($debug = false)
|
485 |
+
{
|
486 |
+
foreach ($this->getNamespaces(true) as $_namespace) {
|
487 |
+
foreach ($this->children($_namespace) as $_child) {
|
488 |
+
return true;
|
489 |
+
}
|
490 |
+
}
|
491 |
+
|
492 |
+
foreach ($this->children() as $_child) {
|
493 |
+
return true;
|
494 |
+
}
|
495 |
+
|
496 |
+
return false;
|
497 |
+
}
|
498 |
+
|
499 |
+
/**
|
500 |
+
* Checks whether this element has a specific child element
|
501 |
+
*
|
502 |
+
* @param $compound
|
503 |
+
* @return bool
|
504 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
505 |
+
*/
|
506 |
+
public function hasChild($compound)
|
507 |
+
{
|
508 |
+
return !is_null($this->getChild($compound));
|
509 |
+
}
|
510 |
+
|
511 |
+
/**
|
512 |
+
* Gets a single child element of this element
|
513 |
+
*
|
514 |
+
* @param string $compound OPTIONAL Target which child to retrieve using a
|
515 |
+
* compound string. If omitted, the first child will be returned
|
516 |
+
* @return mixed
|
517 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
518 |
+
*/
|
519 |
+
public function getChild($compound = null)
|
520 |
+
{
|
521 |
+
if (!$children = $this->getChildren($compound, 1)) {
|
522 |
+
return null;
|
523 |
+
}
|
524 |
+
|
525 |
+
return reset($children);
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* Finds the unique compound for a given child element
|
530 |
+
*
|
531 |
+
* @param mixed $target Element as object or XML string
|
532 |
+
* @return mixed Compound as a string or null if child not found
|
533 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
534 |
+
*/
|
535 |
+
public function getChildCompound($target)
|
536 |
+
{
|
537 |
+
foreach ($this->getChildren() as $_compound => $_child) {
|
538 |
+
if ($_child->equals($target)) {
|
539 |
+
return $_compound;
|
540 |
+
}
|
541 |
+
}
|
542 |
+
|
543 |
+
return null;
|
544 |
+
}
|
545 |
+
|
546 |
+
/**
|
547 |
+
* Gets child elements of this element in correct order
|
548 |
+
*
|
549 |
+
* @param string $compound OPTIONAL Target which children to retrieve using a
|
550 |
+
* compound string. If omitted, all children are retrieved
|
551 |
+
* @param int $limit OPTIONAL The maxiumum number of elements to return
|
552 |
+
* @return array Associative, element compounds as keys, element objects as values
|
553 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
554 |
+
*/
|
555 |
+
public function getChildren($compound = null, $limit = null)
|
556 |
+
{
|
557 |
+
if (!is_null($compound)) {
|
558 |
+
$name = Ampersand_Xml::getNameFromCompound($compound, false);
|
559 |
+
$prefix = Ampersand_Xml::getPrefixFromCompound($compound);
|
560 |
+
$index = Ampersand_Xml::getIndexFromCompound($compound);
|
561 |
+
} else {
|
562 |
+
$name = self::COMPOUND_WILDCARD;
|
563 |
+
$prefix = self::COMPOUND_WILDCARD;
|
564 |
+
$index = self::COMPOUND_WILDCARD;
|
565 |
+
}
|
566 |
+
|
567 |
+
if ($prefix === self::COMPOUND_WILDCARD) {
|
568 |
+
$namespaces = $this->getNamespaces(true);
|
569 |
+
if (array_key_exists('', $namespaces)) {
|
570 |
+
unset($namespaces['']);
|
571 |
+
}
|
572 |
+
if (array_key_exists('xml', $namespaces)) {
|
573 |
+
unset($namespaces['xml']);
|
574 |
+
}
|
575 |
+
|
576 |
+
$prefixes = array_keys($namespaces);
|
577 |
+
|
578 |
+
$prefixes[] = '';
|
579 |
+
} else {
|
580 |
+
// Deliberate array(null) when no prefix specified
|
581 |
+
$prefixes = array($prefix);
|
582 |
+
}
|
583 |
+
|
584 |
+
$children = array();
|
585 |
+
$childCounts = array();
|
586 |
+
if (1 === count($prefixes)) {
|
587 |
+
$_prefix = reset($prefixes);
|
588 |
+
$_children = array();
|
589 |
+
if ($name === self::COMPOUND_WILDCARD) {
|
590 |
+
$_children = $this->children($_prefix, true);
|
591 |
+
} else if ($index === self::COMPOUND_WILDCARD) {
|
592 |
+
$index = 0;
|
593 |
+
while ((!$limit || $index < $limit) && null !== ($_child = $this->children($_prefix, true)->{$name}[$index])) {
|
594 |
+
$_children[] = $_child;
|
595 |
+
$index++;
|
596 |
+
}
|
597 |
+
} else {
|
598 |
+
$_child = $this->children($_prefix, true)->{$name}[(int) $index];
|
599 |
+
if (!is_null($_child)) {
|
600 |
+
$_children[] = $_child;
|
601 |
+
}
|
602 |
+
}
|
603 |
+
|
604 |
+
if (!is_null($_children)) {
|
605 |
+
foreach ($_children as $_node) {
|
606 |
+
$_name = $_node->getName();
|
607 |
+
if (!array_key_exists($_name, $childCounts)) {
|
608 |
+
$childCounts[$_name] = 0;
|
609 |
+
} else {
|
610 |
+
$_name = Ampersand_Xml::buildCompound($_name, null, ++$childCounts[$_name]);
|
611 |
+
}
|
612 |
+
|
613 |
+
$children[$_name] = $_node;
|
614 |
+
|
615 |
+
if ($limit && $limit <= count($children)) {
|
616 |
+
break;
|
617 |
+
}
|
618 |
+
}
|
619 |
+
}
|
620 |
+
} else {
|
621 |
+
$childNodes = array();
|
622 |
+
foreach ($prefixes as $_prefix) {
|
623 |
+
$compound = Ampersand_Xml::buildCompound($name, $_prefix, $index);
|
624 |
+
|
625 |
+
foreach ($this->getChildren($compound, $limit) as $_node) {
|
626 |
+
$_nodeId = $_node->getIdentifier(true);
|
627 |
+
$childNodes[$_nodeId] = $_node;
|
628 |
+
}
|
629 |
+
}
|
630 |
+
|
631 |
+
$string = $this->asXml();
|
632 |
+
if (preg_match_all('/[<\s]' . self::NODE_ID_FIELD . '\s*="(?P<child_ids>\d+)"/', $string, $matches)) {
|
633 |
+
$childIds = $matches['child_ids'];
|
634 |
+
foreach ($childIds as $_childId) {
|
635 |
+
if (!array_key_exists($_childId, $childNodes)) {
|
636 |
+
continue;
|
637 |
+
}
|
638 |
+
|
639 |
+
$_node = $childNodes[$_childId]->removeIdentifier();
|
640 |
+
$_name = $_node->getName();
|
641 |
+
|
642 |
+
if (!array_key_exists($_name, $childCounts)) {
|
643 |
+
$childCounts[$_name] = 0;
|
644 |
+
} else {
|
645 |
+
$_name = Ampersand_Xml::buildCompound($_name, null, ++$childCounts[$_name]);
|
646 |
+
}
|
647 |
+
|
648 |
+
$children[$_name] = $_node;
|
649 |
+
|
650 |
+
if ($limit && $limit <= count($children)) {
|
651 |
+
break;
|
652 |
+
}
|
653 |
+
}
|
654 |
+
}
|
655 |
+
}
|
656 |
+
|
657 |
+
return $children;
|
658 |
+
}
|
659 |
+
|
660 |
+
/**
|
661 |
+
* Appends a new child to the end of this element or inserts a new child after
|
662 |
+
* a specified existing child element
|
663 |
+
*
|
664 |
+
* @param mixed $_source Either instance of element to be appended (in which
|
665 |
+
* case it must be cloned), an element in string form, or just the name of a
|
666 |
+
* new element to append, or an array of any of the above
|
667 |
+
* @param mixed $value OPTIONAL The value of the new element
|
668 |
+
* @param mixed $after OPTIONAL If specified, insert the new child immediately
|
669 |
+
* after the specified child element. Element, XML string, or element name of
|
670 |
+
* the existing child element
|
671 |
+
* @return Ampersand_Xml_Element The new child element
|
672 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
673 |
+
*/
|
674 |
+
public function appendChild($source, $value = null, $after = null)
|
675 |
+
{
|
676 |
+
$child = null;
|
677 |
+
$removedChildren = array();
|
678 |
+
|
679 |
+
if (!is_null($after)) {
|
680 |
+
if (Ampersand_Xml::isValidCompound($after)) {
|
681 |
+
$compound = $after;
|
682 |
+
} else {
|
683 |
+
$compound = $this->getChildCompound($after);
|
684 |
+
}
|
685 |
+
|
686 |
+
if ($this->hasChild($compound)) {
|
687 |
+
// We have to remove the children in reverse order
|
688 |
+
$children = array_reverse($this->getChildren());
|
689 |
+
$matchFound = false;
|
690 |
+
foreach ($children as $_compound => $_child) {
|
691 |
+
if ($compound === $_compound) {
|
692 |
+
$matchFound = true;
|
693 |
+
} else if (!$matchFound) {
|
694 |
+
array_unshift($removedChildren, $this->removeChild($_compound));
|
695 |
+
}
|
696 |
+
}
|
697 |
+
}
|
698 |
+
}
|
699 |
+
|
700 |
+
if (!is_array($source)) {
|
701 |
+
$source = array($source);
|
702 |
+
}
|
703 |
+
|
704 |
+
foreach ($source as $_source) {
|
705 |
+
$_value = $value;
|
706 |
+
|
707 |
+
if (Ampersand_Xml::isValidName($_source)) {
|
708 |
+
$_name = $_source;
|
709 |
+
$_namespace = $this->getNamespace("<$_source/>");
|
710 |
+
} else {
|
711 |
+
if (!is_object($_source)) {
|
712 |
+
$_source = $this->getNewInstance($_source);
|
713 |
+
}
|
714 |
+
|
715 |
+
$_name = $_source->getName();
|
716 |
+
if (is_null($_value)) {
|
717 |
+
$_value = $_source->hasChildren() ? null : Ampersand_Xml::escape($_source);
|
718 |
+
}
|
719 |
+
$_namespace = $_source->getNamespace() ? $_source->getNamespace() : Ampersand_XML::NULL_NAMESPACE;
|
720 |
+
}
|
721 |
+
$child = $this->addChild($_name, $_value, $_namespace);
|
722 |
+
|
723 |
+
$child->extendAttributes($_source, false);
|
724 |
+
|
725 |
+
foreach ($_source->getChildren() as $_sourceChild) {
|
726 |
+
$child->appendChild($_sourceChild);
|
727 |
+
}
|
728 |
+
}
|
729 |
+
|
730 |
+
foreach ($removedChildren as $_child) {
|
731 |
+
$this->appendChild($_child);
|
732 |
+
}
|
733 |
+
|
734 |
+
return $child;
|
735 |
+
}
|
736 |
+
|
737 |
+
/**
|
738 |
+
* @todo IMPLEMENT ME
|
739 |
+
*/
|
740 |
+
public function prependChild($source)
|
741 |
+
{
|
742 |
+
if (!is_object($source)) {
|
743 |
+
$source = $this->getNewInstance($source);
|
744 |
+
}
|
745 |
+
|
746 |
+
return $this;
|
747 |
+
}
|
748 |
+
|
749 |
+
/**
|
750 |
+
* Removes a child element from this element
|
751 |
+
*
|
752 |
+
* @param mixed $target The element to remove; either its compound name (in
|
753 |
+
* which case the first matching child is removed), the target in object form,
|
754 |
+
* or the target as an XML string in which case the first matching child is
|
755 |
+
* removed
|
756 |
+
* @return mixed XML string representation of removed child; null if no child
|
757 |
+
* was removed. Cannot return removed element object as it becomes inaccessible
|
758 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
759 |
+
*/
|
760 |
+
public function removeChild($target)
|
761 |
+
{
|
762 |
+
$matchedChild = null;
|
763 |
+
|
764 |
+
if (Ampersand_Xml::isValidCompound($target)) {
|
765 |
+
// [if] Remove by compound
|
766 |
+
$namespace = $this->getNamespaceFromCompound($target);
|
767 |
+
$name = Ampersand_Xml::getNameFromCompound($target, false);
|
768 |
+
// If no index is provided we default to 0 to avoid removing multiple nodes
|
769 |
+
$index = (int) Ampersand_Xml::getIndexFromCompound($target);
|
770 |
+
|
771 |
+
$matchedChild = $this->children($namespace)->{$name}[$index];
|
772 |
+
if (is_object($matchedChild)) {
|
773 |
+
$matchedChild = $matchedChild->asValidXml();
|
774 |
+
}
|
775 |
+
unset($this->children($namespace)->{$name}[$index]);
|
776 |
+
} else {
|
777 |
+
// [else] Remove by element
|
778 |
+
if ($compound = $this->getChildCompound($target)) {
|
779 |
+
$matchedChild = $this->removeChild($compound);
|
780 |
+
}
|
781 |
+
}
|
782 |
+
|
783 |
+
return $matchedChild;
|
784 |
+
}
|
785 |
+
|
786 |
+
/**
|
787 |
+
* Removes all of the child elements from this element
|
788 |
+
*
|
789 |
+
* @param string $compound OPTIONAL Target which children to remove using a
|
790 |
+
* compound string. If omitted, all children are removed
|
791 |
+
* @return Ampersand_Xml_Element
|
792 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
793 |
+
*/
|
794 |
+
public function removeChildren($compound = null)
|
795 |
+
{
|
796 |
+
$children = array_reverse($this->getChildren($compound));
|
797 |
+
foreach ($children as $_compound => $_child) {
|
798 |
+
$this->removeChild($_compound);
|
799 |
+
}
|
800 |
+
|
801 |
+
return $this;
|
802 |
+
}
|
803 |
+
|
804 |
+
/**
|
805 |
+
* Adds an attribute with a unique value to the XML pointed to by this element.
|
806 |
+
* Can be used to determine whether this element points a certain piece of XML
|
807 |
+
*
|
808 |
+
* @param bool $onlyAddIfNotSet OPTIONAL If true and identifier is already set
|
809 |
+
* then do not update it
|
810 |
+
* @return Ampersand_Xml_Element
|
811 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
812 |
+
*/
|
813 |
+
public function addIdentifier($onlyAddIfNotSet = true)
|
814 |
+
{
|
815 |
+
if (!$onlyAddIfNotSet || !$this->hasAttribute(self::NODE_ID_FIELD)) {
|
816 |
+
$this->appendAttribute(self::NODE_ID_FIELD, self::$_nextNodeId++);
|
817 |
+
}
|
818 |
+
|
819 |
+
return $this;
|
820 |
+
}
|
821 |
+
|
822 |
+
/**
|
823 |
+
* Gets this element's unique identifier. Can be used to determine whether
|
824 |
+
* this element points to a certain piece of XML
|
825 |
+
*
|
826 |
+
* @param bool $addIfNotSet OPTIONAL If true and no identifier is currently set then
|
827 |
+
* add one using addIdentifier()
|
828 |
+
* @return Ampersand_Xml_Element
|
829 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
830 |
+
*/
|
831 |
+
public function getIdentifier($addIfNotSet = false)
|
832 |
+
{
|
833 |
+
if (!($id = $this->getAttribute(self::NODE_ID_FIELD)) && $addIfNotSet) {
|
834 |
+
$this->addIdentifier();
|
835 |
+
$id = $this->getAttribute(self::NODE_ID_FIELD);
|
836 |
+
}
|
837 |
+
|
838 |
+
return $id;
|
839 |
+
}
|
840 |
+
|
841 |
+
/**
|
842 |
+
* Removes this element's unique identifier. Fails gracefully if no identifier
|
843 |
+
* is set
|
844 |
+
*
|
845 |
+
* @return Ampersand_Xml_Element
|
846 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
847 |
+
*/
|
848 |
+
public function removeIdentifier()
|
849 |
+
{
|
850 |
+
return $this->removeAttribute(self::NODE_ID_FIELD);
|
851 |
+
}
|
852 |
+
|
853 |
+
/**
|
854 |
+
* Merges another XML element into this one, including its children, and their
|
855 |
+
* children, etc.
|
856 |
+
*
|
857 |
+
* @param mixed $source The XML element to extend either as an Ampersand_Xml_Element
|
858 |
+
* or an XML string
|
859 |
+
* @param mixed $overwrite OPTIONAL Overwrite existing attributes and values
|
860 |
+
* @return Ampersand_Xml_Element
|
861 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
862 |
+
*/
|
863 |
+
public function extend($source, $overwrite = false)
|
864 |
+
{
|
865 |
+
if (!is_object($source)) {
|
866 |
+
$source = $this->getNewInstance($source);
|
867 |
+
}
|
868 |
+
|
869 |
+
if ($source->hasChildren() && ($this->hasChildren() || $overwrite || !$this->getValue())) {
|
870 |
+
if (!$this->hasChildren()) {
|
871 |
+
$this->unsetValue();
|
872 |
+
}
|
873 |
+
|
874 |
+
foreach ($source->getChildren() as $_compound => $_node) {
|
875 |
+
$_index = Ampersand_Xml::getIndexFromCompound($_compound);
|
876 |
+
if (!$_index && $this->hasChild($_compound)) {
|
877 |
+
$this->getChild($_compound)->extend($_node, $overwrite);
|
878 |
+
} else {
|
879 |
+
$this->appendChild($_node);
|
880 |
+
}
|
881 |
+
}
|
882 |
+
} else if (!$this->hasChildren() && (!$this->getValue() || $overwrite)) {
|
883 |
+
$this->setValue((string) $source);
|
884 |
+
}
|
885 |
+
|
886 |
+
$this->extendAttributes($source, $overwrite);
|
887 |
+
|
888 |
+
return $this;
|
889 |
+
}
|
890 |
+
|
891 |
+
/**
|
892 |
+
* Appends the children and attributes of another element to this element
|
893 |
+
*
|
894 |
+
* @param Ampersand_Xml_Element $source The XML element containing the children
|
895 |
+
* to be appended, either as an Ampersand_Xml_Element or an XML string
|
896 |
+
* @param mixed $after
|
897 |
+
* @return Ampersand_Xml_Element
|
898 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
899 |
+
*/
|
900 |
+
public function append($source, $after = null)
|
901 |
+
{
|
902 |
+
if (!is_object($source)) {
|
903 |
+
$source = $this->getNewInstance($source);
|
904 |
+
}
|
905 |
+
|
906 |
+
if ($source->hasChildren()) {
|
907 |
+
if (!$this->hasChildren()) {
|
908 |
+
$this->unsetValue();
|
909 |
+
}
|
910 |
+
|
911 |
+
$this->appendChild($source->getChildren(), null, $after);
|
912 |
+
} else if (!$this->hasChildren() && !$this->getValue()) {
|
913 |
+
$this->setValue((string) $source);
|
914 |
+
}
|
915 |
+
|
916 |
+
$this->extendAttributes($source, false);
|
917 |
+
|
918 |
+
return $this;
|
919 |
+
}
|
920 |
+
|
921 |
+
/**
|
922 |
+
* Merges the attributes from another XML element into this element
|
923 |
+
*
|
924 |
+
* @param mixed $source The XML element to extend either as an Ampersand_Xml_Element
|
925 |
+
* or an XML string
|
926 |
+
* @param bool $overwrite Overwrite attributes which already exist in this
|
927 |
+
* element
|
928 |
+
* @return Ampersand_Xml_Element
|
929 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
930 |
+
*/
|
931 |
+
public function extendAttributes($source, $overwrite = false)
|
932 |
+
{
|
933 |
+
if (!is_object($source)) {
|
934 |
+
$source = $this->getNewInstance($source);
|
935 |
+
}
|
936 |
+
|
937 |
+
foreach ($source->getAttributes() as $_name => $_value) {
|
938 |
+
if (!$this->hasAttribute($_name) || $overwrite) {
|
939 |
+
$_prefix = Ampersand_Xml::getPrefixFromCompound($_name);
|
940 |
+
if (!$this->hasPrefix($_prefix)) {
|
941 |
+
$_namespace = $source->getNamespaceByPrefix($_prefix);
|
942 |
+
} else {
|
943 |
+
$_namespace = null;
|
944 |
+
}
|
945 |
+
$this->setAttribute($_name, $_value, $_namespace);
|
946 |
+
}
|
947 |
+
}
|
948 |
+
|
949 |
+
return $this;
|
950 |
+
}
|
951 |
+
|
952 |
+
/**
|
953 |
+
* Extracts the prefix part from a compound string and converts it to a namespace
|
954 |
+
*
|
955 |
+
* @param string $compound
|
956 |
+
* @return mixed Namespace as string; null if no prefix is in the compound
|
957 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
958 |
+
*/
|
959 |
+
public function getNamespaceFromCompound($compound)
|
960 |
+
{
|
961 |
+
$namespace = null;
|
962 |
+
|
963 |
+
$prefix = Ampersand_Xml::getPrefixFromCompound($compound);
|
964 |
+
if ($prefix === self::COMPOUND_WILDCARD) {
|
965 |
+
$namespace = $prefix;
|
966 |
+
} else if (!is_null($prefix)) {
|
967 |
+
$namespace = $this->getNamespaceByPrefix($prefix);
|
968 |
+
}
|
969 |
+
|
970 |
+
return $namespace;
|
971 |
+
}
|
972 |
+
|
973 |
+
/**
|
974 |
+
* Returns this element and its children as an array, recursively
|
975 |
+
*
|
976 |
+
* @param bool $isCanonical OPTIONAL Whether to ignore attributes
|
977 |
+
* @return mixed If has children or includes attributes then returns array,
|
978 |
+
* otherwise returns the value of this element
|
979 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
980 |
+
*/
|
981 |
+
protected function _asArray($isCanonical = true)
|
982 |
+
{
|
983 |
+
$result = array();
|
984 |
+
if (!$isCanonical) {
|
985 |
+
// add attributes
|
986 |
+
foreach ($this->getAttributes() as $_name => $_value) {
|
987 |
+
if ($_value) {
|
988 |
+
$result['@'][$_name] = $_value;
|
989 |
+
}
|
990 |
+
}
|
991 |
+
}
|
992 |
+
|
993 |
+
// add children values
|
994 |
+
if ($this->hasChildren()) {
|
995 |
+
foreach ($this->getChildren() as $_element) {
|
996 |
+
$result[$_element->getName()] = $_element->_asArray($isCanonical);
|
997 |
+
}
|
998 |
+
} else if (empty($result)) {
|
999 |
+
// return as string, if nothing was found
|
1000 |
+
$result = $this->getValue();
|
1001 |
+
} else {
|
1002 |
+
// value has zero key element
|
1003 |
+
$result[0] = $this->getValue();
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
return $result;
|
1007 |
+
}
|
1008 |
+
|
1009 |
+
public function asPairs()
|
1010 |
+
{
|
1011 |
+
// add children values
|
1012 |
+
if ($this->hasChildren()) {
|
1013 |
+
$result = new Ampersand_Pairs();
|
1014 |
+
foreach ($this->getChildren() as $_element) {
|
1015 |
+
$result->addPair($_element->getName(), $_element->asPairs());
|
1016 |
+
}
|
1017 |
+
} else {
|
1018 |
+
// return as string, if nothing was found
|
1019 |
+
$result = $this->getValue();
|
1020 |
+
}
|
1021 |
+
|
1022 |
+
return $result;
|
1023 |
+
}
|
1024 |
+
|
1025 |
+
/**
|
1026 |
+
* Searches this element for children which match an xpath expression
|
1027 |
+
*
|
1028 |
+
* @param string $path An xpath expression
|
1029 |
+
* @return array An array of matching elements
|
1030 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1031 |
+
*/
|
1032 |
+
public function xpath($path)
|
1033 |
+
{
|
1034 |
+
if (!$matches = parent::xpath($path)) {
|
1035 |
+
foreach ($this->getNamespaces(true) as $_prefix => $_namespace) {
|
1036 |
+
$this->registerXPathNamespace($_prefix, $_namespace);
|
1037 |
+
}
|
1038 |
+
if ($nullNamespace = $this->getNamespaceByPrefix(null)) {
|
1039 |
+
$this->registerXPathNamespace(self::NULL_PREFIX, $nullNamespace);
|
1040 |
+
}
|
1041 |
+
|
1042 |
+
$path = $this->_filterXpath($path);
|
1043 |
+
$matches = parent::xpath($path);
|
1044 |
+
}
|
1045 |
+
|
1046 |
+
return $matches;
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
/**
|
1050 |
+
* Filters an xpath expression to get around bugs in the SimpleXMLElement class
|
1051 |
+
*
|
1052 |
+
* @param string $path An xpath expression
|
1053 |
+
* @return string The filtered xpath expression
|
1054 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1055 |
+
*/
|
1056 |
+
protected function _filterXpath($path)
|
1057 |
+
{
|
1058 |
+
if ($nullNamespace = $this->getNamespaceByPrefix(null)) {
|
1059 |
+
$path = $this->_addNullPrefixToXpath($path);
|
1060 |
+
}
|
1061 |
+
|
1062 |
+
return $path;
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
/**
|
1066 |
+
* Adds "null prefixes" to element names in an xpath expression. This is
|
1067 |
+
* necessary if the element uses a namespace which has no prefix, otherwise
|
1068 |
+
* the xpath method does not work
|
1069 |
+
*
|
1070 |
+
* @param string $path An xpath expression
|
1071 |
+
* @return string The filtered xpath expression
|
1072 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1073 |
+
*/
|
1074 |
+
protected function _addNullPrefixToXpath($path)
|
1075 |
+
{
|
1076 |
+
$parts = explode('/', $path);
|
1077 |
+
foreach ($parts as $_key => $_part) {
|
1078 |
+
if (!$_part || '.' === $_part{0} || '@' == $_part{0}
|
1079 |
+
|| Ampersand_Xml::getPrefixFromCompound($_part)
|
1080 |
+
) {
|
1081 |
+
continue;
|
1082 |
+
}
|
1083 |
+
|
1084 |
+
$parts[$_key] = Ampersand_Xml::buildCompound($_part, self::NULL_PREFIX);
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
return implode('/', $parts);
|
1088 |
+
}
|
1089 |
+
|
1090 |
+
/**
|
1091 |
+
* Gets a formatted XML string based on this element ignoring any existing
|
1092 |
+
* whitespace
|
1093 |
+
*
|
1094 |
+
* @param int $indentSize OPTIONAL The size of the indentation to use
|
1095 |
+
* @param int $indentChar OPTIONAL The character to use for indentation
|
1096 |
+
* @return string
|
1097 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1098 |
+
*/
|
1099 |
+
public function asFormattedXml($indentSize = 4, $indentChar = ' ')
|
1100 |
+
{
|
1101 |
+
$document = $this->asDomDocument(false);
|
1102 |
+
$document->formatOutput = true;
|
1103 |
+
|
1104 |
+
$xml = $document->saveXML();
|
1105 |
+
|
1106 |
+
$standardIndent = ' ';
|
1107 |
+
$indent = str_repeat($indentChar, $indentSize);
|
1108 |
+
if ($indent !== $standardIndent) {
|
1109 |
+
$lines = explode(PHP_EOL, $xml);
|
1110 |
+
foreach ($lines as $_key => $_line) {
|
1111 |
+
$_trimmed = ltrim($_line);
|
1112 |
+
$_level = (strlen($_line) - strlen($_trimmed)) / strlen($standardIndent);
|
1113 |
+
$lines[$_key] = str_repeat($indent, $_level) . $_trimmed;
|
1114 |
+
}
|
1115 |
+
$xml = implode(PHP_EOL, $lines);
|
1116 |
+
}
|
1117 |
+
|
1118 |
+
return $xml;
|
1119 |
+
}
|
1120 |
+
|
1121 |
+
public function getInnerXml($indentSize = 4, $indentChar = ' ')
|
1122 |
+
{
|
1123 |
+
if ($this->hasChildren()) {
|
1124 |
+
$childXmlStrings = array();
|
1125 |
+
foreach ($this->getChildren() as $_child) {
|
1126 |
+
$_childXmlString = $_child->asFormattedXml($indentSize, $indentChar);
|
1127 |
+
$childXmlStrings[] = Ampersand_Xml::removeDeclaration($_childXmlString);
|
1128 |
+
}
|
1129 |
+
|
1130 |
+
return implode(PHP_EOL, $childXmlStrings);
|
1131 |
+
}
|
1132 |
+
|
1133 |
+
return $this->getValue();
|
1134 |
+
}
|
1135 |
+
|
1136 |
+
public function trimValue()
|
1137 |
+
{
|
1138 |
+
if ($this->hasChildren() || stripos($this->asXml(), '<![cdata[')) {
|
1139 |
+
return $this;
|
1140 |
+
}
|
1141 |
+
|
1142 |
+
$value = $this->getValue();
|
1143 |
+
|
1144 |
+
$value = preg_replace('/^\s*/', '', $value);
|
1145 |
+
$value = preg_replace('/\s*$/', '', $value);
|
1146 |
+
|
1147 |
+
$this->setValue($value);
|
1148 |
+
|
1149 |
+
return $this;
|
1150 |
+
}
|
1151 |
+
|
1152 |
+
/**
|
1153 |
+
* Returns VALID string representation of this element. XML string returned
|
1154 |
+
* by SimpleXMLElement::asXml often does not include namespace declarations
|
1155 |
+
* etc., and therefore such XML cannot always be used to create a new XML
|
1156 |
+
* element object. Unlike asXml, this method should always return valid XML
|
1157 |
+
*
|
1158 |
+
* @return string
|
1159 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1160 |
+
*/
|
1161 |
+
public function asValidXml($xml = null)
|
1162 |
+
{
|
1163 |
+
if (is_null($xml)) {
|
1164 |
+
$xml = $this->asXml();
|
1165 |
+
}
|
1166 |
+
|
1167 |
+
return $this->addNamespacesToXml($xml);
|
1168 |
+
}
|
1169 |
+
|
1170 |
+
/**
|
1171 |
+
* Adds all XML namespace definitions which this object knows about to the root
|
1172 |
+
* node of an XML string
|
1173 |
+
*
|
1174 |
+
* @param string $xml XML string which may be missing namespace definitions
|
1175 |
+
* @return string XML string with all of this element's namespaces defined
|
1176 |
+
* in the root node exactly once
|
1177 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1178 |
+
*/
|
1179 |
+
public function addNamespacesToXml($xml)
|
1180 |
+
{
|
1181 |
+
$namespaces = $this->getNamespaces(true);
|
1182 |
+
foreach ($namespaces as $_prefix => $_namespace) {
|
1183 |
+
if (!$_prefix) {
|
1184 |
+
unset($namespaces[$_prefix]);
|
1185 |
+
}
|
1186 |
+
}
|
1187 |
+
$prefixes = array_flip($namespaces);
|
1188 |
+
|
1189 |
+
$attributes = Ampersand_Xml::getAttributes($xml, 'xmlns');
|
1190 |
+
|
1191 |
+
$matchedPrefixes = array();
|
1192 |
+
if ($attributes) {
|
1193 |
+
foreach ($attributes as $_name => $_value) {
|
1194 |
+
if ($_namespacePrefix = Ampersand_Xml::getNameFromCompound($_name, false)) {
|
1195 |
+
$matchedPrefixes[] = $_namespacePrefix;
|
1196 |
+
}
|
1197 |
+
}
|
1198 |
+
}
|
1199 |
+
|
1200 |
+
/**
|
1201 |
+
* @var array $missing Prefixes used by this element or its children
|
1202 |
+
* which are not defined in the XML string
|
1203 |
+
*/
|
1204 |
+
if ($missing = array_diff($prefixes, $matchedPrefixes)) {
|
1205 |
+
foreach ($missing as $_key => $_prefix) {
|
1206 |
+
$missing[$_key] = "xmlns:$_prefix=\"{$this->getNamespaceByPrefix($_prefix)}\"";
|
1207 |
+
}
|
1208 |
+
$newPrefixes = implode(' ', $missing);
|
1209 |
+
$xml = preg_replace("#^(\s*(?:\<\?xml[^>]+\?>)?\s*<{$this->getName()})#", "$1 $newPrefixes", $xml);
|
1210 |
+
}
|
1211 |
+
|
1212 |
+
return $xml;
|
1213 |
+
}
|
1214 |
+
|
1215 |
+
/**
|
1216 |
+
* Gets a DOMDocument instance based on this element
|
1217 |
+
*
|
1218 |
+
* @param bool $preserveWhiteSpace OPTIONAL Whether or not to preserve
|
1219 |
+
* any irrelevant whitespace which appears within this element
|
1220 |
+
* @return DOMDocument
|
1221 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1222 |
+
*/
|
1223 |
+
public function asDomDocument($preserveWhiteSpace = false)
|
1224 |
+
{
|
1225 |
+
$document = new DOMDocument();
|
1226 |
+
$document->preserveWhiteSpace = $preserveWhiteSpace;
|
1227 |
+
@$document->loadXML($this->asValidXml());
|
1228 |
+
if (!$document->encoding) {
|
1229 |
+
$document->encoding = 'UTF-8';
|
1230 |
+
}
|
1231 |
+
|
1232 |
+
return $document;
|
1233 |
+
}
|
1234 |
+
|
1235 |
+
/**
|
1236 |
+
* Creates and returns a new instance of the current class based on the
|
1237 |
+
* provided XML element
|
1238 |
+
*
|
1239 |
+
* @param mixed $source The XML element to base the new object on, either as
|
1240 |
+
* an XML string, an XML object or the path to a file containing an XML string
|
1241 |
+
* @param bool $isFilePath Is $source a file path
|
1242 |
+
* @return Ampersand_Xml_Element
|
1243 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
1244 |
+
*/
|
1245 |
+
public function getNewInstance($source, $isFilePath = false)
|
1246 |
+
{
|
1247 |
+
$class = get_class($this);
|
1248 |
+
|
1249 |
+
if (is_object($source)) {
|
1250 |
+
$source = $source->asValidXml();
|
1251 |
+
}
|
1252 |
+
|
1253 |
+
return Ampersand_Xml::factory($source, $isFilePath, $class);
|
1254 |
+
}
|
1255 |
+
|
1256 |
+
public function copy($name = null)
|
1257 |
+
{
|
1258 |
+
$xml = $this->asFormattedXml();
|
1259 |
+
|
1260 |
+
if ($name) {
|
1261 |
+
$xml = preg_replace("#^(\s*(?:\<\?xml[^>]+\?>)?\s*<){$this->getName()}#", "$1{$name}", $xml);
|
1262 |
+
$xml = preg_replace("#</{$this->getName()}(\s*>\s*)$#", "</{$name}$1", $xml);
|
1263 |
+
}
|
1264 |
+
|
1265 |
+
return $this->getNewInstance($xml);
|
1266 |
+
}
|
1267 |
+
}
|
lib/Ampersand/Xml/Resource.php
CHANGED
@@ -1,62 +1,130 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Ampersand IT Library
|
4 |
+
*
|
5 |
+
* @category Ampersand_Library
|
6 |
+
* @package Ampersand_Xml
|
7 |
+
* @copyright Copyright (c) 2008-2011 Ampersand IT (UK) Ltd. (http://www.ampersandit.co.uk)
|
8 |
+
* @license TBC
|
9 |
+
*/
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @category Ampersand_Library
|
13 |
+
* @package Ampersand_Xml
|
14 |
+
* @author Josh Di Fabio <josh.difabio@ampersandit.co.uk>
|
15 |
+
*/
|
16 |
+
class Ampersand_Xml_Resource
|
17 |
+
{
|
18 |
+
const ATTRIBUTE = 'resource_id';
|
19 |
+
|
20 |
+
protected static $_registry = array();
|
21 |
+
protected static $_nextId = 0;
|
22 |
+
|
23 |
+
protected $_id;
|
24 |
+
protected $_value;
|
25 |
+
|
26 |
+
public static function factory($value, Ampersand_Xml_Element $element)
|
27 |
+
{
|
28 |
+
$resource = self::_getNewResourceInstance();
|
29 |
+
|
30 |
+
$resourceId = self::$_nextId++;
|
31 |
+
self::$_registry[$resourceId] = $resource;
|
32 |
+
|
33 |
+
$resource->setId($resourceId)
|
34 |
+
->setValue($value)
|
35 |
+
->assignToElement($element)
|
36 |
+
;
|
37 |
+
|
38 |
+
return $resource;
|
39 |
+
}
|
40 |
+
|
41 |
+
public static function reset()
|
42 |
+
{
|
43 |
+
self::$_registry = array();
|
44 |
+
self::$_nextId = 0;
|
45 |
+
}
|
46 |
+
|
47 |
+
protected static function _getNewResourceInstance()
|
48 |
+
{
|
49 |
+
return new Ampersand_Xml_Resource();
|
50 |
+
}
|
51 |
+
|
52 |
+
public function getId()
|
53 |
+
{
|
54 |
+
return $this->_id;
|
55 |
+
}
|
56 |
+
|
57 |
+
public function setId($id)
|
58 |
+
{
|
59 |
+
$this->_id = $id;
|
60 |
+
|
61 |
+
return $this;
|
62 |
+
}
|
63 |
+
|
64 |
+
public function getValue()
|
65 |
+
{
|
66 |
+
return $this->_value;
|
67 |
+
}
|
68 |
+
|
69 |
+
public function setValue($value)
|
70 |
+
{
|
71 |
+
$this->_value = $value;
|
72 |
+
|
73 |
+
return $this;
|
74 |
+
}
|
75 |
+
|
76 |
+
public static function clearElement(Ampersand_Xml_Element $element)
|
77 |
+
{
|
78 |
+
$element->removeAttribute(self::ATTRIBUTE);
|
79 |
+
}
|
80 |
+
|
81 |
+
public function assignToElement(Ampersand_Xml_Element $element)
|
82 |
+
{
|
83 |
+
$element->unsetValue()
|
84 |
+
->setAttribute(self::ATTRIBUTE, $this->getId())
|
85 |
+
;
|
86 |
+
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
|
90 |
+
public static function elementHasResource($element)
|
91 |
+
{
|
92 |
+
return !is_null(self::getElementResourceId($element));
|
93 |
+
}
|
94 |
+
|
95 |
+
public static function getResource($id)
|
96 |
+
{
|
97 |
+
if (array_key_exists($id, self::$_registry)) {
|
98 |
+
return self::$_registry[$id];
|
99 |
+
}
|
100 |
+
|
101 |
+
return null;
|
102 |
+
}
|
103 |
+
|
104 |
+
public static function getElementResourceId($element)
|
105 |
+
{
|
106 |
+
if (!is_object($element)) {
|
107 |
+
$render = Ampersand_Xml::factory($element);
|
108 |
+
}
|
109 |
+
|
110 |
+
return $element->getAttribute(self::ATTRIBUTE);
|
111 |
+
}
|
112 |
+
|
113 |
+
public static function getElementResource($element)
|
114 |
+
{
|
115 |
+
if (!self::elementHasResource($element)) {
|
116 |
+
return null;
|
117 |
+
}
|
118 |
+
|
119 |
+
return self::getResource(self::getElementResourceId($element));
|
120 |
+
}
|
121 |
+
|
122 |
+
public static function getElementValue($element)
|
123 |
+
{
|
124 |
+
if (!$resource = self::getElementResource($element)) {
|
125 |
+
return null;
|
126 |
+
}
|
127 |
+
|
128 |
+
return $resource->getValue();
|
129 |
+
}
|
130 |
+
}
|
package.xml
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Ampersand_Core</name>
|
4 |
-
<version>0.2.
|
5 |
<stability>stable</stability>
|
6 |
-
<license uri="http://www.
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
-
<summary>Ampersand
|
10 |
-
<description
|
11 |
-
<notes>
|
12 |
-
<authors><author><name>
|
13 |
-
<date>
|
14 |
-
<time>
|
15 |
-
<contents><target name="magecore"><dir name="Ampersand"><dir name="Adminhtml"><dir name="Block"><dir name="System"><dir name="Config"><dir name="Element"><dir name="ProductImage"><file name="Attribute.php" hash="2dab6e0a0cba8d14e02f7bfccab603c0"/><file name="Select.php" hash="c0ce54d53b1d800c37de5a421087f601"/><file name="UseFrame.php" hash="dfb16c3fd9eea7adc2191d14a8249a54"/></dir></dir><dir name="Renderer"><file name="ArrayAbstract.php" hash="2bb99de581bdd2001a6c300cf2de211a"/><file name="ProductImage.php" hash="e584aa740a6662ad3a1f0bd006f9797c"/><file name="ProductImages.php" hash="d22cde5c5af1f7e36aff8a128b5359bc"/></dir></dir></dir></dir><dir name="Controller"><file name="Action.php" hash="e203163a85be4b5386ea8bd4f2799b36"/></dir><dir name="Helper"><file name="Data.php" hash="f7523c60b2759c1ced481064202771d7"/><file name="Image.php" hash="e4268e0e7c7f7d78169df333da6d92b9"/></dir><dir name="Model"><file name="Observer.php" hash="38826df74cc74039bff1db129883cde8"/><dir name="System"><dir name="Config"><dir name="Backend"><file name="Obscure.php" hash="ade7b393da8b92e1369a7ccc8dd67983"/></dir><dir name="Source"><file name="ProductAttributes.php" hash="e4ec32b21bbe8101d9f6059ae0a5798c"/><file name="ProductImageAttributes.php" hash="0ee84c842d35fbb885e791adcf8a5ebc"/><file name="Store.php" hash="b226d9837382489e773ed2deecf67e75"/></dir></dir></dir></dir><dir name="etc"><file name="config.xml" hash="8c3b48f12762a90434bc05c77179b6ce"/></dir></dir><dir name="Catalog"><dir name="Model"><file name="Category.php" hash="15ccfff66c3567865b7cd9c262d6a166"/><file name="Product.php" hash="316ada27f33d272c6dac30b94337efbb"/><dir name="Resource"><dir name="Eav"><dir name="Mysql4"><dir name="Category"><file name="Collection.php" hash="d1758c5cdfa91259940ef3d4edca7267"/></dir><file name="Category.php" hash="af3cf2fd975154c4c815cb2f980e05b4"/><dir name="Product"><file name="Collection.php" hash="d01b24c6b65c78609c6fd62b0b0fbb8d"/></dir><file name="Product.php" hash="a2f2ce1054f8e4dd9c7b5cd321fc43ee"/></dir></dir></dir></dir></dir><dir name="Core"><dir name="Block"><file name="Abstract.php" hash="6ec92f8410d9f6030aff9f48023eee2f"/><file name="Template.php" hash="77993aa2bf12cb82d3db33ab126104c6"/></dir><dir name="Controller"><dir name="Front"><file name="Action.php" hash="ebea27fc191182fd3b44b88f218d954c"/></dir></dir><file name="Exception.php" hash="f8b5c4240baee933cff1ee7a0527b18a"/><dir name="Helper"><file name="Abstract.php" hash="d847e9ec1e4ebf47850aa52ea4400e67"/><file name="Data.php" hash="7bba39857edc0903e224c84695e21b44"/></dir><dir name="Model"><file name="Abstract.php" hash="534eca258075364b01df20197625f108"/><dir name="Mysql4"><file name="Abstract.php" hash="663e5c55ee4e7a749690b7b37b9f32e9"/><dir name="Collection"><file name="Abstract.php" hash="3cfb93c9611a8067a15ab468776b959a"/></dir></dir></dir><file name="changelog.txt" hash="6ee58d3bcfdf0a35f7c55a5221ce013f"/><dir name="etc"><file name="config.xml" hash="33420ee1f8602000ca89039679e80a8d"/><file name="system.xml" hash="5fd3e24923ca0f55f2e5c379426fc9df"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Ampersand_Core.xml" hash="1716748a50b43c1a755c5425c8f14a4f"/></dir></target><target name="magelib"><dir name="Ampersand"><dir name="Db"><dir name="Test"><file name="Abstract.php" hash="24433637b46a102b2a0bb0c07858cb74"/><file name="Adapter.php" hash="5325d1003f0f91b087232a20d31dd259"/><file name="Config.php" hash="85064b76808f75a2d6585fc380b4e231"/><file name="Connection.php" hash="4b3979bcca85c17d068d9841abd9d7e2"/><file name="Exception.php" hash="e8d5fee91a5e62a7e0570b7c294893b2"/><file name="MageResource.php" hash="7013d601f29a696d5df1d63181710534"/><dir name="Output"><file name="Abstract.php" hash="4d50877830c9786ec12452c09309aae5"/><file name="Statement.php" hash="b4e0ec97c9191161d63a21df9db26b90"/><file name="This.php" hash="1847e72d84cd835e3ec131a0c8429aa0"/></dir><file name="Statement.php" hash="f57b52947ba9cbea407898e5e8ff5920"/></dir></dir><dir name="Filter"><file name="Compress.php" hash="99b3ece329f7a5541b36a601716405b9"/><dir name="Zend"><dir name="Filter"><dir name="Compress"><file name="Bz2.php" hash="ce9c58f20d869d985a66036d47fb69a7"/><file name="CompressAbstract.php" hash="8862e9a0eb57736255b37790a8c355a8"/><file name="CompressInterface.php" hash="fb3f1bb646e81aa6845ff116fbaf410d"/><file name="Gz.php" hash="072580001b6332d33f39be73a61f3700"/><file name="Lzf.php" hash="86f8b40dc4db21ef71801136133c51a8"/><file name="Rar.php" hash="0a2a564efb52d2feb40b7605a66bea5a"/><file name="Tar.php" hash="2b63dfe7082d320f37ea6486ea1bdbfa"/><file name="Zip.php" hash="50567f6f791bc5edb9fadb68a749d4d8"/></dir><file name="Compress.php" hash="644020a0b4e37649698e17fa3440b6be"/></dir></dir></dir><dir name="License"><file name="Helper.php" hash="2d6c17b8ece6ecb15252907d5cc91b14"/><file name="Remote.php" hash="ecf9e020fea4dd22839793d38781320c"/><file name="ResourceRegistry.php" hash="baad47ba81b7e558e6ee561371896f1b"/></dir><dir name="Registry"><file name="Abstract.php" hash="f0834d8ca1f668b21a456ac037181b83"/><file name="Container.php" hash="b3f3d4a4f6b12c717eced86481ab2b33"/></dir><dir name="Xml"><file name="Config.php" hash="8dd90ba4d276d0d9a0932ae48214cafc"/><file name="Element.php" hash="9d33f82bd0b5c20ef6c9233018a1aa20"/><file name="Resource.php" hash="8d8c8375875659bf02abd1d08fa08fe0"/></dir><file name="ClassProvider.php" hash="4d6f2e35a2b74d6123fb5a8c7b78b1f2"/><file name="Exception.php" hash="8ed589615e194dd560c22ed3d0c75860"/><file name="License.php" hash="66844554233992fb58784c88e362eebf"/><file name="Object.php" hash="b77d3edaf66c337a741c681b5fa4d183"/><file name="Pairs.php" hash="c53e1dd5fb47f1ebc93ef58f561d4c6e"/><file name="Registry.php" hash="a4a10cb6d6bb2384e85812057b9742d3"/><file name="Xml.php" hash="f665195fb3dd786e2c4c0696ae6f2d04"/></dir><dir name="."><file name="Ampersand.php" hash="fb38a0bafedd9364ee5505af928979de"/></dir></target></contents>
|
16 |
<compatible/>
|
17 |
<dependencies><required><php><min>5.0.0</min><max>5.9.9</max></php><extension><name>ionCube Loader</name><min></min><max></max></extension></required></dependencies>
|
18 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Ampersand_Core</name>
|
4 |
+
<version>0.2.6</version>
|
5 |
<stability>stable</stability>
|
6 |
+
<license uri="http://www.opensource.org/licenses/gpl-license.php">GNU General Public License (GPL)</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
+
<summary>Ampersand Core utility modules from Ampersand Commerce.</summary>
|
10 |
+
<description></description>
|
11 |
+
<notes>Ampersand_Core v0.2.6</notes>
|
12 |
+
<authors><author><name>AmpersandHQ</name><user>AmpersandHQ</user><email>magento@ampersandcommerce.com</email></author></authors>
|
13 |
+
<date>2013-01-11</date>
|
14 |
+
<time>11:09:09</time>
|
15 |
+
<contents><target name="magecore"><dir name="Ampersand"><dir name="PageCache"><dir name="Model"><dir name="Container"><file name="NoCache.php" hash="2e362a9b44dbe1463c66dbe4e8d2c030"/></dir></dir></dir><dir name="Core"><file name="changelog.txt" hash="0c38aee788c7bf07e95f74dd1d8edfcf"/><dir name="Controller"><dir name="Front"><file name="Action.php" hash="ebea27fc191182fd3b44b88f218d954c"/></dir></dir><dir name="Block"><file name="Template.php" hash="77993aa2bf12cb82d3db33ab126104c6"/><file name="Abstract.php" hash="6ec92f8410d9f6030aff9f48023eee2f"/></dir><dir name="etc"><file name="config.xml" hash="e2133171fad1081e13bd4b53c9ae8024"/><file name="system.xml" hash="5fd3e24923ca0f55f2e5c379426fc9df"/></dir><dir name="sql"><dir name="ampersand_core_setup"><file name="mysql4-install-0.2.3.php" hash="728c0f3226af4607fbb60bd249e0b9c8"/></dir></dir><file name="Exception.php" hash="f8b5c4240baee933cff1ee7a0527b18a"/><dir name="Helper"><file name="Validate.php" hash="e3d0a27fe853605e0549a4695ca9bf94"/><file name="File.php" hash="b1d09cacd28f488b1aae49adc253c36d"/><file name="Data.php" hash="82153d9383eb4ba127452b3f6d48fe43"/><file name="Abstract.php" hash="d847e9ec1e4ebf47850aa52ea4400e67"/></dir><dir name="Model"><file name="Versioning.php" hash="74d2c447705d507dbef7a0b009b469d8"/><dir name="Resource"><file name="Setup.php" hash="dc4c53baaaddd504e96896ca6974f121"/></dir><dir name="Mysql4"><dir name="Collection"><file name="Abstract.php" hash="14ebf27f20dcd908b432beefa99b0e0f"/></dir><file name="Value.php" hash="1808d4a8609de1d0fcbcc337f6d55f30"/><file name="Collection.php" hash="fdeac9e9bd3938328ccf8364d45fbabd"/><file name="Abstract.php" hash="dde9ffff5a69fc7504c1cdaeb6f39df0"/></dir><file name="Value.php" hash="a3040b655f095d15e5c8cdc318fef042"/><file name="SessionObject.php" hash="8f7621b1fe0dfc80e4ac0a5332f94909"/><file name="Abstract.php" hash="534eca258075364b01df20197625f108"/></dir></dir><dir name="Catalog"><dir name="etc"><file name="config.xml" hash="42d0d3364841416eab5c691866c829d3"/></dir><dir name="Helper"><file name="Category.php" hash="739b67b43672b419e134b46625c00825"/><dir name="Product"><file name="Attribute.php" hash="42c27c01325d349061a3030d694e5f7f"/></dir><file name="Product.php" hash="7b8d38ab4bd24ec6bf224b2edbc77d3d"/></dir><dir name="Model"><file name="Category.php" hash="15ccfff66c3567865b7cd9c262d6a166"/><dir name="Resource"><dir name="Eav"><dir name="Mysql4"><dir name="Category"><file name="Collection.php" hash="d1758c5cdfa91259940ef3d4edca7267"/></dir><file name="Category.php" hash="af3cf2fd975154c4c815cb2f980e05b4"/><dir name="Product"><file name="Collection.php" hash="d01b24c6b65c78609c6fd62b0b0fbb8d"/></dir><file name="Product.php" hash="a2f2ce1054f8e4dd9c7b5cd321fc43ee"/></dir></dir></dir><file name="Product.php" hash="316ada27f33d272c6dac30b94337efbb"/></dir></dir><dir name="Sales"><dir name="etc"><file name="config.xml" hash="43e811b7123975725f9a385a32c5eb07"/></dir><dir name="Helper"><file name="Quote.php" hash="fd5ea2e85f7ca2bb3db1e203afb6d330"/></dir><dir name="Model"><file name="AbstractHelper.php" hash="dc35407a867e2020302ad17a49115fba"/><file name="InvoiceHelper.php" hash="bcd6e4d716d743ab7620da275b506e0c"/><dir name="Quote"><dir name="Address"><dir name="Total"><dir name="Discount"><file name="PercentageAbstract.php" hash="867e5dc48eb85ebe917dcea780620663"/></dir></dir></dir></dir><file name="OrderHelper.php" hash="249042752368cb7a5a57ef8a33b16b6b"/></dir></dir><dir name="System"><dir name="etc"><file name="config.xml" hash="f7e6e2bc50cfa47fb59a31873a727ab6"/></dir><dir name="Helper"><file name="Store.php" hash="ea2f5b798ed7487b498831405a226dc4"/><file name="Data.php" hash="3d986a1f1448396feac866e13d27ed4f"/></dir><dir name="Model"><file name="Website.php" hash="c75a8f597098cd73b58d6d6b40bfece1"/><file name="Store.php" hash="82dd90ac575adc401362ce0e1a4ee301"/><file name="Category.php" hash="d89f44b84bc6c88c68834f53c06f9ca5"/><file name="Images.php" hash="11e987c56050ddf4d74ca3165c9d72a6"/><dir name="Cms"><file name="Block.php" hash="45bf767d62b524f0ace1bbe4fdb4eba6"/><file name="Page.php" hash="15a6e2696fd022ab63262d5102d5be0a"/></dir><file name="TaxRate.php" hash="57309afbec8af006c03faa3007f3ab7d"/><file name="TaxRule.php" hash="65c5a11b1557a9fe4b2b07f5d19df402"/><file name="Index.php" hash="7bfb2de6d1904b34c2d3dd6d52337651"/><file name="Shipping.php" hash="1efd37bff53fcf7812e23e621def3be8"/><file name="Cache.php" hash="3f80ac9b1dd39127937d7ffaf7d2a319"/><file name="Group.php" hash="43d3bcecc45ef10d41d81f2d0333dede"/><file name="Config.php" hash="c9fb4938b44c9ec717f9ab162673660d"/></dir></dir><dir name="Adminhtml"><dir name="Controller"><file name="Action.php" hash="e203163a85be4b5386ea8bd4f2799b36"/></dir><dir name="Block"><dir name="Catalog"><dir name="Form"><dir name="Renderer"><dir name="Fieldset"><file name="ConfigurableElement.php" hash="bcbcb1986ea9611ea8d818f64d8ff002"/></dir></dir></dir></dir><dir name="System"><dir name="Config"><dir name="Renderer"><file name="Datetime.php" hash="b57e9d783265055c9f8e8a53428364bf"/><file name="ArrayAbstract.php" hash="2599c679edaee2ddea8d6a1732a40dc2"/><file name="ProductImage.php" hash="e584aa740a6662ad3a1f0bd006f9797c"/><file name="Hidden.php" hash="837e88d6fd53d4e506f3d149af3ccf04"/><file name="ProductImages.php" hash="d22cde5c5af1f7e36aff8a128b5359bc"/></dir><dir name="Element"><dir name="ProductImage"><file name="UseFrame.php" hash="dfb16c3fd9eea7adc2191d14a8249a54"/><file name="Select.php" hash="c0ce54d53b1d800c37de5a421087f601"/><file name="Attribute.php" hash="2dab6e0a0cba8d14e02f7bfccab603c0"/></dir></dir></dir></dir><dir name="Widget"><file name="Container.php" hash="b871abec7d43d672caae8c5edb2372da"/><file name="Grid.php" hash="1240d75d734dfb85e6615ca6a497b407"/></dir></dir><dir name="etc"><file name="config.xml" hash="171a1de8fc6246792e8ed4a1bb1e100f"/></dir><dir name="sql"><dir name="ampersand_adminhtml_setup"><file name="mysql4-upgrade-0.0.2-0.0.3.php" hash="5175143c30b8163ea4aabcb37e4f5e1b"/><file name="mysql4-install-0.0.2.php" hash="1a30128362cccea38b4c371529ffc5b1"/></dir></dir><dir name="Helper"><file name="Image.php" hash="e4268e0e7c7f7d78169df333da6d92b9"/><file name="Data.php" hash="f9df723b613ffb06cca056f314cec96a"/></dir><dir name="Model"><dir name="Mysql4"><dir name="Search"><dir name="Item"><file name="Collection.php" hash="29af1359b4779b7ff09bff1dec16cb5d"/></dir><file name="Item.php" hash="cffc39a2182b651030863f40c7a8b1a7"/></dir><file name="Search.php" hash="51d7e49c07a07d7f019a5593a0b0fd11"/></dir><dir name="Search"><file name="Item.php" hash="60310c3f6574dad4ea10f4d4363132d5"/></dir><dir name="System"><dir name="Config"><dir name="Backend"><file name="Obscure.php" hash="ade7b393da8b92e1369a7ccc8dd67983"/><file name="Void.php" hash="405f742229d9732435d19bf8b61c3cc2"/></dir><dir name="Source"><file name="Website.php" hash="db2e03bbe9e7e78fde491958b2c39fd6"/><file name="Store.php" hash="b226d9837382489e773ed2deecf67e75"/><file name="Category.php" hash="9c7b6e60c00f7aaed07c7a2c7ac08ca2"/><file name="ProductSimpleTypes.php" hash="bda966586271e24df9fa027f8921e896"/><file name="ProductAttributeSets.php" hash="ef697041ca85b3249883e2be450f642a"/><file name="ProductImageAttributes.php" hash="0ee84c842d35fbb885e791adcf8a5ebc"/><file name="Stock.php" hash="ea2cc7c1ff99c7f3553d9859e05e8868"/><file name="ProductAttributes.php" hash="a44f7fc196cec765c6b00d27b35c419f"/></dir></dir></dir><file name="Observer.php" hash="e38c12a45f6347e4dedb40985abc5f1b"/><dir name="Entity"><dir name="Attribute"><dir name="Frontend"><file name="ConfigurableInterface.php" hash="5ee5bd4444227568332d17a66fc63845"/><file name="Configurable.php" hash="63eca3c39ec80395fb802a8a936fcd0a"/></dir></dir></dir><file name="Search.php" hash="f694f7bcdb058c2a04216daf07d75ed7"/></dir></dir><dir name="Api"><dir name="etc"><file name="config.xml" hash="a333e811f6e854549634b1d92d7e50c3"/><file name="api.xml" hash="cc0f9c530796eb4188a053189d4894eb"/></dir><dir name="Helper"><file name="Data.php" hash="f396ad17327dbf3e28c698d550489d4f"/></dir><dir name="Model"><dir name="Catalog"><file name="Category.php" hash="6f7cee37b06d2a1ac0750c5ed30d2acb"/><dir name="Product"><file name="Attribute.php" hash="85dbf6eb56d41b183d1b0141f01fe059"/></dir><file name="Product.php" hash="0dfd6aeadfe9c18bb2c53028a66c64a3"/></dir><dir name="Sales"><file name="Order.php" hash="d67d8026afd03c2f6320da74e05317e9"/><dir name="Order"><file name="Invoice.php" hash="98074b87686d9a4949c09e33b15e0b58"/><file name="Creditmemo.php" hash="338eaed9e812d29c0617230859c5d635"/><file name="Shipment.php" hash="aeff4bf86605bceba718cc592204a9d6"/></dir><file name="Quote.php" hash="2069e69c9ab3f8dcf1ee0b7de0dc88ee"/></dir><file name="Review.php" hash="abc25b80927556705fea1ef2aa5d1f0c"/><file name="Rating.php" hash="be741ba7130723414cd7d633427a55cb"/><dir name="Customer"><file name="Address.php" hash="0bef9d0e563d05a07f14d589f4074e8f"/></dir></dir></dir><dir name="Fakepay"><dir name="etc"><file name="config.xml" hash="899a1c4abb423e03c1d19baf43543eab"/><file name="system.xml" hash="e860a2ee9cbeb4934074a420445dee7a"/></dir><dir name="Helper"><file name="Data.php" hash="992ee7efc3df32d4e73c1eaa34b90ff8"/></dir><dir name="Model"><file name="Method.php" hash="cc31f4f2dae2748baffcb4e1f2dbf51d"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="base"><dir name="default"><dir name="template"><dir name="ampersand_adminhtml"><dir name="catalog"><dir name="form"><dir name="renderer"><dir name="element"><file name="use-config.phtml" hash="00f90df2f8caf3e505fb99fd10647491"/></dir></dir></dir></dir><dir name="system"><file name="config-form-array-simple.phtml" hash="fe217f999335888554b54991e3efc387"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Ampersand_Core.xml" hash="732f9f1753f6e89344adde4022546327"/></dir></target><target name="magelib"><dir name="Ampersand"><file name="Deprecate.php" hash="f0eec19747051786ebdaef8ca6c9fc86"/><dir name="Db"><dir name="Test"><dir name="Output"><file name="Statement.php" hash="ea27bf2fde3c602d565dcd8c539fef5a"/><file name="This.php" hash="a04e8a19738e372b6d0732faad88d052"/><file name="Abstract.php" hash="565f7dbbc1bdd669c02e0838aef8edb2"/></dir><file name="Statement.php" hash="e49272a924c2ef3ab953c1afe333a439"/><file name="Connection.php" hash="10f8977efe5fa719649d672ed5dd5894"/><file name="Exception.php" hash="f569111f4ad4a3b4c1902a1c6c8e5789"/><file name="MageResource.php" hash="cae564fee4ed40227feb469434a63987"/><file name="Adapter.php" hash="8ddb05a2e883fc66eb25848adbe7c597"/><file name="Abstract.php" hash="f2af933c57e5f000ed44ed5332d56e52"/><file name="Config.php" hash="5f5351860b215d612e84d255c142ae76"/></dir></dir><file name="Pairs.php" hash="b9c020f86c8779fb8290b2b262d7cfc5"/><file name="ClassProvider.php" hash="a3c1314f404f4ee5d75b10effead60be"/><dir name="Xml"><file name="Resource.php" hash="ca65ea349912ad9984cb5f91606e5d0f"/><file name="Element.php" hash="7eba4a26d2f7df67f6e4904df4dc06a7"/><file name="Config.php" hash="d54fe61d42e55bfb955d52cde5ccf7bf"/></dir><dir name="Deprecate"><file name="Registry.php" hash="e83880e302d3d824a6c6cd714a8dd742"/></dir><file name="Stack.php" hash="44ac4a1ae0caaef0583fee8bd8b0be8f"/><file name="BinPack.php" hash="333e7739e091502660471825c7fe9dea"/><dir name="Registry"><file name="Container.php" hash="b0e97248ecb3faf82abc785f67771607"/><file name="Abstract.php" hash="a27260429ecd9cc83c75bca8e621289f"/><file name="Interface.php" hash="710949b40aea5985e87309009c4f779d"/></dir><dir name="License"><file name="Remote.php" hash="c3c33291c08edf1e30ec75409e15b2a4"/><file name="ResourceRegistry.php" hash="082d084b2292aaf4954d98966257139b"/><file name="Helper.php" hash="949644ffb11e313e584125a5371762c6"/></dir><file name="Xml.php" hash="4c9d45f2c752e41e129488c9d449475e"/><dir name="BinPack"><file name="Input.php" hash="d4ba8645476b69385527b9fcfd8038ea"/><file name="Bin.php" hash="aa595d8064ca781e835231dffd06a6c3"/><file name="Output.php" hash="dba6a181c670eeddafe2a5789611bb3a"/><file name="ItemDimension.php" hash="c3dd50ec2156d5b85ab849f44ca7a3e7"/><dir name="Packer"><file name="PackerInterface.php" hash="e111e9835a3bc675def8bbcc1b6b0e36"/><file name="PackerAbstract.php" hash="5138430a4f3faa74c351e6a9fde46d75"/><file name="FirstFit.php" hash="f636b07f17c1ab0f29273008955c4d7b"/><file name="JoshBestFit.php" hash="9fe0cdcd3919919406044162251242bb"/></dir><file name="State.php" hash="aa3fedaa223e2dd98e620b6ebd7911c1"/><dir name="Dimension"><file name="DimensionInterface.php" hash="62abd36d3c20d305007a19fd4ca1ce2f"/><file name="Standard.php" hash="019269abc804d45372ec84ca0ddf56a2"/></dir><file name="BinDimension.php" hash="c3874b969e4664d23d492358f52530d5"/><file name="Item.php" hash="ba720287934418327b84f1106c9dd7d4"/></dir><file name="Exception.php" hash="7e17531cf2b8dccac7e3513e0925e090"/><file name="Random.php" hash="bc14e6bf174deb87f50b11c84a816c8c"/><file name="License.php" hash="3828a1f32c0e3589285f6c8843c8aafa"/><file name="Registry.php" hash="f2a25033b95fa5cded92ffeed990596f"/><dir name="Filter"><file name="Compress.php" hash="18ce69a8994c53cef250613fa0fc395e"/><dir name="Zend"><dir name="Filter"><dir name="Compress"><file name="CompressInterface.php" hash="57dc11590120af393023a57c108b9712"/><file name="Zip.php" hash="f1a35886800405c54ea885653b66c20e"/><file name="Gz.php" hash="c6ede5a52ac849420b88358455fb11fc"/><file name="Tar.php" hash="4a2486ab475ed057b8c4835d98ee4dd1"/><file name="Lzf.php" hash="51ff8b8b26038764ca225f4d1ec844b7"/><file name="Rar.php" hash="e00605b4b10575734a75d06ea7ca26b8"/><file name="Bz2.php" hash="833babb46fba465754d150ab5ea0af05"/><file name="CompressAbstract.php" hash="5711d16d446723349f699108e2459017"/></dir><file name="Compress.php" hash="7ff4808a714d40da3a41ab81c5077ad7"/></dir></dir></dir><file name="Object.php" hash="f14635be05b02da9e48bc5fc10247373"/></dir><dir name="."><file name="Ampersand.php" hash="6108375c69ce2ed54565b6171f7a313b"/></dir></target></contents>
|
16 |
<compatible/>
|
17 |
<dependencies><required><php><min>5.0.0</min><max>5.9.9</max></php><extension><name>ionCube Loader</name><min></min><max></max></extension></required></dependencies>
|
18 |
</package>
|