Version Notes
* Add setting to limit the list of fields available for editing via the frontend
* Add support for editing of configurable products
* Add tabs for quick generating of QR labels (works only when MVentory_API extesion is installed)
* Extend filtering by all image types (i.e. base image, small image and thumbnail) in the list of products with missing images
* Allow to expand categories with 'Include in Navigation Menu' set to No
Download this release
Release Info
| Developer | Anatoly A. Kazantsev |
| Extension | mVentory_Productivity |
| Version | 1.1.1 |
| Comparing to | |
| See all releases | |
Code changes from version 1.1.0 to 1.1.1
- app/code/community/MVentory/Productivity/Block/Config/Buildinfo.php +42 -0
- app/code/community/MVentory/Productivity/Block/Panel.php +51 -61
- app/code/community/MVentory/Productivity/Helper/Attribute.php +247 -0
- app/code/community/MVentory/Productivity/Helper/Data.php +2 -25
- app/code/community/MVentory/Productivity/Model/Config.php +7 -0
- app/code/community/MVentory/Productivity/Model/Mage/Catalog/Category.php +111 -3
- app/code/community/MVentory/Productivity/Model/Observer.php +19 -3
- app/code/community/MVentory/Productivity/Model/Resource/Category/Tree.php +109 -0
- app/code/community/MVentory/Productivity/Model/Setting/Source/Copyattrs.php +47 -0
- app/code/community/MVentory/Productivity/Model/Setting/Source/Flattentype.php +49 -0
- app/code/community/MVentory/Productivity/controllers/ProductController.php +119 -42
- app/code/community/MVentory/Productivity/etc/config.xml +8 -1
- app/code/community/MVentory/Productivity/etc/system.xml +52 -3
- app/design/adminhtml/default/default/template/productivity/config/build-info.phtml +22 -0
- app/design/frontend/base/default/layout/productivity.xml +3 -5
- app/design/frontend/base/default/template/productivity/panel.phtml +37 -7
- app/etc/modules/MVentory_Productivity.xml +3 -0
- package.xml +46 -57
- skin/adminhtml/default/default/productivity.css +1 -0
- skin/frontend/base/default/productivity/css/styles.css +8 -0
- var/connect/mVentory_Productivity.xml +171 -0
app/code/community/MVentory/Productivity/Block/Config/Buildinfo.php
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* NOTICE OF LICENSE
|
| 5 |
+
*
|
| 6 |
+
* This source file is subject to the Creative Commons License BY-NC-ND.
|
| 7 |
+
* NonCommercial — You may not use the material for commercial purposes.
|
| 8 |
+
* NoDerivatives — If you remix, transform, or build upon the material,
|
| 9 |
+
* you may not distribute the modified material.
|
| 10 |
+
* See the full license at http://creativecommons.org/licenses/by-nc-nd/4.0/
|
| 11 |
+
*
|
| 12 |
+
* See http://mventory.com/legal/licensing/ for other licensing options.
|
| 13 |
+
*
|
| 14 |
+
* @package MVentory/Productivity
|
| 15 |
+
* @copyright Copyright (c) 2015 mVentory Ltd. (http://mventory.com)
|
| 16 |
+
* @license http://creativecommons.org/licenses/by-nc-nd/4.0/
|
| 17 |
+
*/
|
| 18 |
+
|
| 19 |
+
/**
|
| 20 |
+
* Block for displaying build version in system config
|
| 21 |
+
*
|
| 22 |
+
* @package MVentory/Productivity
|
| 23 |
+
* @author Andrew Gilman <andrew@mventory.com>
|
| 24 |
+
*/
|
| 25 |
+
|
| 26 |
+
class MVentory_Productivity_Block_Config_Buildinfo
|
| 27 |
+
extends Mage_Adminhtml_Block_Abstract
|
| 28 |
+
implements Varien_Data_Form_Element_Renderer_Interface
|
| 29 |
+
{
|
| 30 |
+
protected $_template = 'productivity/config/build-info.phtml';
|
| 31 |
+
|
| 32 |
+
/**
|
| 33 |
+
* Render fieldset html
|
| 34 |
+
*
|
| 35 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
| 36 |
+
* @return string
|
| 37 |
+
*/
|
| 38 |
+
public function render (Varien_Data_Form_Element_Abstract $element) {
|
| 39 |
+
return $this->toHtml();
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
app/code/community/MVentory/Productivity/Block/Panel.php
CHANGED
|
@@ -92,83 +92,73 @@ class MVentory_Productivity_Block_Panel
|
|
| 92 |
* @return Varien_Data_Form
|
| 93 |
*/
|
| 94 |
public function getEditForm() {
|
|
|
|
|
|
|
| 95 |
/* @var $product Mage_Catalog_Model_Product */
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
$
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
$allowedInputs = array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
/* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
|
| 106 |
-
foreach ($
|
| 107 |
-
$
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
unset($values[$i]);
|
| 124 |
-
|
| 125 |
-
//Also hide attribute if it doesn't have allowed values
|
| 126 |
-
if (count($values) < 2)
|
| 127 |
-
continue;
|
| 128 |
-
}
|
| 129 |
-
|
| 130 |
-
$field = array(
|
| 131 |
-
'name' => $attribute->getAttributeCode(),
|
| 132 |
-
'label' => $label,
|
| 133 |
-
'values' => $values
|
| 134 |
);
|
| 135 |
-
$input = in_array($attribute->getFrontendInput(), $allowedInputs)
|
| 136 |
-
? $attribute->getFrontendInput()
|
| 137 |
-
: 'text';
|
| 138 |
-
$form->addField($field['name'], $input, $field)
|
| 139 |
-
->setFormat(Mage::app()->getLocale()->getDateFormat()) // for date, time & datetime fields
|
| 140 |
-
->setRows(5); // in case it's a textarea, make it taller
|
| 141 |
}
|
| 142 |
|
| 143 |
$form->setValues($product->getData());
|
| 144 |
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
$form
|
| 148 |
-
->addField(
|
| 149 |
-
'qty',
|
| 150 |
-
$isConfigurable ? 'label' : 'text',
|
| 151 |
-
array(
|
| 152 |
-
'name' => 'qty',
|
| 153 |
-
'label' => 'Qty',
|
| 154 |
-
),
|
| 155 |
-
'price'
|
| 156 |
-
)
|
| 157 |
-
->setValue(
|
| 158 |
-
$isConfigurable
|
| 159 |
-
? $this->__('Edit individual sub-products')
|
| 160 |
-
: $product->getStockItem()->getQty() * 1
|
| 161 |
-
);
|
| 162 |
-
|
| 163 |
-
// add field after values so "Submit" value is not overwritten
|
| 164 |
$form->addField('submit', 'submit', array(
|
| 165 |
'value' => 'Save',
|
| 166 |
'no_span' => true,
|
| 167 |
));
|
|
|
|
| 168 |
$form->addField('cancel', 'button', array(
|
| 169 |
'value' => 'Cancel',
|
| 170 |
'no_span' => true,
|
| 171 |
));
|
|
|
|
| 172 |
return $form;
|
| 173 |
}
|
| 174 |
|
| 92 |
* @return Varien_Data_Form
|
| 93 |
*/
|
| 94 |
public function getEditForm() {
|
| 95 |
+
$helper = Mage::helper('productivity/attribute');
|
| 96 |
+
|
| 97 |
/* @var $product Mage_Catalog_Model_Product */
|
| 98 |
+
$product = Mage::registry('product');
|
| 99 |
+
|
| 100 |
+
$dateFormat = Mage::app()->getLocale()->getDateFormat();
|
| 101 |
+
$isConfigurable
|
| 102 |
+
= $product->getTypeId()
|
| 103 |
+
== Mage_Catalog_Model_Product_Type_Configurable::TYPE_CODE;
|
| 104 |
+
|
| 105 |
+
$allowedInputs = array(
|
| 106 |
+
'label' => true,
|
| 107 |
+
'text' => true,
|
| 108 |
+
'textarea' => true,
|
| 109 |
+
'date' => true,
|
| 110 |
+
'select' => true,
|
| 111 |
+
'multiselect' => true
|
| 112 |
+
);
|
| 113 |
+
|
| 114 |
+
$product['qty'] = $isConfigurable
|
| 115 |
+
? $this->__('Edit individual sub-products')
|
| 116 |
+
: (int) $product->getStockItem()->getQty();
|
| 117 |
+
|
| 118 |
+
$form = new Varien_Data_Form();
|
| 119 |
+
|
| 120 |
+
$form
|
| 121 |
+
->setUseContainer(true)
|
| 122 |
+
->setMethod('post')
|
| 123 |
+
/* @see MVentory_Productivity_ProductController::saveAction() */
|
| 124 |
+
->setAction(
|
| 125 |
+
Mage::getUrl('catalog/product/save', array('id' => $product->getId()))
|
| 126 |
+
);
|
| 127 |
|
| 128 |
/* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
|
| 129 |
+
foreach ($helper->getEditables($product) as $code => $attribute) {
|
| 130 |
+
$input = $attribute->getFrontendInput();
|
| 131 |
+
|
| 132 |
+
$form->addField(
|
| 133 |
+
$code,
|
| 134 |
+
isset($allowedInputs[$input]) ? $input : 'text',
|
| 135 |
+
array(
|
| 136 |
+
'name' => $code,
|
| 137 |
+
'label' => trim($attribute->getStoreLabel()),
|
| 138 |
+
'values' => $values = $attribute->usesSource()
|
| 139 |
+
? $attribute->getSource()->getAllOptions()
|
| 140 |
+
: null,
|
| 141 |
+
|
| 142 |
+
//In case it's a textarea, make it taller
|
| 143 |
+
'rows' => 5
|
| 144 |
+
),
|
| 145 |
+
($after = $attribute['_insert_after']) ? $after : false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
}
|
| 148 |
|
| 149 |
$form->setValues($product->getData());
|
| 150 |
|
| 151 |
+
//Add field after values so "Submit" value is not overwritten
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
$form->addField('submit', 'submit', array(
|
| 153 |
'value' => 'Save',
|
| 154 |
'no_span' => true,
|
| 155 |
));
|
| 156 |
+
|
| 157 |
$form->addField('cancel', 'button', array(
|
| 158 |
'value' => 'Cancel',
|
| 159 |
'no_span' => true,
|
| 160 |
));
|
| 161 |
+
|
| 162 |
return $form;
|
| 163 |
}
|
| 164 |
|
app/code/community/MVentory/Productivity/Helper/Attribute.php
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* NOTICE OF LICENSE
|
| 5 |
+
*
|
| 6 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
| 7 |
+
* that is bundled with this package in the file LICENSE-OSL.
|
| 8 |
+
* It is also available through the world-wide-web at this URL:
|
| 9 |
+
* http://opensource.org/licenses/osl-3.0.php
|
| 10 |
+
*
|
| 11 |
+
* @package MVentory/Productivity
|
| 12 |
+
* @copyright Copyright (c) 2014 mVentory Ltd. (http://mventory.com)
|
| 13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
| 14 |
+
*/
|
| 15 |
+
|
| 16 |
+
/**
|
| 17 |
+
* Attribute helper
|
| 18 |
+
*
|
| 19 |
+
* @package MVentory/Productivity
|
| 20 |
+
* @author Anatoly A. Kazantsev <anatoly@mventory.com>
|
| 21 |
+
*/
|
| 22 |
+
class MVentory_Productivity_Helper_Attribute
|
| 23 |
+
extends MVentory_Productivity_Helper_Data
|
| 24 |
+
{
|
| 25 |
+
protected $_whitelist = array(
|
| 26 |
+
//Selecting category is not implemented on frontend
|
| 27 |
+
//'category_ids' => true,
|
| 28 |
+
|
| 29 |
+
'name' => true,
|
| 30 |
+
'description' => true,
|
| 31 |
+
'short_description' => true,
|
| 32 |
+
'sku' => true,
|
| 33 |
+
'price' => true,
|
| 34 |
+
'special_price' => true,
|
| 35 |
+
|
| 36 |
+
//Setting date via calendar component is not implemented on frontend
|
| 37 |
+
//'special_from_date' => true,
|
| 38 |
+
//'special_to_date' => true,
|
| 39 |
+
|
| 40 |
+
'weight' => true,
|
| 41 |
+
'tax_class_id' => true
|
| 42 |
+
);
|
| 43 |
+
|
| 44 |
+
//!!!TODO: do we need to ignore following attributes in the front-end editor
|
| 45 |
+
protected $_blacklist = array('cost' => true);
|
| 46 |
+
|
| 47 |
+
protected $_configurableBlacklist = array(
|
| 48 |
+
);
|
| 49 |
+
|
| 50 |
+
protected $_nonReplicable = array(
|
| 51 |
+
'sku' => true,
|
| 52 |
+
'price' => true,
|
| 53 |
+
'special_price' => true,
|
| 54 |
+
'special_from_date' => true,
|
| 55 |
+
'special_to_data' => true,
|
| 56 |
+
'weight' => true,
|
| 57 |
+
|
| 58 |
+
//!!!TODO: do we need to process API specific attributes here or not?
|
| 59 |
+
//We can apply additional filters required by other exts using event
|
| 60 |
+
//observer
|
| 61 |
+
//'product_barcode_' => true,
|
| 62 |
+
);
|
| 63 |
+
|
| 64 |
+
/**
|
| 65 |
+
* Return list of attributes which can be edited
|
| 66 |
+
*
|
| 67 |
+
* @param Mage_Catalog_Model_Product $product Product
|
| 68 |
+
* @return array List of Mage_Catalog_Model_Resource_Eav_Attribute entities
|
| 69 |
+
*/
|
| 70 |
+
public function getEditables ($product) {
|
| 71 |
+
$setId = $product->getAttributeSetId();
|
| 72 |
+
$isConfigurable = $product->isConfigurable();
|
| 73 |
+
|
| 74 |
+
$attrs = $this->_getAttrs($setId);
|
| 75 |
+
$allow = $this->_getAllowedAttrsByUser();
|
| 76 |
+
$ignore = $isConfigurable
|
| 77 |
+
? $this->_configurableBlacklist
|
| 78 |
+
: array();
|
| 79 |
+
|
| 80 |
+
//Add QTY pseudo-attribute before filtering so filtering rules can be
|
| 81 |
+
//applied for it
|
| 82 |
+
$attrs['qty'] = $this->_getQtyPseudoAttr($isConfigurable);
|
| 83 |
+
|
| 84 |
+
//Remove attributes which are used in configurable attributes so they
|
| 85 |
+
//won't appear in the fronend editor
|
| 86 |
+
if ($isConfigurable)
|
| 87 |
+
$attrs = $this->_removeConfigurableAttrs($attrs, $product);
|
| 88 |
+
|
| 89 |
+
$_attrs = array();
|
| 90 |
+
|
| 91 |
+
foreach ($attrs as $attr)
|
| 92 |
+
if ((!$attr->getId() || $attr->isInSet($setId))
|
| 93 |
+
&& $this->_isAllowedAttribute($attr, $allow, $ignore))
|
| 94 |
+
$_attrs[$attr->getAttributeCode()] = $attr;
|
| 95 |
+
|
| 96 |
+
return $_attrs;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
/**
|
| 100 |
+
* Return list of attributes which can be replocated among configurable
|
| 101 |
+
* products and its assigned simple products
|
| 102 |
+
*
|
| 103 |
+
* @param Mage_Catalog_Model_Product $product Product
|
| 104 |
+
* @return array List of Mage_Catalog_Model_Resource_Eav_Attribute entities
|
| 105 |
+
*/
|
| 106 |
+
public function getReplicables ($product) {
|
| 107 |
+
$setId = $product->getAttributeSetId();
|
| 108 |
+
|
| 109 |
+
$attrs = $this->_removeConfigurableAttrs(
|
| 110 |
+
$this->_getAttrs($setId),
|
| 111 |
+
$product
|
| 112 |
+
);
|
| 113 |
+
|
| 114 |
+
$allow = $this->_getReplicableAttrsByUser();
|
| 115 |
+
|
| 116 |
+
$_attrs = array();
|
| 117 |
+
|
| 118 |
+
foreach ($attrs as $attr)
|
| 119 |
+
if ((!$attr->getId() || $attr->isInSet($setId))
|
| 120 |
+
&& $this->_isAllowedAttribute($attr, $allow, $this->_nonReplicable))
|
| 121 |
+
$_attrs[$attr->getAttributeCode()] = $attr;
|
| 122 |
+
|
| 123 |
+
return $_attrs;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
/**
|
| 127 |
+
* Return sorted list of attributes for the specified attribute set
|
| 128 |
+
*
|
| 129 |
+
* @param int $setId ID of atrribute set
|
| 130 |
+
* @return array List of Mage_Catalog_Model_Resource_Eav_Attribute entities
|
| 131 |
+
*/
|
| 132 |
+
protected function _getAttrs ($setId) {
|
| 133 |
+
return Mage::getModel('catalog/product')
|
| 134 |
+
->getResource()
|
| 135 |
+
->loadAllAttributes()
|
| 136 |
+
->getSortedAttributes($setId);
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
/**
|
| 140 |
+
* Check if specified attribute is allowed.
|
| 141 |
+
* List of allowed attributes has higher priority over list of ignored and
|
| 142 |
+
* blacklisted attributes.
|
| 143 |
+
*
|
| 144 |
+
* @param Mage_Catalog_Model_Resource_Eav_Attribute $attr Atrribute
|
| 145 |
+
* @param array $allow Key based list of allowed attributes
|
| 146 |
+
* @param array $ignore Key based list of attributes to ignore
|
| 147 |
+
*/
|
| 148 |
+
protected function _isAllowedAttribute ($attr,
|
| 149 |
+
$allow = array(),
|
| 150 |
+
$ignore = array()) {
|
| 151 |
+
|
| 152 |
+
$code = $attr->getAttributeCode();
|
| 153 |
+
|
| 154 |
+
if (($allow && !isset($allow[$code]))
|
| 155 |
+
|| isset($ignore[$code])
|
| 156 |
+
|| isset($this->_blacklist[$code]))
|
| 157 |
+
return false;
|
| 158 |
+
|
| 159 |
+
return ($attr->getIsVisible() && $attr->getIsUserDefined())
|
| 160 |
+
|| isset($this->_whitelist[$code]);
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
/**
|
| 164 |
+
* Get list of allowed attributes by user
|
| 165 |
+
*
|
| 166 |
+
* @return array Key based list of codes of allowed attributes
|
| 167 |
+
*/
|
| 168 |
+
protected function _getAllowedAttrsByUser () {
|
| 169 |
+
$attrs = trim(
|
| 170 |
+
Mage::getStoreConfig(MVentory_Productivity_Model_Config::_EDITABLE_ATTRS)
|
| 171 |
+
);
|
| 172 |
+
|
| 173 |
+
return $attrs ? $this->_parseListOfAttrs($attrs) : array();
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
/**
|
| 177 |
+
* Get list of replicable attributes by user
|
| 178 |
+
*
|
| 179 |
+
* @return array Key based list of codes of replicable attributes
|
| 180 |
+
*/
|
| 181 |
+
public function _getReplicableAttrsByUser () {
|
| 182 |
+
$attrs = strtolower(trim(
|
| 183 |
+
Mage::getStoreConfig(MVentory_Productivity_Model_Config::_COPY_ATTRS)
|
| 184 |
+
));
|
| 185 |
+
|
| 186 |
+
return $attrs
|
| 187 |
+
? $this->_parseListOfAttrs($attrs)
|
| 188 |
+
: $this->_getAllowedAttrsByUser();
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
/**
|
| 192 |
+
* Parse user-defined list of attribute codes and return it as key-based array
|
| 193 |
+
*
|
| 194 |
+
* @param string $attrs
|
| 195 |
+
* List of attribute coes. One attribute code per line
|
| 196 |
+
*
|
| 197 |
+
* @return array
|
| 198 |
+
* Key-based list of attribute codes
|
| 199 |
+
*/
|
| 200 |
+
protected function _parseListOfAttrs ($attrs) {
|
| 201 |
+
return array_flip(array_map(
|
| 202 |
+
'trim',
|
| 203 |
+
explode("\n", str_replace(array("\r\n", "\r"), "\n", trim($attrs)))
|
| 204 |
+
));
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
/**
|
| 208 |
+
* Return model for QTY pseudo-attribute with prefilled required fields
|
| 209 |
+
*
|
| 210 |
+
* @param bool $isConfigurable Show if current product is configurable one
|
| 211 |
+
* @return Catalog_Model_Resource_Eav_Attribute
|
| 212 |
+
*/
|
| 213 |
+
protected function _getQtyPseudoAttr ($isConfigurable) {
|
| 214 |
+
return Mage::getModel(
|
| 215 |
+
'catalog/resource_eav_attribute',
|
| 216 |
+
array(
|
| 217 |
+
'attribute_code' => 'qty',
|
| 218 |
+
'store_label' => 'Qty',
|
| 219 |
+
'frontend_input' => $isConfigurable ? 'label' : 'text',
|
| 220 |
+
'uses_sources' => false,
|
| 221 |
+
'is_visible' => true,
|
| 222 |
+
'is_user_defined' => true,
|
| 223 |
+
'_insert_after' => 'price'
|
| 224 |
+
)
|
| 225 |
+
);
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
/**
|
| 229 |
+
* Filter out attributes which are used in configurable product
|
| 230 |
+
*
|
| 231 |
+
* @param array $attrs List of attributes to filter
|
| 232 |
+
* @param Mage_Catalog_Model_Product $product Configurable product
|
| 233 |
+
* @return array List of attributes
|
| 234 |
+
*/
|
| 235 |
+
protected function _removeConfigurableAttrs ($attrs, $product) {
|
| 236 |
+
$_attrs = (($_attrs = $product->getConfigurableAttributesData()) !== null)
|
| 237 |
+
? $_attrs
|
| 238 |
+
: $product
|
| 239 |
+
->getTypeInstance()
|
| 240 |
+
->getConfigurableAttributesAsArray();
|
| 241 |
+
|
| 242 |
+
foreach ($_attrs as $_attr)
|
| 243 |
+
unset($attrs[$_attr['attribute_code']]);
|
| 244 |
+
|
| 245 |
+
return $attrs;
|
| 246 |
+
}
|
| 247 |
+
}
|
app/code/community/MVentory/Productivity/Helper/Data.php
CHANGED
|
@@ -219,30 +219,7 @@ class MVentory_Productivity_Helper_Data
|
|
| 219 |
->send();
|
| 220 |
}
|
| 221 |
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
*
|
| 225 |
-
* @param Mage_Catalog_Model_Product $product
|
| 226 |
-
* @return array of Mage_Catalog_Model_Resource_Eav_Attribute
|
| 227 |
-
*/
|
| 228 |
-
public function getVisibleAttributes($product) {
|
| 229 |
-
$result = array();
|
| 230 |
-
if (!$product) return $result;
|
| 231 |
-
|
| 232 |
-
$attributes = $product->getAttributes();
|
| 233 |
-
// these attrs are always shown somewhere even if not "visible on front"
|
| 234 |
-
$result['name'] = $attributes['name'];
|
| 235 |
-
$result['description'] = $attributes['description'];
|
| 236 |
-
$result['price'] = $attributes['price'];
|
| 237 |
-
|
| 238 |
-
foreach ($attributes as $attribute) {
|
| 239 |
-
$code = $attribute->getAttributeCode();
|
| 240 |
-
|
| 241 |
-
if ($attribute->getIsVisibleOnFront() || substr($code, -1) === '_')
|
| 242 |
-
$result[$code] = $attribute;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
return $result;
|
| 246 |
}
|
| 247 |
-
|
| 248 |
}
|
| 219 |
->send();
|
| 220 |
}
|
| 221 |
|
| 222 |
+
public function isMVentoryModuleEnabled () {
|
| 223 |
+
return parent::isModuleEnabled('MVentory_API');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
}
|
|
|
|
| 225 |
}
|
app/code/community/MVentory/Productivity/Model/Config.php
CHANGED
|
@@ -26,9 +26,16 @@ class MVentory_Productivity_Model_Config {
|
|
| 26 |
const _CATEGORY_HOME_URL = 'productivity/category/home_url';
|
| 27 |
const _DISPLAY_PRODUCTS = 'productivity/category/display_descending_products';
|
| 28 |
const _PRODUCT_SAVE_SCOPE = 'productivity/product/save_scope';
|
|
|
|
|
|
|
| 29 |
const _ANALYTICS_URL = 'productivity/analytics/url';
|
| 30 |
|
| 31 |
//Product save scopes
|
| 32 |
const PRODUCT_SCOPE_GLOBAL = 1;
|
| 33 |
const PRODUCT_SCOPE_CURRENT = 2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
}
|
| 26 |
const _CATEGORY_HOME_URL = 'productivity/category/home_url';
|
| 27 |
const _DISPLAY_PRODUCTS = 'productivity/category/display_descending_products';
|
| 28 |
const _PRODUCT_SAVE_SCOPE = 'productivity/product/save_scope';
|
| 29 |
+
const _EDITABLE_ATTRS = 'productivity/product/editable_attr';
|
| 30 |
+
const _COPY_ATTRS = 'productivity/product/copy_attrs';
|
| 31 |
const _ANALYTICS_URL = 'productivity/analytics/url';
|
| 32 |
|
| 33 |
//Product save scopes
|
| 34 |
const PRODUCT_SCOPE_GLOBAL = 1;
|
| 35 |
const PRODUCT_SCOPE_CURRENT = 2;
|
| 36 |
+
|
| 37 |
+
//Types of flatten category tree
|
| 38 |
+
const FLATTEN_NO = 0;
|
| 39 |
+
const FLATTEN_PATHS = 1;
|
| 40 |
+
const FLATTEN_EXPAND = 2;
|
| 41 |
}
|
app/code/community/MVentory/Productivity/Model/Mage/Catalog/Category.php
CHANGED
|
@@ -71,6 +71,19 @@ class MVentory_Productivity_Model_Mage_Catalog_Category
|
|
| 71 |
$asCollection = false,
|
| 72 |
$toLoad = true) {
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
$categories = parent::getCategories(
|
| 75 |
$parent,
|
| 76 |
$recursionLevel,
|
|
@@ -79,9 +92,7 @@ class MVentory_Productivity_Model_Mage_Catalog_Category
|
|
| 79 |
$toLoad
|
| 80 |
);
|
| 81 |
|
| 82 |
-
return
|
| 83 |
-
MVentory_Productivity_Model_Config::_CATEGORY_FLATTEN_TREE
|
| 84 |
-
)
|
| 85 |
? $this->_removeParentCategories($categories)
|
| 86 |
: $categories;
|
| 87 |
}
|
|
@@ -108,4 +119,101 @@ class MVentory_Productivity_Model_Mage_Catalog_Category
|
|
| 108 |
|
| 109 |
return $this->_removeParentCategories($children);
|
| 110 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
}
|
| 71 |
$asCollection = false,
|
| 72 |
$toLoad = true) {
|
| 73 |
|
| 74 |
+
$flattenType = (int) Mage::getStoreConfig(
|
| 75 |
+
MVentory_Productivity_Model_Config::_CATEGORY_FLATTEN_TREE
|
| 76 |
+
);
|
| 77 |
+
|
| 78 |
+
if ($flattenType == MVentory_Productivity_Model_Config::FLATTEN_EXPAND)
|
| 79 |
+
return $this->_expandCategories($this->_getCategories(
|
| 80 |
+
$parent,
|
| 81 |
+
$recursionLevel,
|
| 82 |
+
$sorted,
|
| 83 |
+
$asCollection,
|
| 84 |
+
$toLoad
|
| 85 |
+
));
|
| 86 |
+
|
| 87 |
$categories = parent::getCategories(
|
| 88 |
$parent,
|
| 89 |
$recursionLevel,
|
| 92 |
$toLoad
|
| 93 |
);
|
| 94 |
|
| 95 |
+
return $flattenType == MVentory_Productivity_Model_Config::FLATTEN_PATHS
|
|
|
|
|
|
|
| 96 |
? $this->_removeParentCategories($categories)
|
| 97 |
: $categories;
|
| 98 |
}
|
| 119 |
|
| 120 |
return $this->_removeParentCategories($children);
|
| 121 |
}
|
| 122 |
+
|
| 123 |
+
/**
|
| 124 |
+
* Expand recursively hidden (include_in_menu = 0) categories. Preserve
|
| 125 |
+
* order of categories. Hide empty (no subcategories) and hidden categories.
|
| 126 |
+
*
|
| 127 |
+
* @param Varien_Data_Tree_Node_Collection $categories Collection of nodes
|
| 128 |
+
* @return Varien_Data_Tree_Node_Collection
|
| 129 |
+
*/
|
| 130 |
+
protected function _expandCategories ($categories) {
|
| 131 |
+
if (!$categories->count())
|
| 132 |
+
return $categories;
|
| 133 |
+
|
| 134 |
+
foreach ($categories as $id => $category) {
|
| 135 |
+
$children = $this->_expandCategories($category->getChildren());
|
| 136 |
+
|
| 137 |
+
$noChildren = !$children->count();
|
| 138 |
+
$notIncludeInMenu = !$category->getIncludeInMenu();
|
| 139 |
+
|
| 140 |
+
//Hide empty and not included in menu categories
|
| 141 |
+
if ($notIncludeInMenu && $noChildren) {
|
| 142 |
+
$categories->delete($category);
|
| 143 |
+
|
| 144 |
+
continue;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
//Ignore empty categories
|
| 148 |
+
if ($noChildren)
|
| 149 |
+
continue;
|
| 150 |
+
|
| 151 |
+
//Remember hidden category to expand on next step
|
| 152 |
+
if ($notIncludeInMenu)
|
| 153 |
+
$replace[$id] = true;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
if (isset($replace)) {
|
| 157 |
+
|
| 158 |
+
//Expand hidden categories and re-add visible categories as is to preserve
|
| 159 |
+
//original order
|
| 160 |
+
foreach ($categories as $id => $category) {
|
| 161 |
+
$categories->delete($category);
|
| 162 |
+
|
| 163 |
+
if (isset($replace[$id])) {
|
| 164 |
+
|
| 165 |
+
//Copy level and position values of expanded category to it's children
|
| 166 |
+
$level = $category->getLevel();
|
| 167 |
+
$position = $category->getPosition();
|
| 168 |
+
|
| 169 |
+
foreach ($category->getChildren() as $child) {
|
| 170 |
+
$child
|
| 171 |
+
->setLevel($level)
|
| 172 |
+
->setPosition($position);
|
| 173 |
+
|
| 174 |
+
$category->removeChild($child);
|
| 175 |
+
$categories->add($child);
|
| 176 |
+
}
|
| 177 |
+
} else
|
| 178 |
+
$categories->add($category);
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
return $categories;
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
/**
|
| 186 |
+
* Retrieve categories
|
| 187 |
+
*
|
| 188 |
+
* This method is copy of
|
| 189 |
+
* Mage_Catalog_Model_Resource_Category::getCategories(), but with changed
|
| 190 |
+
* category tree model for expanding hidden categories functionality.
|
| 191 |
+
*
|
| 192 |
+
* !!!TODO: move to some helper class to minimize confusion with
|
| 193 |
+
* getCategories() method of this class
|
| 194 |
+
*
|
| 195 |
+
* @param integer $parent
|
| 196 |
+
* @param integer $recursionLevel
|
| 197 |
+
* @param boolean|string $sorted
|
| 198 |
+
* @param boolean $asCollection
|
| 199 |
+
* @param boolean $toLoad
|
| 200 |
+
* @return Varien_Data_Tree_Node_Collection|Mage_Catalog_Model_Resource_Category_Collection
|
| 201 |
+
*/
|
| 202 |
+
protected function _getCategories ($parent,
|
| 203 |
+
$recursionLevel = 0,
|
| 204 |
+
$sorted = false,
|
| 205 |
+
$asCollection = false,
|
| 206 |
+
$toLoad = true)
|
| 207 |
+
{
|
| 208 |
+
/* @var $tree MVentory_Productivity_Model_Resource_Category_Tree */
|
| 209 |
+
$tree = Mage::getResourceModel('productivity/category_tree');
|
| 210 |
+
|
| 211 |
+
$node = $tree
|
| 212 |
+
->loadNode($parent)
|
| 213 |
+
->loadChildren($recursionLevel);
|
| 214 |
+
|
| 215 |
+
$tree->addCollectionData(null, $sorted, $parent, $toLoad, true);
|
| 216 |
+
|
| 217 |
+
return $asCollection ? $tree->getCollection() : $node->getChildren();
|
| 218 |
+
}
|
| 219 |
}
|
app/code/community/MVentory/Productivity/Model/Observer.php
CHANGED
|
@@ -61,13 +61,29 @@ class MVentory_Productivity_Model_Observer {
|
|
| 61 |
$wherePart = $select->getPart(Zend_Db_Select::WHERE);
|
| 62 |
|
| 63 |
foreach ($wherePart as $i => $condition)
|
| 64 |
-
if (strpos($condition, '
|
|
|
|
|
|
|
| 65 |
unset($wherePart[$i]);
|
| 66 |
|
| 67 |
$select->setPart(Zend_Db_Select::WHERE, $wherePart);
|
| 68 |
|
| 69 |
-
$collection->addAttributeToFilter(
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
}
|
| 72 |
|
| 73 |
public function rememberAdminState($observer) {
|
| 61 |
$wherePart = $select->getPart(Zend_Db_Select::WHERE);
|
| 62 |
|
| 63 |
foreach ($wherePart as $i => $condition)
|
| 64 |
+
if (strpos($condition, 'image') !== false
|
| 65 |
+
|| strpos($condition, 'small_image') !== false
|
| 66 |
+
|| strpos($condition, 'thumbnail') !== false)
|
| 67 |
unset($wherePart[$i]);
|
| 68 |
|
| 69 |
$select->setPart(Zend_Db_Select::WHERE, $wherePart);
|
| 70 |
|
| 71 |
+
$collection->addAttributeToFilter(
|
| 72 |
+
array(
|
| 73 |
+
array(
|
| 74 |
+
'attribute' => 'image',
|
| 75 |
+
'in' => array('no_selection', '')
|
| 76 |
+
),
|
| 77 |
+
array(
|
| 78 |
+
'attribute' => 'small_image',
|
| 79 |
+
'in' => array('no_selection', '')
|
| 80 |
+
),
|
| 81 |
+
array(
|
| 82 |
+
'attribute' => 'thumbnail',
|
| 83 |
+
'in' => array('no_selection', '')
|
| 84 |
+
)
|
| 85 |
+
)
|
| 86 |
+
);
|
| 87 |
}
|
| 88 |
|
| 89 |
public function rememberAdminState($observer) {
|
app/code/community/MVentory/Productivity/Model/Resource/Category/Tree.php
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* NOTICE OF LICENSE
|
| 5 |
+
*
|
| 6 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
| 7 |
+
* that is bundled with this package in the file LICENSE-OSL.
|
| 8 |
+
* It is also available through the world-wide-web at this URL:
|
| 9 |
+
* http://opensource.org/licenses/osl-3.0.php
|
| 10 |
+
*
|
| 11 |
+
* @package MVentory/Productivity
|
| 12 |
+
* @copyright Copyright (c) 2014 mVentory Ltd. (http://mventory.com)
|
| 13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
| 14 |
+
*/
|
| 15 |
+
|
| 16 |
+
/**
|
| 17 |
+
* Category tree model
|
| 18 |
+
*
|
| 19 |
+
* @package MVentory/Productivity
|
| 20 |
+
* @author Anatoly A. Kazantsev <anatoly@mventory.com>
|
| 21 |
+
*/
|
| 22 |
+
|
| 23 |
+
class MVentory_Productivity_Model_Resource_Category_Tree
|
| 24 |
+
extends Mage_Catalog_Model_Resource_Category_Tree
|
| 25 |
+
{
|
| 26 |
+
/**
|
| 27 |
+
* Add specified or new collection of categories to category tree. Filter
|
| 28 |
+
* out disabled and non-active categories (if $onlyActive parameter is True)
|
| 29 |
+
* and categories with IDs from $exclude parameter. Load category data and
|
| 30 |
+
* add it to tree nodes if $toLoad parameter is True
|
| 31 |
+
*
|
| 32 |
+
* NOTE: this method is redefined to remove filtering out categories
|
| 33 |
+
* by 'include_in_menu' field for expanding hidden categories in menu
|
| 34 |
+
*
|
| 35 |
+
* !!!IMPORTANT: this method should stay synchronized with original one.
|
| 36 |
+
* Changes on original method should be inspected and applied
|
| 37 |
+
* on every Magento release.
|
| 38 |
+
*
|
| 39 |
+
* @param Mage_Catalog_Model_Resource_Category_Collection $collection
|
| 40 |
+
* @param boolean|string $sorted Sort collection of categories by specified
|
| 41 |
+
* field or by 'name' field if is True
|
| 42 |
+
* @param array $exclude List of category IDs to exclude
|
| 43 |
+
* @param boolean $toLoad Load or not category data
|
| 44 |
+
* @param boolean $onlyActive Load only active categories
|
| 45 |
+
* @return Mage_Catalog_Model_Resource_Category_Tree
|
| 46 |
+
*/
|
| 47 |
+
public function addCollectionData ($collection = null,
|
| 48 |
+
$sorted = false,
|
| 49 |
+
$exclude = array(),
|
| 50 |
+
$toLoad = true,
|
| 51 |
+
$onlyActive = false)
|
| 52 |
+
{
|
| 53 |
+
if (is_null($collection))
|
| 54 |
+
$collection = $this->getCollection($sorted);
|
| 55 |
+
else
|
| 56 |
+
$this->setCollection($collection);
|
| 57 |
+
|
| 58 |
+
if (!is_array($exclude))
|
| 59 |
+
$exclude = array($exclude);
|
| 60 |
+
|
| 61 |
+
//!!!TODO: This can be combined with filtering $disabledIds.
|
| 62 |
+
//Just merge $exclude with $disabledIds and use it for filtering by
|
| 63 |
+
//'entity_id' field with 'nin' condition.
|
| 64 |
+
$nodeIds = array();
|
| 65 |
+
|
| 66 |
+
foreach ($this->getNodes() as $node)
|
| 67 |
+
if (!in_array($node->getId(), $exclude))
|
| 68 |
+
$nodeIds[] = $node->getId();
|
| 69 |
+
|
| 70 |
+
$collection->addIdFilter($nodeIds);
|
| 71 |
+
|
| 72 |
+
if ($onlyActive) {
|
| 73 |
+
$disabledIds = $this->_getDisabledIds($collection);
|
| 74 |
+
|
| 75 |
+
if ($disabledIds)
|
| 76 |
+
$collection->addFieldToFilter(
|
| 77 |
+
'entity_id',
|
| 78 |
+
array('nin' => $disabledIds)
|
| 79 |
+
);
|
| 80 |
+
|
| 81 |
+
$collection->addAttributeToFilter('is_active', 1);
|
| 82 |
+
|
| 83 |
+
//In original method it filters out categories by 'include_in_menu'
|
| 84 |
+
//field, but we don't need it for expanding hidden ('include_in_menu' = 0)
|
| 85 |
+
//categories. So this filter was removed and following line was added
|
| 86 |
+
//to load values of 'include_in_menu' field in collection's entities
|
| 87 |
+
$collection->addAttributeToSelect('include_in_menu');
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
if ($this->_joinUrlRewriteIntoCollection) {
|
| 91 |
+
$collection->joinUrlRewrite();
|
| 92 |
+
$this->_joinUrlRewriteIntoCollection = false;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
if ($toLoad) {
|
| 96 |
+
$collection->load();
|
| 97 |
+
|
| 98 |
+
foreach ($collection as $category)
|
| 99 |
+
if ($node = $this->getNodeById($category->getId()))
|
| 100 |
+
$node->addData($category->getData());
|
| 101 |
+
|
| 102 |
+
foreach ($this->getNodes() as $node)
|
| 103 |
+
if (!$collection->getItemById($node->getId()) && $node->getParent())
|
| 104 |
+
$this->removeNode($node);
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
return $this;
|
| 108 |
+
}
|
| 109 |
+
}
|
app/code/community/MVentory/Productivity/Model/Setting/Source/Copyattrs.php
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* NOTICE OF LICENSE
|
| 5 |
+
*
|
| 6 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
| 7 |
+
* that is bundled with this package in the file LICENSE-OSL.
|
| 8 |
+
* It is also available through the world-wide-web at this URL:
|
| 9 |
+
* http://opensource.org/licenses/osl-3.0.php
|
| 10 |
+
*
|
| 11 |
+
* @package MVentory/Productivity
|
| 12 |
+
* @copyright Copyright (c) 2014 mVentory Ltd. (http://mventory.com)
|
| 13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
| 14 |
+
*/
|
| 15 |
+
|
| 16 |
+
/**
|
| 17 |
+
* Source model for 'Copy from configurable to simple products' option
|
| 18 |
+
*
|
| 19 |
+
* @package MVentory/Productivity
|
| 20 |
+
* @author Anatoly A. Kazantsev <anatoly@mventory.com>
|
| 21 |
+
*/
|
| 22 |
+
class MVentory_Productivity_Model_Setting_Source_Copyattrs {
|
| 23 |
+
|
| 24 |
+
/**
|
| 25 |
+
* Options getter
|
| 26 |
+
*
|
| 27 |
+
* @return array
|
| 28 |
+
*/
|
| 29 |
+
public function toOptionArray () {
|
| 30 |
+
$helper = Mage::helper('productivity');
|
| 31 |
+
|
| 32 |
+
return array(
|
| 33 |
+
array(
|
| 34 |
+
'value' => 'name',
|
| 35 |
+
'label' => $helper->__('Name')
|
| 36 |
+
),
|
| 37 |
+
array(
|
| 38 |
+
'value' => 'description',
|
| 39 |
+
'label' => $helper->__('Description')
|
| 40 |
+
),
|
| 41 |
+
array(
|
| 42 |
+
'value' => 'short_description',
|
| 43 |
+
'label' => $helper->__('Short Description')
|
| 44 |
+
)
|
| 45 |
+
);
|
| 46 |
+
}
|
| 47 |
+
}
|
app/code/community/MVentory/Productivity/Model/Setting/Source/Flattentype.php
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* NOTICE OF LICENSE
|
| 5 |
+
*
|
| 6 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
| 7 |
+
* that is bundled with this package in the file LICENSE-OSL.
|
| 8 |
+
* It is also available through the world-wide-web at this URL:
|
| 9 |
+
* http://opensource.org/licenses/osl-3.0.php
|
| 10 |
+
*
|
| 11 |
+
* @package MVentory/Productivity
|
| 12 |
+
* @copyright Copyright (c) 2014 mVentory Ltd. (http://mventory.com)
|
| 13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
| 14 |
+
*/
|
| 15 |
+
|
| 16 |
+
/**
|
| 17 |
+
* Source model for type of flatten category tree
|
| 18 |
+
*
|
| 19 |
+
* @package MVentory/Productivity
|
| 20 |
+
* @author Anatoly A. Kazantsev <anatoly@mventory.com>
|
| 21 |
+
*/
|
| 22 |
+
class MVentory_Productivity_Model_Setting_Source_Flattentype {
|
| 23 |
+
|
| 24 |
+
/**
|
| 25 |
+
* Options getter
|
| 26 |
+
*
|
| 27 |
+
* @return array
|
| 28 |
+
*/
|
| 29 |
+
public function toOptionArray () {
|
| 30 |
+
$helper = Mage::helper('productivity');
|
| 31 |
+
|
| 32 |
+
return array(
|
| 33 |
+
array(
|
| 34 |
+
'value' => MVentory_Productivity_Model_Config::FLATTEN_NO,
|
| 35 |
+
'label' => $helper->__('No')
|
| 36 |
+
),
|
| 37 |
+
array(
|
| 38 |
+
'value' => MVentory_Productivity_Model_Config::FLATTEN_PATHS,
|
| 39 |
+
'label' => $helper->__('Flatten single branch paths')
|
| 40 |
+
),
|
| 41 |
+
array(
|
| 42 |
+
'value' => MVentory_Productivity_Model_Config::FLATTEN_EXPAND,
|
| 43 |
+
'label' => $helper->__('Show children of hidden parents')
|
| 44 |
+
)
|
| 45 |
+
);
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
?>
|
app/code/community/MVentory/Productivity/controllers/ProductController.php
CHANGED
|
@@ -35,34 +35,50 @@ class MVentory_Productivity_ProductController extends Mage_Core_Controller_Front
|
|
| 35 |
$productId = $request->getParam('id');
|
| 36 |
// Useful stuff
|
| 37 |
$storeId = Mage::app()->getStore()->getId();
|
| 38 |
-
$helper = Mage::helper('productivity');
|
| 39 |
|
| 40 |
if ($helper->isReviewerLogged())
|
| 41 |
{
|
| 42 |
//Check if save scope is set and we need to load product
|
| 43 |
//with dara from current store
|
| 44 |
-
$
|
| 45 |
MVentory_Productivity_Model_Config::_PRODUCT_SAVE_SCOPE
|
| 46 |
);
|
| 47 |
-
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
$product = Mage::getModel('catalog/product');
|
| 51 |
|
| 52 |
-
//Set current store ID before
|
| 53 |
//e.g. user selected Current scope optin in admin interface
|
| 54 |
-
if ($
|
| 55 |
$product->setStoreId($storeId);
|
| 56 |
|
| 57 |
-
$product
|
|
|
|
|
|
|
| 58 |
|
| 59 |
// Only allow certain attributes to be set, if missing product will not be changed.
|
| 60 |
$data = array_intersect_key(
|
| 61 |
$request->getPost(),
|
| 62 |
-
$helper->
|
| 63 |
);
|
| 64 |
-
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
}
|
| 67 |
|
| 68 |
//Find all attributes which value was changed in the editor by comparing
|
|
@@ -78,8 +94,8 @@ class MVentory_Productivity_ProductController extends Mage_Core_Controller_Front
|
|
| 78 |
if ($product->getData($code) != $value)
|
| 79 |
$changeAttrs[$code] = true;
|
| 80 |
|
| 81 |
-
if ($
|
| 82 |
-
$qty = (float) $
|
| 83 |
|
| 84 |
$data['stock_data'] = array(
|
| 85 |
'qty'
|
|
@@ -93,48 +109,109 @@ class MVentory_Productivity_ProductController extends Mage_Core_Controller_Front
|
|
| 93 |
);
|
| 94 |
}
|
| 95 |
|
| 96 |
-
if ($
|
| 97 |
$product->addData($data);
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
//option of Save edits to setting in admin interface
|
| 102 |
-
//
|
| 103 |
-
//Filter out following attributes:
|
| 104 |
-
// - Gallery attr (is a complex attr with it's own editor)
|
| 105 |
-
// - Global (setting value of global attr to false removes it globally)
|
| 106 |
-
// - Non-visible (non-visible attributes can't be edited directly)
|
| 107 |
-
// - Without input field (this attributes can'be edited directly)
|
| 108 |
-
//
|
| 109 |
-
//Filtering rules are taken from:
|
| 110 |
-
// - Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Attributes::_prepareForm()
|
| 111 |
-
// - Mage_Adminhtml_Block_Widget_Form::_setFieldset()
|
| 112 |
-
if ($hasScope) foreach ($product->getAttributes() as $code => $attr) {
|
| 113 |
-
$allow = $code != 'gallery'
|
| 114 |
-
&& $attr->getIsGlobal()
|
| 115 |
-
!= Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL
|
| 116 |
-
&& $attr->getIsVisible()
|
| 117 |
-
&& $attr->getFrontend()->getInputType();
|
| 118 |
-
|
| 119 |
-
if (!$allow || isset($changeAttrs[$code]))
|
| 120 |
-
continue;
|
| 121 |
-
|
| 122 |
-
$product->setData($code, false);
|
| 123 |
-
}
|
| 124 |
-
|
| 125 |
-
//Product saves must be made from admin store
|
| 126 |
-
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
|
| 127 |
|
| 128 |
$product->save();
|
| 129 |
|
|
|
|
|
|
|
|
|
|
| 130 |
//Reset store to be neat
|
| 131 |
Mage::app()->setCurrentStore($storeId);
|
| 132 |
}
|
| 133 |
}
|
| 134 |
|
| 135 |
-
//
|
| 136 |
$this->_redirectUrl($product->setData('url', null)->getProductUrl());
|
| 137 |
}
|
| 138 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
}
|
| 140 |
|
| 35 |
$productId = $request->getParam('id');
|
| 36 |
// Useful stuff
|
| 37 |
$storeId = Mage::app()->getStore()->getId();
|
| 38 |
+
$helper = Mage::helper('productivity/attribute');
|
| 39 |
|
| 40 |
if ($helper->isReviewerLogged())
|
| 41 |
{
|
| 42 |
//Check if save scope is set and we need to load product
|
| 43 |
//with dara from current store
|
| 44 |
+
$saveScope = (int) Mage::getStoreConfig(
|
| 45 |
MVentory_Productivity_Model_Config::_PRODUCT_SAVE_SCOPE
|
| 46 |
);
|
| 47 |
+
|
| 48 |
+
if ($saveScope
|
| 49 |
+
!= MVentory_Productivity_Model_Config::PRODUCT_SCOPE_CURRENT)
|
| 50 |
+
$storeId = false;
|
| 51 |
+
|
| 52 |
+
unset($saveScope);
|
| 53 |
+
|
| 54 |
+
//Product loads and saves must be made from admin store
|
| 55 |
+
//- Magento doesn't fill origData array when product is loaded from
|
| 56 |
+
// non admin scope, so some core comparing function (for comparing
|
| 57 |
+
// original and current product data) won't work as expected
|
| 58 |
+
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
|
| 59 |
|
| 60 |
$product = Mage::getModel('catalog/product');
|
| 61 |
|
| 62 |
+
//Set current store ID before loading product if save scope is set,
|
| 63 |
//e.g. user selected Current scope optin in admin interface
|
| 64 |
+
if ($storeId !== false)
|
| 65 |
$product->setStoreId($storeId);
|
| 66 |
|
| 67 |
+
$isConfigurable = $product
|
| 68 |
+
->load($productId)
|
| 69 |
+
->isConfigurable();
|
| 70 |
|
| 71 |
// Only allow certain attributes to be set, if missing product will not be changed.
|
| 72 |
$data = array_intersect_key(
|
| 73 |
$request->getPost(),
|
| 74 |
+
$helper->getEditables($product)
|
| 75 |
);
|
| 76 |
+
|
| 77 |
+
if (isset($data['qty'])) {
|
| 78 |
+
if (!$isConfigurable)
|
| 79 |
+
$qty = $data['qty'];
|
| 80 |
+
|
| 81 |
+
unset($data['qty']);
|
| 82 |
}
|
| 83 |
|
| 84 |
//Find all attributes which value was changed in the editor by comparing
|
| 94 |
if ($product->getData($code) != $value)
|
| 95 |
$changeAttrs[$code] = true;
|
| 96 |
|
| 97 |
+
if (isset($qty)) {
|
| 98 |
+
$qty = (float) $qty;
|
| 99 |
|
| 100 |
$data['stock_data'] = array(
|
| 101 |
'qty'
|
| 109 |
);
|
| 110 |
}
|
| 111 |
|
| 112 |
+
if ($changeAttrs || isset($qty)) {
|
| 113 |
$product->addData($data);
|
| 114 |
|
| 115 |
+
if ($storeId !== false)
|
| 116 |
+
$this->_unsetValues($product, $changeAttrs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
|
| 118 |
$product->save();
|
| 119 |
|
| 120 |
+
if ($isConfigurable)
|
| 121 |
+
$this->_copyDataToSimpleProducts($product, $changeAttrs, $storeId);
|
| 122 |
+
|
| 123 |
//Reset store to be neat
|
| 124 |
Mage::app()->setCurrentStore($storeId);
|
| 125 |
}
|
| 126 |
}
|
| 127 |
|
| 128 |
+
//Always show same page, even if nothing has changed
|
| 129 |
$this->_redirectUrl($product->setData('url', null)->getProductUrl());
|
| 130 |
}
|
| 131 |
|
| 132 |
+
/**
|
| 133 |
+
* Set value of not changed attributes to false to prevents from copying
|
| 134 |
+
* attribute's values to current scope if user selected Current store
|
| 135 |
+
* option of Save edits to setting in admin interface
|
| 136 |
+
*
|
| 137 |
+
* Filter out following attributes:
|
| 138 |
+
* - Gallery attr (is a complex attr with it's own editor)
|
| 139 |
+
* - Global (setting value of global attr to false removes it globally)
|
| 140 |
+
* - Non-visible (non-visible attributes can't be edited directly)
|
| 141 |
+
* - Without input field (this attributes can'be edited directly)
|
| 142 |
+
*
|
| 143 |
+
* Filtering rules are taken from:
|
| 144 |
+
* - Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Attributes::_prepareForm()
|
| 145 |
+
* - Mage_Adminhtml_Block_Widget_Form::_setFieldset()
|
| 146 |
+
*
|
| 147 |
+
* @param Mage_Catalog_Model_Product $product Product
|
| 148 |
+
* @param array $changed Key-based list of updated attributes
|
| 149 |
+
*/
|
| 150 |
+
protected function _unsetValues ($product, $changed) {
|
| 151 |
+
foreach ($product->getAttributes() as $code => $attr) {
|
| 152 |
+
$allow = $code != 'gallery'
|
| 153 |
+
&& $attr->getIsGlobal()
|
| 154 |
+
!= Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL
|
| 155 |
+
&& $attr->getIsVisible()
|
| 156 |
+
&& $attr->getFrontend()->getInputType();
|
| 157 |
+
|
| 158 |
+
if (!$allow || isset($changed[$code]))
|
| 159 |
+
continue;
|
| 160 |
+
|
| 161 |
+
$product
|
| 162 |
+
->setData($code, false)
|
| 163 |
+
->setOrigData($code, false);
|
| 164 |
+
}
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
/**
|
| 168 |
+
* Copy data from configurable product to it associated
|
| 169 |
+
* simple products
|
| 170 |
+
*
|
| 171 |
+
* @param Mage_Catalog_Model_Product $configurable Configurable product
|
| 172 |
+
* @param array $changed Key-based list of updated attributes
|
| 173 |
+
* @param int|bool $storeId Current store ID
|
| 174 |
+
*/
|
| 175 |
+
protected function _copyDataToSimpleProducts ($configurable,
|
| 176 |
+
$changed,
|
| 177 |
+
$storeId = false)
|
| 178 |
+
{
|
| 179 |
+
if (!$data = $this->_getDataForCopying($configurable, $changed))
|
| 180 |
+
return;
|
| 181 |
+
|
| 182 |
+
$childrenIds = Mage::getModel('catalog/product_type_configurable')
|
| 183 |
+
->getUsedProductIds($configurable);
|
| 184 |
+
|
| 185 |
+
if (!$childrenIds)
|
| 186 |
+
return;
|
| 187 |
+
|
| 188 |
+
//Merge data from parent product to children and save them
|
| 189 |
+
foreach ($childrenIds as $childId) {
|
| 190 |
+
$child = Mage::getModel('catalog/product')
|
| 191 |
+
->setStoreId($storeId)
|
| 192 |
+
->load($childId)
|
| 193 |
+
->addData($data);
|
| 194 |
+
|
| 195 |
+
if ($storeId !== false)
|
| 196 |
+
$this->_unsetValues($child, $data);
|
| 197 |
+
|
| 198 |
+
$child->save();
|
| 199 |
+
}
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
/**
|
| 203 |
+
* Get data from configurable product for updated attributes and only selected
|
| 204 |
+
* attributes on the extension settings
|
| 205 |
+
*
|
| 206 |
+
* @param $configurable Configurable product
|
| 207 |
+
* @return array|null Data for copying into associated simple products
|
| 208 |
+
*/
|
| 209 |
+
protected function _getDataForCopying ($configurable, $changed) {
|
| 210 |
+
return array_intersect_key(
|
| 211 |
+
$configurable->getData(),
|
| 212 |
+
$changed,
|
| 213 |
+
Mage::helper('productivity/attribute')->getReplicables($configurable)
|
| 214 |
+
);
|
| 215 |
+
}
|
| 216 |
}
|
| 217 |
|
app/code/community/MVentory/Productivity/etc/config.xml
CHANGED
|
@@ -62,9 +62,13 @@
|
|
| 62 |
<models>
|
| 63 |
<productivity>
|
| 64 |
<class>MVentory_Productivity_Model</class>
|
| 65 |
-
<resourceModel>
|
| 66 |
</productivity>
|
| 67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
<catalog>
|
| 69 |
<rewrite>
|
| 70 |
<category>MVentory_Productivity_Model_Mage_Catalog_Category</category>
|
|
@@ -217,6 +221,9 @@
|
|
| 217 |
<productivity>
|
| 218 |
<product>
|
| 219 |
<save_scope>2</save_scope>
|
|
|
|
|
|
|
|
|
|
| 220 |
</product>
|
| 221 |
</productivity>
|
| 222 |
</default>
|
| 62 |
<models>
|
| 63 |
<productivity>
|
| 64 |
<class>MVentory_Productivity_Model</class>
|
| 65 |
+
<resourceModel>productivity_resources</resourceModel>
|
| 66 |
</productivity>
|
| 67 |
|
| 68 |
+
<productivity_resources>
|
| 69 |
+
<class>MVentory_Productivity_Model_Resource</class>
|
| 70 |
+
</productivity_resources>
|
| 71 |
+
|
| 72 |
<catalog>
|
| 73 |
<rewrite>
|
| 74 |
<category>MVentory_Productivity_Model_Mage_Catalog_Category</category>
|
| 221 |
<productivity>
|
| 222 |
<product>
|
| 223 |
<save_scope>2</save_scope>
|
| 224 |
+
|
| 225 |
+
<!-- '.' - Don't copy any attributes -->
|
| 226 |
+
<copy_attrs>.</copy_attrs>
|
| 227 |
</product>
|
| 228 |
</productivity>
|
| 229 |
</default>
|
app/code/community/MVentory/Productivity/etc/system.xml
CHANGED
|
@@ -58,10 +58,18 @@
|
|
| 58 |
<fields>
|
| 59 |
<flatten_tree translate="label comment tooltip">
|
| 60 |
<label>Flatten categories tree</label>
|
| 61 |
-
<comment>
|
| 62 |
-
<tooltip>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
<frontend_type>select</frontend_type>
|
| 64 |
-
<source_model>
|
| 65 |
|
| 66 |
<show_in_default>1</show_in_default>
|
| 67 |
<show_in_website>1</show_in_website>
|
|
@@ -123,6 +131,36 @@
|
|
| 123 |
|
| 124 |
<sort_order>1</sort_order>
|
| 125 |
</save_scope>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
</fields>
|
| 127 |
</product>
|
| 128 |
|
|
@@ -151,6 +189,17 @@
|
|
| 151 |
</url>
|
| 152 |
</fields>
|
| 153 |
</analytics>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
</groups>
|
| 155 |
</productivity>
|
| 156 |
</sections>
|
| 58 |
<fields>
|
| 59 |
<flatten_tree translate="label comment tooltip">
|
| 60 |
<label>Flatten categories tree</label>
|
| 61 |
+
<comment>Behavior of categories tree</comment>
|
| 62 |
+
<tooltip>
|
| 63 |
+
<![CDATA[
|
| 64 |
+
<ul class="productivity-tooltip-list">
|
| 65 |
+
<li>No - default Magento behavior</li>
|
| 66 |
+
<li>Flatten single branch paths - Do not show parents with only a single subcategory to show the subcategory in its place. E.g. Cat A only one subcategory Cat AA. Category Cat AA will show in place of Cat A</li>
|
| 67 |
+
<li>Show children of hidden parents - If Cat A has "Include in Navigation Menu" set to NO then exclude it, but show it's subcategories at the level of Cat A</li>
|
| 68 |
+
</ul>
|
| 69 |
+
]]>
|
| 70 |
+
</tooltip>
|
| 71 |
<frontend_type>select</frontend_type>
|
| 72 |
+
<source_model>productivity/setting_source_flattentype</source_model>
|
| 73 |
|
| 74 |
<show_in_default>1</show_in_default>
|
| 75 |
<show_in_website>1</show_in_website>
|
| 131 |
|
| 132 |
<sort_order>1</sort_order>
|
| 133 |
</save_scope>
|
| 134 |
+
|
| 135 |
+
<editable_attr translate="label comment tooltip">
|
| 136 |
+
<label>Editable fields</label>
|
| 137 |
+
<comment>One attribute code per line or leave empty to allow all.</comment>
|
| 138 |
+
<tooltip>Only listed attributes can be edited via the front end. Leave empty to allow all attributes to be edited. Use qty code for product quantity.</tooltip>
|
| 139 |
+
<frontend_type>textarea</frontend_type>
|
| 140 |
+
|
| 141 |
+
<show_in_default>1</show_in_default>
|
| 142 |
+
<show_in_website>1</show_in_website>
|
| 143 |
+
<show_in_store>1</show_in_store>
|
| 144 |
+
|
| 145 |
+
<sort_order>2</sort_order>
|
| 146 |
+
</editable_attr>
|
| 147 |
+
|
| 148 |
+
<copy_attrs>
|
| 149 |
+
<label>Copy from configurable to simple products</label>
|
| 150 |
+
<comment>One attribute code per line to copy into associated products, blank for all or . for none.</comment>
|
| 151 |
+
<tooltip><![CDATA[Changes in configurable products are always saved in the product itself, but the listed attributes can also be copied into all associated simple products.<br /><br />Leave blank to copy all attributes, except quantity.<br /><br />Use . or any other string that is not an attribute name to avoid copying any of the values.]]></tooltip>
|
| 152 |
+
<frontend_type>textarea</frontend_type>
|
| 153 |
+
|
| 154 |
+
<!--
|
| 155 |
+
<source_model>productivity/setting_source_copyattrs</source_model>
|
| 156 |
+
-->
|
| 157 |
+
|
| 158 |
+
<show_in_default>1</show_in_default>
|
| 159 |
+
<show_in_website>1</show_in_website>
|
| 160 |
+
<show_in_store>1</show_in_store>
|
| 161 |
+
|
| 162 |
+
<sort_order>3</sort_order>
|
| 163 |
+
</copy_attrs>
|
| 164 |
</fields>
|
| 165 |
</product>
|
| 166 |
|
| 189 |
</url>
|
| 190 |
</fields>
|
| 191 |
</analytics>
|
| 192 |
+
|
| 193 |
+
<build_info>
|
| 194 |
+
<frontend_model>productivity/config_buildinfo</frontend_model>
|
| 195 |
+
|
| 196 |
+
<show_in_default>1</show_in_default>
|
| 197 |
+
<show_in_website>1</show_in_website>
|
| 198 |
+
<show_in_store>1</show_in_store>
|
| 199 |
+
|
| 200 |
+
<sort_order>5</sort_order>
|
| 201 |
+
</build_info>
|
| 202 |
+
|
| 203 |
</groups>
|
| 204 |
</productivity>
|
| 205 |
</sections>
|
app/design/adminhtml/default/default/template/productivity/config/build-info.phtml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* NOTICE OF LICENSE
|
| 5 |
+
*
|
| 6 |
+
* This source file is subject to the Creative Commons License BY-NC-ND.
|
| 7 |
+
* NonCommercial — You may not use the material for commercial purposes.
|
| 8 |
+
* NoDerivatives — If you remix, transform, or build upon the material,
|
| 9 |
+
* you may not distribute the modified material.
|
| 10 |
+
* See the full license at http://creativecommons.org/licenses/by-nc-nd/4.0/
|
| 11 |
+
*
|
| 12 |
+
* See http://mventory.com/legal/licensing/ for other licensing options.
|
| 13 |
+
*
|
| 14 |
+
* @package MVentory/Productivity
|
| 15 |
+
* @copyright Copyright (c) 2015 mVentory Ltd. (http://mventory.com)
|
| 16 |
+
* @license http://creativecommons.org/licenses/by-nc-nd/4.0/
|
| 17 |
+
*/
|
| 18 |
+
|
| 19 |
+
?>
|
| 20 |
+
|
| 21 |
+
Build version: 903ba0a
|
| 22 |
+
<BR/>Build date: 01/02/2015 08:22 UTC
|
app/design/frontend/base/default/layout/productivity.xml
CHANGED
|
@@ -21,6 +21,8 @@
|
|
| 21 |
</productivity_rss_product_latest>
|
| 22 |
|
| 23 |
<productivity_panel>
|
|
|
|
|
|
|
| 24 |
<reference name="head">
|
| 25 |
<action method="addCss">
|
| 26 |
<stylesheet>productivity/css/styles.css</stylesheet>
|
|
@@ -33,7 +35,7 @@
|
|
| 33 |
</productivity_panel>
|
| 34 |
|
| 35 |
<catalog_product_view>
|
| 36 |
-
<update handle="
|
| 37 |
|
| 38 |
<reference name="head">
|
| 39 |
<action method="addJs">
|
|
@@ -86,10 +88,6 @@
|
|
| 86 |
<update handle="productivity_panel" />
|
| 87 |
</catalog_category_layered>
|
| 88 |
|
| 89 |
-
<catalog_product_view>
|
| 90 |
-
<update handle="productivity_panel" />
|
| 91 |
-
</catalog_product_view>
|
| 92 |
-
|
| 93 |
<cms_page>
|
| 94 |
<update handle="productivity_panel" />
|
| 95 |
</cms_page>
|
| 21 |
</productivity_rss_product_latest>
|
| 22 |
|
| 23 |
<productivity_panel>
|
| 24 |
+
<update handle="jquery" />
|
| 25 |
+
|
| 26 |
<reference name="head">
|
| 27 |
<action method="addCss">
|
| 28 |
<stylesheet>productivity/css/styles.css</stylesheet>
|
| 35 |
</productivity_panel>
|
| 36 |
|
| 37 |
<catalog_product_view>
|
| 38 |
+
<update handle="productivity_panel" />
|
| 39 |
|
| 40 |
<reference name="head">
|
| 41 |
<action method="addJs">
|
| 88 |
<update handle="productivity_panel" />
|
| 89 |
</catalog_category_layered>
|
| 90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
<cms_page>
|
| 92 |
<update handle="productivity_panel" />
|
| 93 |
</cms_page>
|
app/design/frontend/base/default/template/productivity/panel.phtml
CHANGED
|
@@ -74,6 +74,10 @@ if ($_type == 'product') {
|
|
| 74 |
|
| 75 |
<?php endif; ?>
|
| 76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
<li>
|
| 78 |
<a title="<?php echo $this->__('View products with no images'); ?>" href="<?php echo $this->_getWithoutImagesLink() ?>"><?php echo $this->__('No-image products'); ?></a>
|
| 79 |
</li>
|
|
@@ -99,10 +103,33 @@ if ($_type == 'product') {
|
|
| 99 |
</ul>
|
| 100 |
</div>
|
| 101 |
|
| 102 |
-
<?php if ($_type == 'product'): ?>
|
| 103 |
<div id="productivity-panel-content">
|
| 104 |
<div id="productivity-panel-content-inner" class="clearer">
|
| 105 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
<div id="productivity-uploader">
|
| 107 |
<div id="productivity-uploader-element"></div>
|
| 108 |
|
|
@@ -124,21 +151,20 @@ if ($_type == 'product') {
|
|
| 124 |
<?php echo $this->getEditForm()->setHtmlIdPrefix('productivity_edit_form_')->toHtml() ?>
|
| 125 |
</div>
|
| 126 |
</div>
|
|
|
|
| 127 |
|
| 128 |
</div>
|
| 129 |
</div>
|
| 130 |
-
<?php endif; ?>
|
| 131 |
|
| 132 |
</div>
|
| 133 |
|
| 134 |
-
<?php if ($_type == 'product'): ?>
|
| 135 |
-
|
| 136 |
<script type="text/javascript">
|
| 137 |
//<