diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 257cc4ed0f62fedeefb700ee523caa08fddc9ca0..e3b499c3bc77121971916e7b1f56befb2a53d6a3 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -1,3 +1,26 @@ +2.0.0.0-dev32 +============= +* Improved product edit workflow: + * Introduced Category Assignment control on "General" tab + * Eliminated attribute preselection screen + * Base image assignment control moved to "General" tab + * Base inventory attributes controls displayed on "General" tab. Values of the attributes are synchronized between "General" and "Inventory" tabs +* Improved static code analysis tests to verify existence of paths specified in white/black lists +* Reduced memory usage by integration tests by automatic cleaning properties of test classes +* Added migration tool `dev/tools/migration/themes_view.php` for replacing old `{{skin}}` with new `{{view}}` placeholders +* Changed handling of exceptions, produced by non-existing view files, to not break whole page +* Removed empty locale files +* Bug fixes: + * Page with tracking information absent, if shipping labels integration is used + * Category is not displayed on frontend with "Use Flat Catalog Category" option enabled + * Exception on "Coupons Usage Report" page after upgrade from Magento 1.x + * Exception on "Most Viewed Products" page after upgrade from Magento 1.x + * Quick search produces error, if searching for a product with an attribute that has "Use In Search Results Layered Navigation" option set to "Yes" + * Exception on "Add/Edit Customer" page when Magento profiler with html output is enabled + * Can't duplicate downloadable product with sample file attached + * Product Type dropdown on "Add Product" page doesn't work in IE9 + * Various issues related to adding/editing product + 2.0.0.0-dev31 ============= * Themes: diff --git a/app/Mage.php b/app/Mage.php index 166c83887b5d1514f0e275eeb71427a2ed10ef4a..6a78b1cc14ce2a468f35d497fd0c11718b99345d 100644 --- a/app/Mage.php +++ b/app/Mage.php @@ -170,7 +170,7 @@ final class Mage 'revision' => '0', 'patch' => '0', 'stability' => 'dev', - 'number' => '31', + 'number' => '32', ); } diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php index b9e4fb7f9db3b1670d2dbff6593df4aa8d56001a..acf14a7f5a01ded34e21d4d0147fc416a16f0461 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php @@ -30,7 +30,7 @@ * * @category Mage * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> + * @author Magento Core Team <core@magentocommerce.com> */ class Mage_Adminhtml_Block_Catalog_Category_Tree extends Mage_Adminhtml_Block_Catalog_Category_Abstract { @@ -104,6 +104,57 @@ class Mage_Adminhtml_Block_Catalog_Category_Tree extends Mage_Adminhtml_Block_Ca return $collection; } + /** + * Retrieve list of categories with name containing $namePart and their parents + * + * @param string $namePart + * @return string + */ + public function getSuggestedCategoriesJson($namePart) + { + $storeId = $this->getRequest()->getParam('store', $this->_getDefaultStoreId()); + + /* @var $collection Mage_Catalog_Model_Resource_Category_Collection */ + $collection = Mage::getModel('Mage_Catalog_Model_Category')->getCollection(); + + $matchingNamesCollection = clone $collection; + $matchingNamesCollection->addAttributeToFilter('name', array('like' => "%{$namePart}%")) + ->addAttributeToSelect('path') + ->setStoreId($storeId); + + $shownCategoriesIds = array(); + foreach ($matchingNamesCollection as $category) { + foreach (explode('/', $category->getPath()) as $parentId) { + $shownCategoriesIds[$parentId] = 1; + } + } + + $collection->addAttributeToFilter('entity_id', array('in' => array_keys($shownCategoriesIds))) + ->addAttributeToSelect(array('name', 'is_active', 'parent_id')) + ->setStoreId($storeId); + + $categoryById = array( + Mage_Catalog_Model_Category::TREE_ROOT_ID => array( + 'id' => Mage_Catalog_Model_Category::TREE_ROOT_ID, + 'children' => array() + ) + ); + foreach ($collection as $category) { + foreach (array($category->getId(), $category->getParentId()) as $categoryId) { + if (!isset($categoryById[$categoryId])) { + $categoryById[$categoryId] = array('id' => $categoryId, 'children' => array()); + } + } + $categoryById[$category->getId()]['is_active'] = $category->getIsActive(); + $categoryById[$category->getId()]['name'] = $category->getName(); + $categoryById[$category->getParentId()]['children'][] = &$categoryById[$category->getId()]; + } + + return Mage::helper('Mage_Core_Helper_Data')->jsonEncode( + $categoryById[Mage_Catalog_Model_Category::TREE_ROOT_ID]['children'] + ); + } + public function getAddRootButtonHtml() { return $this->getChildHtml('add_root_button'); @@ -173,7 +224,9 @@ class Mage_Adminhtml_Block_Catalog_Category_Tree extends Mage_Adminhtml_Block_Ca public function getTreeJson($parenNodeCategory=null) { $rootArray = $this->_getNodeJson($this->getRoot($parenNodeCategory)); - $json = Mage::helper('Mage_Core_Helper_Data')->jsonEncode(isset($rootArray['children']) ? $rootArray['children'] : array()); + $json = Mage::helper('Mage_Core_Helper_Data')->jsonEncode( + isset($rootArray['children']) ? $rootArray['children'] : array() + ); return $json; } diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php index d983531284a17bf57a98a92a108ce8909d51fe7b..2aa6aa2b60f16d0c8da4415a97b76387e812f32f 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php @@ -74,15 +74,12 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit extends Mage_Adminhtml_Block_Wid } if (!$this->getProduct()->isReadonly()) { - $this->setChild('change_attribute_set_button', - $this->getLayout()->createBlock( - 'Mage_Adminhtml_Block_Widget_Button', - $this->getNameInLayout() . '-change-attribute-set' - )->setData(array( + if (!$this->getProduct()->isConfigurable() || !$this->getIsConfigured()) { + $this->addChild('change_attribute_set_button', 'Mage_Adminhtml_Block_Widget_Button', array( 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Change Attribute Set'), 'onclick' => "jQuery('#attribute-set-info').dialog('open');" - )) - ); + )); + } $this->addChild('reset_button', 'Mage_Adminhtml_Block_Widget_Button', array( 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Reset'), diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php index f23247e207d50c4da1cdf27a1fb71f9d102cab9b..0f37e1b31913794b13a93a2403b802491eb255e9 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php @@ -45,7 +45,8 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Action_Attribute_Tab_Attributes protected function _prepareForm() { $this->setFormExcludedFieldList(array( - 'tier_price','gallery', 'media_gallery', 'recurring_profile', 'group_price' + 'tier_price', 'gallery', 'media_gallery', 'recurring_profile', 'group_price', + 'quantity_and_stock_status' )); Mage::dispatchEvent('adminhtml_catalog_product_form_prepare_excluded_field_list', array('object'=>$this)); diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Categories.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Categories.php deleted file mode 100644 index 6036e58c6b879f6e9a9e3e798daa3c1e7ce64ae5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Categories.php +++ /dev/null @@ -1,286 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category Mage - * @package Mage_Adminhtml - * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Product categories tab - * - * @category Mage - * @package Mage_Adminhtml - * @author Magento Core Team <core@magentocommerce.com> - */ -class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Categories extends Mage_Adminhtml_Block_Catalog_Category_Tree -{ - protected $_categoryIds; - protected $_selectedNodes = null; - - protected $_template = 'catalog/product/edit/categories.phtml'; - - /** - * Retrieve currently edited product - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - return Mage::registry('current_product'); - } - - /** - * Checks when this block is readonly - * - * @return boolean - */ - public function isReadonly() - { - return $this->getProduct()->getCategoriesReadonly(); - } - - /** - * Return array with category IDs which the product is assigned to - * - * @return array - */ - protected function getCategoryIds() - { - return $this->getProduct()->getCategoryIds(); - } - - /** - * Forms string out of getCategoryIds() - * - * @return string - */ - public function getIdsString() - { - return implode(',', $this->getCategoryIds()); - } - - /** - * Returns root node and sets 'checked' flag (if necessary) - * - * @return Varien_Data_Tree_Node - */ - public function getRootNode() - { - $root = $this->getRoot(); - if ($root && in_array($root->getId(), $this->getCategoryIds())) { - $root->setChecked(true); - } - return $root; - } - - /** - * Returns root node - * - * @param Mage_Catalog_Model_Category|null $parentNodeCategory - * @param int $recursionLevel - * @return Varien_Data_Tree_Node - */ - public function getRoot($parentNodeCategory = null, $recursionLevel = 3) - { - if (!is_null($parentNodeCategory) && $parentNodeCategory->getId()) { - return $this->getNode($parentNodeCategory, $recursionLevel); - } - $root = Mage::registry('root'); - if (is_null($root)) { - $storeId = (int) $this->getRequest()->getParam('store'); - - if ($storeId) { - $store = Mage::app()->getStore($storeId); - $rootId = $store->getRootCategoryId(); - } - else { - $rootId = Mage_Catalog_Model_Category::TREE_ROOT_ID; - } - - $ids = $this->getSelectedCategoriesPathIds($rootId); - $tree = Mage::getResourceSingleton('Mage_Catalog_Model_Resource_Category_Tree') - ->loadByIds($ids, false, false); - - if ($this->getCategory()) { - $tree->loadEnsuredNodes($this->getCategory(), $tree->getNodeById($rootId)); - } - - $tree->addCollectionData($this->getCategoryCollection()); - - $root = $tree->getNodeById($rootId); - - if ($root && $rootId != Mage_Catalog_Model_Category::TREE_ROOT_ID) { - $root->setIsVisible(true); - if ($this->isReadonly()) { - $root->setDisabled(true); - } - } - elseif($root && $root->getId() == Mage_Catalog_Model_Category::TREE_ROOT_ID) { - $root->setName(Mage::helper('Mage_Catalog_Helper_Data')->__('Root')); - } - - Mage::register('root', $root); - } - - return $root; - } - - /** - * Returns array with configuration of current node - * - * @param Varien_Data_Tree_Node $node - * @param int $level How deep is the node in the tree - * @return array - */ - protected function _getNodeJson($node, $level = 1) - { - $item = parent::_getNodeJson($node, $level); - - if ($this->_isParentSelectedCategory($node)) { - $item['expanded'] = true; - } - - if (in_array($node->getId(), $this->getCategoryIds())) { - $item['checked'] = true; - } - - if ($this->isReadonly()) { - $item['disabled'] = true; - } - - return $item; - } - - /** - * Returns whether $node is a parent (not exactly direct) of a selected node - * - * @param Varien_Data_Tree_Node $node - * @return bool - */ - protected function _isParentSelectedCategory($node) - { - $result = false; - // Contains string with all category IDs of children (not exactly direct) of the node - $allChildren = $node->getAllChildren(); - if ($allChildren) { - $selectedCategoryIds = $this->getCategoryIds(); - $allChildrenArr = explode(',', $allChildren); - for ($i = 0, $cnt = count($selectedCategoryIds); $i < $cnt; $i++) { - $isSelf = $node->getId() == $selectedCategoryIds[$i]; - if (!$isSelf && in_array($selectedCategoryIds[$i], $allChildrenArr)) { - $result = true; - break; - } - } - } - - return $result; - } - - /** - * Returns array with nodes those are selected (contain current product) - * - * @return array - */ - protected function _getSelectedNodes() - { - if ($this->_selectedNodes === null) { - $this->_selectedNodes = array(); - $root = $this->getRoot(); - foreach ($this->getCategoryIds() as $categoryId) { - if ($root) { - $this->_selectedNodes[] = $root->getTree()->getNodeById($categoryId); - } - } - } - - return $this->_selectedNodes; - } - - /** - * Returns JSON-encoded array of category children - * - * @param int $categoryId - * @return string - */ - public function getCategoryChildrenJson($categoryId) - { - $category = Mage::getModel('Mage_Catalog_Model_Category')->load($categoryId); - $node = $this->getRoot($category, 1)->getTree()->getNodeById($categoryId); - - if (!$node || !$node->hasChildren()) { - return '[]'; - } - - $children = array(); - foreach ($node->getChildren() as $child) { - $children[] = $this->_getNodeJson($child); - } - - return Mage::helper('Mage_Core_Helper_Data')->jsonEncode($children); - } - - /** - * Returns URL for loading tree - * - * @param null $expanded - * @return string - */ - public function getLoadTreeUrl($expanded = null) - { - return $this->getUrl('*/*/categoriesJson', array('_current' => true)); - } - - /** - * Return distinct path ids of selected categories - * - * @param mixed $rootId Root category Id for context - * @return array - */ - public function getSelectedCategoriesPathIds($rootId = false) - { - $ids = array(); - $categoryIds = $this->getCategoryIds(); - if (empty($categoryIds)) { - return array(); - } - $collection = Mage::getResourceModel('Mage_Catalog_Model_Resource_Category_Collection'); - - if ($rootId) { - $collection->addFieldToFilter('parent_id', $rootId); - } else { - $collection->addFieldToFilter('entity_id', array('in'=>$categoryIds)); - } - - foreach ($collection as $item) { - if ($rootId && !in_array($rootId, $item->getPathIds())) { - continue; - } - foreach ($item->getPathIds() as $id) { - if (!in_array($id, $ids)) { - $ids[] = $id; - } - } - } - return $ids; - } -} diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php index 40252148a040573854785b7a80b2e60261696fad..7409fbe3ef21635f3cb9870ddee710b80f3bdaf4 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php @@ -110,6 +110,7 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config extends Mage_Ad 'class' => 'add', 'onclick' => 'superProduct.createEmptyProduct()' )); + $this->addChild('super_settings', 'Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Settings'); if ($this->_getProduct()->getId()) { $this->setChild('simple', @@ -356,4 +357,16 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config extends Mage_Ad return !Mage::helper('Mage_Catalog_Helper_Data')->isPriceGlobal() && $this->_getProduct()->getStoreId(); } + + /** + * Get list of used attributes + * + * @return array + */ + public function getSelectedAttributes() + { + return array_filter( + $this->_getProduct()->getTypeInstance()->getUsedProductAttributes($this->_getProduct()) + ); + } } diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php index 2d12e501402a1a99b796fda26123d2e111482b2b..2ac3036dfaf4e4c7cbc1560cdd6178fa718c993c 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php @@ -41,30 +41,17 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Settings extends Mage_ protected function _prepareLayout() { $onclick = "setSuperSettings('" . $this->getContinueUrl() . "','attribute-checkbox', 'attributes')"; - $this->addChild('continue_button', 'Mage_Adminhtml_Block_Widget_Button', array( - 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Continue'), - 'onclick' => $onclick, - 'class' => 'save' + $this->addChild('continue_button', 'Mage_Backend_Block_Widget_Button', array( + 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Continue'), + 'onclick' => $onclick, + 'class' => 'save', )); - $backButton = $this->getLayout()->createBlock('Mage_Adminhtml_Block_Widget_Button') - ->setData(array( - 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Back'), - 'onclick' => "setLocation('".$this->getBackUrl()."')", - 'class' => 'back' - )); - - $this->setChild('back_button', $backButton); - - $this->setChild('change_attribute_set_button', - $this->getLayout()->createBlock( - 'Mage_Adminhtml_Block_Widget_Button', - $this->getNameInLayout() . '-change-attribute-set' - )->setData(array( - 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Change Attribute Set'), - 'onclick' => "jQuery('#attribute-set-info').dialog('open');" - )) - ); + $this->addChild('back_button', 'Mage_Backend_Block_Widget_Button', array( + 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Back'), + 'onclick' => "setLocation('" . $this->getBackUrl() . "')", + 'class' => 'back' + )); parent::_prepareLayout(); } @@ -97,12 +84,8 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Settings extends Mage_ $fieldset->addField('req_text', 'note', array( 'text' => '<ul class="messages"><li class="notice-msg"><ul><li>' - . $this->__('Only attributes with scope "Global", input type "Dropdown" and Use To Create Configurable Product "Yes" are available.') - . '</li></ul></li></ul>' - )); - - $fieldset->addField('change_attribute_set_button', 'note', array( - 'text' => $this->getChildHtml('change_attribute_set_button'), + . $this->__('Only attributes with scope "Global", input type "Dropdown" and Use To Create Configurable Product "Yes" are available.') + . '</li></ul></li></ul>' )); $hasAttributes = false; @@ -153,7 +136,7 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Settings extends Mage_ */ public function getContinueUrl() { - return $this->getUrl('*/*/new', array( + return $this->getUrl($this->_getProduct()->getId() ? '*/*/edit' : '*/*/new', array( '_current' => true, 'attributes' => '{{attributes}}' )); diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php index 5da169c93b0de5009ec1d8ae45a0af3cda391bd2..a88b2cac04daf3a55efb56f9f0c8c3aa55ee5f01 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php @@ -102,12 +102,6 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs extends Mage_Adminhtml_Bloc )); } - $this->addTab('categories', array( - 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Categories'), - 'url' => $this->getUrl('*/*/categories', array('_current' => true)), - 'class' => 'ajax', - )); - $this->addTab('related', array( 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('Related Products'), 'url' => $this->getUrl('*/*/related', array('_current' => true)), diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/BaseImage.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/BaseImage.php new file mode 100644 index 0000000000000000000000000000000000000000..27614be23d971ec532894196d23138bc47c5ba9e --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/BaseImage.php @@ -0,0 +1,179 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Adminhtml + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Product form image field helper + * + * @category Mage + * @package Mage_Adminhtml + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Adminhtml_Block_Catalog_Product_Helper_Form_BaseImage extends Varien_Data_Form_Element_Hidden +{ + /** + * Maximum file size to upload in bytes. + * + * @var int + */ + protected $_maxFileSize; + + /** + * Media Uploader instance + * + * @var Mage_Adminhtml_Block_Media_Uploader + */ + protected $_mediaUploader; + + /** + * Model Url instance + * + * @var Mage_Backend_Model_Url + */ + protected $_url; + + /** + * Media Config instance + * + * @var Mage_Catalog_Model_Product_Media_Config + */ + protected $_mediaConfig; + + /** + * Design Package instance + * + * @var Mage_Core_Model_Design_Package + */ + protected $_design; + + /** + * Data instance + * + * @var Mage_Core_Helper_Data + */ + protected $_helperData; + + /** + * Constructor + * + * @param array $attributes + */ + public function __construct(array $attributes = array()) + { + parent::__construct($attributes); + + $this->_mediaUploader = isset($attributes['mediaUploader']) ? $attributes['mediaUploader'] + : Mage::getSingleton('Mage_Adminhtml_Block_Media_Uploader'); + $this->_url = isset($attributes['url']) ? $attributes['url'] + : Mage::getModel('Mage_Backend_Model_Url'); + $this->_mediaConfig = isset($attributes['mediaConfig']) ? $attributes['mediaConfig'] + : Mage::getSingleton('Mage_Catalog_Model_Product_Media_Config'); + $this->_design = isset($attributes['design']) ? $attributes['design'] + : Mage::getSingleton('Mage_Core_Model_Design_Package'); + $this->_helperData = isset($attributes['helperData']) ? $attributes['helperData'] + : Mage::helper('Mage_Core_Helper_Data'); + + $this->_maxFileSize = $this->_getFileMaxSize(); + } + + /** + * Return element html code + * + * @return string + */ + public function getElementHtml() + { + $imageUrl = $this->_helperData->escapeHtml($this->_getImageUrl($this->getValue())); + $htmlId = $this->_helperData->escapeHtml($this->getHtmlId()); + $uploadUrl = $this->_helperData->escapeHtml($this->_getUploadUrl()); + + $html = '<input id="' . $htmlId .'_upload" type="file" name="image" ' + . 'data-url="' . $uploadUrl . '" style="display: none;" />' + . parent::getElementHtml() + . '<img align="left" src="' . $imageUrl . '" id="' . $htmlId . '_image"' + . ' title="' . $imageUrl . '" alt="' . $imageUrl . '" class="base-image-uploader"' + . ' onclick="jQuery(\'#' . $htmlId . '_upload\').trigger(\'click\')"/>'; + $html .= $this->_getJs(); + + return $html; + } + + /** + * Get js for image uploader + * + * @return string + */ + protected function _getJs() + { + return "<script>/* <![CDATA[ */" + . "jQuery(function(){" + . "BaseImageUploader({$this->_helperData->jsonEncode($this->getHtmlId())}, " + . "{$this->_helperData->jsonEncode($this->_maxFileSize)});" + . " });" + . "/*]]>*/</script>"; + } + + /** + * Get full url for image + * + * @param string $imagePath + * + * @return string + */ + protected function _getImageUrl($imagePath) + { + if (!in_array($imagePath, array(null, 'no_selection', '/'))) { + if (pathinfo($imagePath, PATHINFO_EXTENSION) == 'tmp') { + $imageUrl = $this->_mediaConfig->getTmpMediaUrl(substr($imagePath, 0, -4)); + } else { + $imageUrl = $this->_mediaConfig->getMediaUrl($imagePath); + } + } else { + $imageUrl = $this->_design->getViewFileUrl('Mage_Adminhtml::images/image-placeholder.png'); + } + + return $imageUrl; + } + + /** + * Get url to upload files + * + * @return string + */ + protected function _getUploadUrl() + { + return $this->_url->getUrl('*/catalog_product_gallery/upload'); + } + + /** + * Get maximum file size to upload in bytes + * + * @return int + */ + protected function _getFileMaxSize() + { + return $this->_mediaUploader->getDataMaxSizeInBytes(); + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Category.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Category.php new file mode 100644 index 0000000000000000000000000000000000000000..24b4519307b14a77a8b6caaa20b39a68c845b8ef --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Category.php @@ -0,0 +1,116 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Adminhtml + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Product form category field helper + * + * @category Mage + * @package Mage_Adminhtml + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Category extends Varien_Data_Form_Element_Multiselect +{ + /** + * Get values for select + * @return array + */ + public function getValues() + { + $collection = $this->_getCategoriesCollection(); + $values = $this->getValue(); + if (!is_array($values)) { + $values = explode(',', $values); + } + $collection->addAttributeToSelect('name'); + $collection->addIdFilter($values); + + $options = array(); + + foreach ($collection as $category) { + $options[] = array( + 'label' => $category->getName(), + 'value' => $category->getId() + ); + } + return $options; + } + + /** + * Get categories collection + * @return Mage_Catalog_Model_Resource_Category_Collection + */ + protected function _getCategoriesCollection() + { + return Mage::getResourceModel('Mage_Catalog_Model_Resource_Category_Collection'); + } + + /** + * Get html for element + * + * @return string + */ + public function getElementHtml() + { + return parent::getElementHtml() + . "<script>//<![CDATA[\n jQuery(" + . $this->_getCodeHelper()->jsonEncode('#' . $this->getHtmlId()) + . ").categorySelector(" . $this->_getCodeHelper()->jsonEncode($this->_getSelectorOptions()) . "); + \n//]]></script>"; + } + + /** + * Get selector options + * + * @return array + */ + protected function _getSelectorOptions() + { + return array( + 'url' => $this->_getBackendHelper()->getUrl('adminhtml/catalog_category/suggestCategories'), + ); + } + + /** + * Get backend area helper + * + * @return Mage_Backend_Helper_Data" + */ + protected function _getBackendHelper() + { + return Mage::helper("Mage_Backend_Helper_Data"); + } + + /** + * Get code module helper + * + * @return Mage_Backend_Helper_Data" + */ + protected function _getCodeHelper() + { + return Mage::helper("Mage_Core_Helper_Data"); + } + +} diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php index 9d0563e3b70503344218ad5185e6d167a7a7f2d3..b4eb09a2f797b0cbec4253716b7cd261636e5c2b 100644 --- a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php +++ b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php @@ -50,7 +50,8 @@ class Mage_Adminhtml_Block_Customer_Edit_Tabs extends Mage_Adminhtml_Block_Widge if (Mage::registry('current_customer')->getId()) { $this->addTab('view', array( 'label' => Mage::helper('Mage_Customer_Helper_Data')->__('Customer View'), - 'content' => $this->getLayout()->createBlock('Mage_Adminhtml_Block_Customer_Edit_Tab_View')->toHtml(), + 'content' => $this->getLayout() + ->createBlock('Mage_Adminhtml_Block_Customer_Edit_Tab_View')->toHtml(), 'active' => true )); } @@ -111,29 +112,18 @@ class Mage_Adminhtml_Block_Customer_Edit_Tabs extends Mage_Adminhtml_Block_Widge } $this->_updateActiveTab(); + Magento_Profiler::stop('customer/tabs'); return parent::_beforeToHtml(); } protected function _updateActiveTab() { $tabId = $this->getRequest()->getParam('tab'); - if( $tabId ) { + if ($tabId) { $tabId = preg_replace("#{$this->getId()}_#", '', $tabId); - if($tabId) { + if ($tabId) { $this->setActiveTab($tabId); } } } - - /** - * Processing block html after rendering - * - * @param string $html - * @return string - */ - protected function _afterToHtml($html) - { - Magento_Profiler::stop('customer/tabs'); - return parent::_afterToHtml($html); - } } diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php index 7cda96758f3a4dc80423169735d98aa05ed45254..870841c937e58998df506149ab6149b6464bf682 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php @@ -502,6 +502,16 @@ class Mage_Adminhtml_Catalog_CategoryController extends Mage_Adminhtml_Controlle } } + /** + * Category list suggestion based on already entered symbols + */ + public function suggestCategoriesAction() + { + $this->getResponse()->setBody($this->getLayout()->createBlock('Mage_Adminhtml_Block_Catalog_Category_Tree') + ->getSuggestedCategoriesJson($this->getRequest()->getParam('name_part')) + ); + } + /** * Check if admin has permissions to visit related pages * diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php index 1d8e23604d8b5440ebd0e8d223ac8fab5862254a..2c17b8e73b79991da1ef89d63995256d08cdb86c 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php @@ -133,8 +133,10 @@ class Mage_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Controller $product->addData($data) ->setWebsiteIds($configProduct->getWebsiteIds()); } - if ($product->dataHasChangedFor('attribute_set_id')) { + + if ($setId != $this->_getSession()->getAttributeSetId()) { $this->_initProductSave($product); + $this->_getSession()->setAttributeSetId($setId); } Mage::register('product', $product); @@ -223,7 +225,7 @@ class Mage_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Controller $this->_setActiveMenu('Mage_Catalog::catalog_products'); } - $this->getLayout()->getBlock('head')->setCanLoadExtJs(true); + $this->getLayout()->getBlock('head')->setCanLoadExtJs(false); $block = $this->getLayout()->getBlock('catalog.wysiwyg.js'); if ($block) { @@ -274,7 +276,7 @@ class Mage_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Controller ); } - $this->getLayout()->getBlock('head')->setCanLoadExtJs(true); + $this->getLayout()->getBlock('head')->setCanLoadExtJs(false); $block = $this->getLayout()->getBlock('catalog.wysiwyg.js'); if ($block) { @@ -620,28 +622,23 @@ class Mage_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Controller */ $links = $this->getRequest()->getPost('links'); if (isset($links['related']) && !$product->getRelatedReadonly()) { - $product->setRelatedLinkData(Mage::helper('Mage_Adminhtml_Helper_Js')->decodeGridSerializedInput($links['related'])); + $product->setRelatedLinkData( + Mage::helper('Mage_Adminhtml_Helper_Js')->decodeGridSerializedInput($links['related']) + ); } if (isset($links['upsell']) && !$product->getUpsellReadonly()) { - $product->setUpSellLinkData(Mage::helper('Mage_Adminhtml_Helper_Js')->decodeGridSerializedInput($links['upsell'])); + $product->setUpSellLinkData( + Mage::helper('Mage_Adminhtml_Helper_Js')->decodeGridSerializedInput($links['upsell']) + ); } if (isset($links['crosssell']) && !$product->getCrosssellReadonly()) { $product->setCrossSellLinkData(Mage::helper('Mage_Adminhtml_Helper_Js') ->decodeGridSerializedInput($links['crosssell'])); } if (isset($links['grouped']) && !$product->getGroupedReadonly()) { - $product->setGroupedLinkData(Mage::helper('Mage_Adminhtml_Helper_Js')->decodeGridSerializedInput($links['grouped'])); - } - - /** - * Initialize product categories - */ - $categoryIds = $this->getRequest()->getPost('category_ids'); - if (null !== $categoryIds) { - if (empty($categoryIds)) { - $categoryIds = array(); - } - $product->setCategoryIds($categoryIds); + $product->setGroupedLinkData( + Mage::helper('Mage_Adminhtml_Helper_Js')->decodeGridSerializedInput($links['grouped']) + ); } /** @@ -703,16 +700,6 @@ class Mage_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Controller } } - public function categoriesJsonAction() - { - $product = $this->_initProduct(); - - $this->getResponse()->setBody( - $this->getLayout()->createBlock('Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Categories') - ->getCategoryChildrenJson($this->getRequest()->getParam('category')) - ); - } - /** * Save product action */ diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml index 2c333c9b25ecc0f33fea1bcdf19ef9ee4ff85d41..546ad98c8b1bb21f14a8dd87bf70f972800504d7 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml @@ -51,7 +51,6 @@ <action method="addJs"><file>mage/jquery-no-conflict.js</file></action> <action method="addJs"><file>jquery/jquery-ui-1.8.18.custom.min.js</file></action> <action method="addCss"><file>Mage_Adminhtml::css/ui-lightness/jquery-ui-1.8.21.custom.css</file></action> - <action method="addCss"><file>Mage_Adminhtml::jquery/fileUploader/css/jquery.fileupload-ui.css</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/vendor/jquery.ui.widget.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/jquery.iframe-transport.js</file></action> @@ -59,6 +58,10 @@ <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/load-image.min.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/canvas-to-blob.min.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/jquery.fileupload-fp.js</file></action> + <action method="addCss"><file>Mage_Adminhtml::catalog/jquery.category-selector.css</file></action> + <action method="addJs"><file>Mage_Adminhtml::catalog/jquery.category-selector.js</file></action> + <action method="addJs"><file>Mage_Adminhtml::catalog/jquery.base-image-uploader.js</file></action> + <action method="addCss"><file>Mage_Adminhtml::catalog/jquery.base-image-uploader.css</file></action> </reference> <reference name="content"> <block type="Mage_Adminhtml_Block_Catalog_Product_Edit" name="product_edit"></block> @@ -81,7 +84,6 @@ <action method="addJs"><file>mage/jquery-no-conflict.js</file></action> <action method="addJs"><file>jquery/jquery-ui-1.8.18.custom.min.js</file></action> <action method="addCss"><file>Mage_Adminhtml::css/ui-lightness/jquery-ui-1.8.21.custom.css</file></action> - <action method="addCss"><file>Mage_Adminhtml::jquery/fileUploader/css/jquery.fileupload-ui.css</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/vendor/jquery.ui.widget.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/jquery.iframe-transport.js</file></action> @@ -89,6 +91,10 @@ <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/load-image.min.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/canvas-to-blob.min.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/jquery.fileupload-fp.js</file></action> + <action method="addCss"><file>Mage_Adminhtml::catalog/jquery.category-selector.css</file></action> + <action method="addJs"><file>Mage_Adminhtml::catalog/jquery.category-selector.js</file></action> + <action method="addJs"><file>Mage_Adminhtml::catalog/jquery.base-image-uploader.js</file></action> + <action method="addCss"><file>Mage_Adminhtml::catalog/jquery.base-image-uploader.css</file></action> </reference> <reference name="content"> <block type="Mage_Adminhtml_Block_Catalog_Product_Edit" name="product_edit"></block> @@ -105,12 +111,6 @@ </reference> </adminhtml_catalog_product_edit> - <adminhtml_catalog_product_categories> - <container name="root" label="Root" output="1"> - <block type="Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Categories" name="catalog.product.edit.tab.categories"/> - </container> - </adminhtml_catalog_product_categories> - <adminhtml_catalog_product_reviews> <container name="root" label="Root" output="1"> <block type="Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Reviews" name="admin.product.reviews"/> @@ -261,9 +261,15 @@ Layout handle for configurable products --> <adminhtml_catalog_product_configurable_new> - <remove name="product_tabs"/> - <reference name="left"> - <block type="Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs_Configurable" name="configurable_product_tabs"/> + <reference name="product_tabs"> + <action method="addTab"> + <name>configurable</name> + <block>Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config</block> + </action> + <action method="bindShadowTabs"> + <first>configurable</first> + <second>customer_options</second> + </action> </reference> </adminhtml_catalog_product_configurable_new> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/select2.png b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/select2.png new file mode 100644 index 0000000000000000000000000000000000000000..1d804ffb99699b9e030f1010314de0970b5a000d Binary files /dev/null and b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/select2.png differ diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/select2x2.png b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/select2x2.png new file mode 100644 index 0000000000000000000000000000000000000000..4bdd5c961d452c49dfa0789c2c7ffb82c238fc24 Binary files /dev/null and b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/select2x2.png differ diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/spinner.gif b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 Binary files /dev/null and b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/images/spinner.gif differ diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.base-image-uploader.css b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.base-image-uploader.css new file mode 100644 index 0000000000000000000000000000000000000000..824ed620b07fa20fd4cad4abce11ce333d2e348c --- /dev/null +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.base-image-uploader.css @@ -0,0 +1,28 @@ +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage_Catalog + * @package + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +.base-image-uploader { + max-height:265px; + max-width:265px; +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.base-image-uploader.js b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.base-image-uploader.js new file mode 100644 index 0000000000000000000000000000000000000000..5a3a3d6cfb79405a91bc24c74e74a30162eed329 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.base-image-uploader.js @@ -0,0 +1,57 @@ +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package js + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +function BaseImageUploader(id, maxFileSize) { + (function ($) { + $('#' + id + '_upload').fileupload({ + dataType: 'json', + dropZone: '#' + id + '_image', + acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, + maxFileSize: maxFileSize, + done: function (e, data) { + if (!data.result) { + return; + } + if (!data.result.error) { + $('#' + id + '_image').attr({src: data.result.url, + title: data.result.url, + alt: data.result.url}); + $('#' + id).val(data.result.file); + if (typeof media_gallery_contentJsObject != 'undefined') { + media_gallery_contentJsObject.handleUploadComplete(data.result); + media_gallery_contentJsObject.imagesValues.image = data.result.file; + media_gallery_contentJsObject.updateImages(); + } + } else { + alert(jQuery.mage.__('File extension not known or unsupported type.')); + } + }, + add: function(e, data) { + $(this).fileupload('process', data).done(function () { + data.submit(); + }); + } + }); + })(jQuery); +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.category-selector.css b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.category-selector.css new file mode 100644 index 0000000000000000000000000000000000000000..ca413121796d77006ca5db1677bc19229d41b8aa --- /dev/null +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.category-selector.css @@ -0,0 +1,585 @@ +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage_Cat + * @package + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +.category-selector-container { + position:relative; + display:inline-block; + vertical-align:top; + width:99%; +} + +.category-selector-container, +.category-selector-drop, +.category-selector-search, +.category-selector-search input { + -moz-box-sizing:border-box; + -ms-box-sizing:border-box; + -webkit-box-sizing:border-box; + -khtml-box-sizing:border-box; + box-sizing:border-box; +} + +.category-selector-container .category-selector-choice { + background-color:#fff; + background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white)); + background-image:-webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image:-moz-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image:-o-linear-gradient(bottom, #eeeeee 0%, #ffffff 50%); + background-image:-ms-linear-gradient(top, #eeeeee 0%, #ffffff 50%); + background-image:linear-gradient(top, #eeeeee 0%, #ffffff 50%); + border-radius:4px; + background-clip:padding-box; + border:1px solid #aaa; + display:block; + overflow:hidden; + white-space:nowrap; + position:relative; + height:26px; + line-height:26px; + padding:0 0 0 8px; + color:#444; + text-decoration:none; +} + +.category-selector-container.category-selector-drop-above .category-selector-choice { + border-bottom-color:#aaa; + border-radius:0px 0px 4px 4px; + background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.9, white)); + background-image:-webkit-linear-gradient(center bottom, #eeeeee 0%, white 90%); + background-image:-moz-linear-gradient(center bottom, #eeeeee 0%, white 90%); + background-image:-o-linear-gradient(bottom, #eeeeee 0%, white 90%); + background-image:-ms-linear-gradient(top, #eeeeee 0%, #ffffff 90%); + background-image:linear-gradient(top, #eeeeee 0%, #ffffff 90%); +} + +.category-selector-container .category-selector-choice span { + margin-right:26px; + display:block; + overflow:hidden; + white-space:nowrap; + -o-text-overflow:ellipsis; + -ms-text-overflow:ellipsis; + text-overflow:ellipsis; +} + +.category-selector-container .category-selector-choice abbr { + display:block; + position:absolute; + right:26px; + top:8px; + width:12px; + height:12px; + font-size:1px; + background:url('images/select2.png') right top no-repeat; + cursor:pointer; + text-decoration:none; + border:0; + outline:0; +} +.category-selector-container .category-selector-choice abbr:hover { + background-position:right -11px; + cursor:pointer; +} + +.category-selector-drop { + background:#fff; + color:#000; + border:1px solid #ccc; + border-top:0; + position:absolute; + top:100%; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.2); + z-index:9999; + width:100%; + margin-top:-3px; + border-radius:0 0 3px 3px; +} + +.category-selector-drop.category-selector-drop-above { + border-radius:3px 3px 0 0; + margin-top:3px; + border-top:1px solid #ccc; + border-bottom:0; + box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.2); +} + +.category-selector-container .category-selector-choice div { + border-radius:0 4px 4px 0; + background-clip:padding-box; + background:#ccc; + background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); + background-image:-webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image:-moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image:-o-linear-gradient(bottom, #ccc 0%, #eee 60%); + background-image:-ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%); + background-image:linear-gradient(top, #cccccc 0%, #eeeeee 60%); + border-left:1px solid #aaa; + position:absolute; + right:0; + top:0; + display:block; + height:100%; + width:18px; +} + +.category-selector-container .category-selector-choice div b { + background:url('images/select2.png') no-repeat 0 1px; + display:block; + width:100%; + height:100%; +} + +.category-selector-search { + display:inline-block; + white-space:nowrap; + z-index:10000; + min-height:26px; + width:100%; + margin:0; + padding-left:4px; + padding-right:4px; +} + +.category-selector-search-hidden { + display:block; + position:absolute; + left:-10000px; +} + +.category-selector-search input { + background:#fff url('images/select2.png') no-repeat 100% -22px; + background:url('images/select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background:url('images/select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background:url('images/select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background:url('images/select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background:url('images/select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); + background:url('images/select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%); + padding:4px 20px 4px 5px; + outline:0; + border:1px solid #aaa; + font-family:sans-serif; + font-size:1em; + width:100%; + margin:0; + height:auto !important; + min-height:26px; + box-shadow:none; + border-radius:0; +} + +.category-selector-drop.category-selector-drop-above .category-selector-search input { + margin-top:4px; +} + +.category-selector-search input.category-selector-active { + background:#fff url('images/spinner.gif') no-repeat 100%; + background:url('images/spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background:url('images/spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background:url('images/spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background:url('images/spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background:url('images/spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); + background:url('images/spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%); +} + +.category-selector-container-active .category-selector-choice, +.category-selector-container-active .category-selector-choices { + box-shadow:0 0 5px rgba(0, 0, 0, .3); + border:1px solid #74B9EF; + outline:none; +} + +.category-selector-dropdown-open .category-selector-choice { + border:1px solid #aaa; + border-bottom-color:transparent; + box-shadow:0 1px 0 #fff inset; + background-color:#eee; + background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee)); + background-image:-webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image:-moz-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image:-o-linear-gradient(bottom, white 0%, #eeeeee 50%); + background-image:-ms-linear-gradient(top, #ffffff 0%, #eeeeee 50%); + background-image:linear-gradient(top, #ffffff 0%, #eeeeee 50%); + -webkit-border-bottom-left-radius:0; + -webkit-border-bottom-right-radius:0; + -moz-border-radius-bottomleft:0; + -moz-border-radius-bottomright:0; + border-bottom-left-radius:0; + border-bottom-right-radius:0; +} + +.category-selector-dropdown-open .category-selector-choice div { + background:transparent; + border-left:none; +} +.category-selector-dropdown-open .category-selector-choice div b { + background-position:-18px 1px; +} + +/* results */ +.category-selector-results { + margin:4px 4px 4px 0; + padding:0 0 0 4px; + position:relative; + overflow-x:hidden; + overflow-y:auto; + max-height:200px; +} + +.category-selector-results ul.category-selector-result-sub { + margin:0; + padding:0; +} + +.category-selector-results ul.category-selector-result-sub > li .category-selector-result-label { padding-left:20px } +.category-selector-results ul.category-selector-result-sub ul.category-selector-result-sub > li .category-selector-result-label { padding-left:40px } +.category-selector-results ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub > li .category-selector-result-label { padding-left:60px } +.category-selector-results ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub > li .category-selector-result-label { padding-left:80px } +.category-selector-results ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub > li .category-selector-result-label { padding-left:100px } +.category-selector-results ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub > li .category-selector-result-label { padding-left:110px } +.category-selector-results ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub ul.category-selector-result-sub > li .category-selector-result-label { padding-left:120px } + +.category-selector-results li { + list-style:none; + display:list-item; +} + +.category-selector-results li.category-selector-result-with-children > .category-selector-result-label { + font-weight:bold; +} + +.category-selector-results .category-selector-result-label { + padding:3px 7px 4px; + margin:0; + cursor:pointer; +} + +.category-selector-results .category-selector-highlighted { + background:#3875d7; + color:#fff; +} +.category-selector-results li em { + background:#feffde; + font-style:normal; +} +.category-selector-results .category-selector-highlighted em { + background:transparent; +} +.category-selector-results .category-selector-no-results { + padding:3px; +} +.category-selector-results .category-selector-no-results, +.category-selector-results .category-selector-searching, +.category-selector-results .category-selector-selection-limit { + background:#f4f4f4; + display:list-item; +} +.category-selector-results .category-selector-disabled { + display:none; +} +.category-selector-more-results.category-selector-active { + background:#f4f4f4 url('images/spinner.gif') no-repeat 100%; +} + +.category-selector-more-results { + background:#f4f4f4; + display:list-item; +} + +/* disabled styles */ +.category-selector-container.category-selector-container-disabled .category-selector-choice { + background-color:#f4f4f4; + background-image:none; + border:1px solid #ddd; + cursor:default; +} + +.category-selector-container.category-selector-container-disabled .category-selector-choice div { + background-color:#f4f4f4; + background-image:none; + border-left:0; +} + +/* multiselect */ + +.category-selector-container-multi .category-selector-choices { + background-color:#fff; + border:1px solid #ccc; + margin:0; + padding:0; + cursor:text; + overflow:hidden; + min-height:28px; + position:relative; + box-sizing:border-box; + border-radius:3px; + box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition:border linear 0.2s, box-shadow linear 0.2s; + -moz-transition:border linear 0.2s, box-shadow linear 0.2s; + -ms-transition:border linear 0.2s, box-shadow linear 0.2s; + -o-transition:border linear 0.2s, box-shadow linear 0.2s; + transition:border linear 0.2s, box-shadow linear 0.2s; +} + +.category-selector-container-multi.category-selector-container-active .category-selector-choices { + box-shadow:0 0 5px rgba(0, 0, 0, .3); + border:1px solid #74B9EF; + outline:none; +} +.category-selector-container-multi .category-selector-choices li { + float:left; + list-style:none; +} +.category-selector-container-multi .category-selector-choices .category-selector-search-field { + white-space:nowrap; + margin:0; + padding:0; +} + +.category-selector-container-multi .category-selector-choices .category-selector-search-field input { + color:#666; + background:transparent !important; + font-family:sans-serif; + font-size:100%; + height:22px; + padding:5px; + margin:1px 0; + outline:0; + border:0; + box-shadow:none; +} + +.category-selector-container-multi .category-selector-choices .category-selector-search-field input.category-selector-active { + background:#fff url('images/spinner.gif') no-repeat 100% !important; +} + +.category-selector-default { + color:#999 !important; +} + +.category-selector-container-multi .category-selector-choices .category-selector-search-choice { + margin:3px 0 3px 5px; + padding-left:15px; + position:relative; + cursor:default; +} +.category-selector-container-multi .category-selector-choices .category-selector-search-choice span { + cursor:default; +} +.category-selector-container-multi .category-selector-choices .category-selector-search-choice-focus { + background:#d4d4d4; +} + +.category-selector-search-choice-close { + display:block; + position:absolute; + right:3px; + top:4px; + width:12px; + height:13px; + font-size:1px; + background:url('images/select2.png') right top no-repeat; + outline:none; +} + +.category-selector-container-multi .category-selector-search-choice-close { + left:3px; + top:7px; +} + +.category-selector-container-multi .category-selector-choices .category-selector-search-choice .category-selector-search-choice-close:hover { + background-position:right -11px; +} +.category-selector-container-multi .category-selector-choices .category-selector-search-choice-focus .category-selector-search-choice-close { + background-position:right -11px; +} + +/* disabled styles */ + +.category-selector-container-multi.category-selector-container-disabled .category-selector-choices { + background-color:#f4f4f4; + background-image:none; + border:1px solid #ddd; + cursor:default; +} + +.category-selector-container-multi.category-selector-container-disabled .category-selector-choices .category-selector-search-choice { + background-image:none; + background-color:#f4f4f4; + border:1px solid #ddd; + padding:3px 5px 3px 5px; +} + +.category-disabled a{ + color: #808080; +} + +.category-selected a{ + background-color: #0000ff; + color: #FFF; +} +.category-selector-container-multi.category-selector-container-disabled .category-selector-choices .category-selector-search-choice .category-selector-search-choice-close { + display:none; +} +/* end multiselect */ + +.category-selector-result-selectable .category-selector-match, +.category-selector-result-unselectable .category-selector-result-selectable .category-selector-match { + text-decoration:underline; +} +.category-selector-result-unselectable .category-selector-match { + text-decoration:none; +} + +.category-selector-offscreen { + position:absolute; left:-10000px; +} + +.category-selector-results li { + margin-bottom:1px; +} + +.parent { + font-weight:bold; +} +.parent.level-1 { + margin-left:0; +} +.level-1, +.parent.level-2 { + margin-left:15px; +} +.level-2, +.parent.level-3 { + margin-left:25px; +} +.level-3, +.parent.level-4 { + margin-left:35px; +} +.level-4, +.parent.level-5{ + margin-left:45px; +} +.level-5 { + margin-left:55px; +} + +/* Retina-ize icons */ +@media only screen and (-webkit-min-device-pixel-ratio: 1.5) { + .category-selector-search input, + .category-selector-search-choice-close, + .category-selector-container .category-selector-choice abbr, + .category-selector-container .category-selector-choice div b { + background-image:url(images/select2x2.png) !important; + background-repeat:no-repeat !important; + background-size:60px 40px !important; + } + .category-selector-search input { + background-position:100% -21px !important; + } +} + +/* TODO: remove after Magento User Interface framework integration */ +/* ============================================================================= + Buttons + ========================================================================== */ +.button { + position:relative; + display: inline-block; + padding: 4px 10px; + margin-bottom: 0; + font-size: 13px; + line-height: 18px; + color: #333; + text-align: center; + text-decoration:none; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background: #ffffff; + background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlNmU2ZTYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); + background: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#e6e6e6)); + background: -webkit-linear-gradient(top, #ffffff 0%,#e6e6e6 100%); + background: -o-linear-gradient(top, #ffffff 0%,#e6e6e6 100%); + background: -ms-linear-gradient(top, #ffffff 0%,#e6e6e6 100%); + background: linear-gradient(to bottom, #ffffff 0%,#e6e6e6 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#e6e6e6',GradientType=0 ); + border: 1px solid #ccc; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.ie9 .button { + padding-top:5px; + padding-bottom:3px; + filter:none; +} + +.button:hover { + color: #333; + text-decoration: none; + background: #f9f9f9; + background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlNmU2ZTYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); + background: -moz-linear-gradient(top, #f9f9f9 0%, #e6e6e6 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f9f9f9), color-stop(100%,#e6e6e6)); + background: -webkit-linear-gradient(top, #f9f9f9 0%,#e6e6e6 100%); + background: -o-linear-gradient(top, #f9f9f9 0%,#e6e6e6 100%); + background: -ms-linear-gradient(top, #f9f9f9 0%,#e6e6e6 100%); + background: linear-gradient(to bottom, #f9f9f9 0%,#e6e6e6 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f9f9f9', endColorstr='#e6e6e6',GradientType=0 ); +} +.button:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.button:active +.button.active { + background-color: #e6e6e6; + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} +.button[disabled] { + cursor: not-allowed; + background-color: #e6e6e6; + background-image: none; + opacity: 0.65; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.button:visited { + color:#333; +} diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.category-selector.js b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.category-selector.js new file mode 100644 index 0000000000000000000000000000000000000000..7c3f604bfdd80e6417497ff37dbb7798c6ca5775 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/jquery.category-selector.js @@ -0,0 +1,142 @@ +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package js + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +(function ($, undefined) { + "use strict"; + var treeToList = function(list, nodes, level, path) { + $.each(nodes, function() { + list.push({ + label: this.name, + value: this.id, + level: level, + item: this, + path: path + this.name + }); + if ('children' in this) { + treeToList(list, this.children, level + 1, path + this.name + '/' ); + } + }); + return list; + }; + $.fn.categorySelector = function (options) { + this.each(function () { + var $element = $( + '<div class="category-selector-container category-selector-container-multi">' + + '<ul class="category-selector-choices">' + + '<li class="category-selector-search-field">' + + '<input type="text" autocomplete="off" ' + + 'data-ui-id="category-selector-input" class="category-selector-input">' + + '</li></ul></div>' + ), + $list = $element.children(), + $this = $(this), + name = $this.attr('name'), + $searchField = $list.find('.category-selector-search-field'), + itemRenderer = function(value, text, data) { + $('<li class="category-selector-search-choice button"/>') + .data(data || {}) + .append($('<input type="hidden" />').attr('name', name).val(value)) + .append($('<div/>').text(text)) + .append('<span ' + + 'class="category-selector-search-choice-close" tabindex="-1"></span>' + ) + .insertBefore($searchField); + }, + $input = $element.find('.category-selector-input'), + elementPresent = function(item) { + var selector = '[name="product[category_ids][]"][value=' + parseInt(item.value, 10) + ']'; + return $list.find(selector).length > 0; + }; + $element.append($('<input type="hidden" />').attr('name', name)); + $this.find('option').each(function(){ + itemRenderer($(this).val(), $(this).text()); + }); + $this.attr('disabled', 'disabled').hide(); + $this.data('category-selector-element', $element); + $element.insertAfter($this); + $list.delegate(".category-selector-search-choice-close", "click", function() { + $(this).parent().remove(); + }); + $input.bind('ajaxSend ajaxComplete', function(e) { + e.stopPropagation(); + switch (e.type) { + case 'ajaxSend': $input.addClass('category-selector-active'); break; + case 'ajaxComplete': $input.removeClass('category-selector-active'); break; + } + }); + $input.autocomplete({ + source: function(request, response) { + $.ajax({ + url: options.url, + context: $input, + dataType: "json", + data: { + name_part: request.term + }, + success: function(data) { + response(treeToList([], data || [], 0, '')); + } + }); + }, + minLength: 1, + select: function(event, ui) { + if (elementPresent(ui.item)) { + event.preventDefault(); + return false; + } + itemRenderer(ui.item.value, ui.item.label, ui.item); + $element.find('.category-selector-input').val(''); + return false; + }, + close: function(event) { + event.preventDefault(); + return false; + } + }); + $input.data("autocomplete")._renderItem = function(ul, item) { + var level = window.parseInt(item.level), + $li = $("<li>"); + $li.data("item.autocomplete", item); + $li.append($("<a />", { + 'data-level': level, + 'data-ui-id': 'category-selector-' + item.value + }) + .attr('title', item.path) + .addClass('level-' + level) + .text(item.label) + .css({marginLeft: level * 16}) + ); + if (window.parseInt(item.item.is_active, 10) == 0) { + $li.addClass('category-disabled'); + } + if (elementPresent(item)) { + $li.addClass('category-selected'); + } + $li.appendTo(ul); + + return $li; + }; + }); + }; +})(jQuery); diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit.phtml index b18d03181a15ef3b595097cf87b07d2a9feff511..610a0b9f170b645e40835a973fb77dad25f079d5 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit.phtml @@ -42,7 +42,7 @@ <?php echo $this->getDuplicateButtonHtml() ?> <?php endif; ?> <?php endif; ?> - <?php if($this->getProductSetId() && $this->getIsConfigured()): ?> + <?php if ($this->getProductSetId()): ?> <?php echo $this->getChangeAttributeSetButtonHtml() ?> <?php echo $this->getSaveButtonHtml() ?> <?php echo $this->getSaveAndEditButtonHtml() ?> @@ -85,26 +85,24 @@ setLocation(template.evaluate({attribute_set:$F(setElement),type:$F(typeElement)})); } - function setSuperSettings(urlTemplate, attributesClass, validateField) { + function setSuperSettings(urlTemplate, attributesClass, validateField) { var attributesFields = $$('.' + attributesClass); var attributes = Form.serializeElements(attributesFields, true).attribute; - if(typeof attributes == 'string') { + if (typeof attributes == 'string') { attributes = [attributes]; } - if(!attributes) { + if (!attributes) { $(validateField).value = 'no-attributes'; } else { $(validateField).value = 'has-attributes'; } - if (productForm.validator.validate()) { - var template = new Template(urlTemplate, productTemplateSyntax); - var url = template.evaluate({ - attributes: encode_base64(attributes.join(',')).replace(new RegExp('/','g'),'%2F').replace(new RegExp('=','g'),'%3D') - }); - setLocation(url); - } + var template = new Template(urlTemplate, productTemplateSyntax); + var url = template.evaluate({ + attributes: encode_base64(attributes.join(',')).replace(new RegExp('/', 'g'), '%2F').replace(new RegExp('=', 'g'), '%3D') + }); + jQuery('#product_edit_form').attr('action', url + '&active_tab=configurable').submit(); } function checkMaxLength(Object, MaxLen) @@ -115,7 +113,7 @@ return 1; } -Event.observe(window, 'load', function() { +jQuery(function() { var objName = '<?php echo $this->getSelectedTabId() ?>'; if (objName) { obj = $(objName); diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit/categories.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit/categories.phtml deleted file mode 100644 index 436ebdd18a7c6a9eac6f532f3a93eb26f5e33890..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit/categories.phtml +++ /dev/null @@ -1,148 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/afl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @category design - * @package default_default - * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<div class="entry-edit"> - <div class="entry-edit-head"> - <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('Mage_Catalog_Helper_Data')->__('Product Categories') ?></h4> - </div> - <fieldset id="grop_fields"> - <input type="hidden" name="category_ids" id="product_categories" value="<?php echo $this->getIdsString() ?>"> - <div id="product-categories" class="tree"></div> - </fieldset> -</div> -<?php if($this->getRootNode() && $this->getRootNode()->hasChildren()): ?> -<script type="text/javascript"> -Ext.EventManager.onDocumentReady(function() { - var categoryLoader = new Ext.tree.TreeLoader({ - dataUrl: '<?php echo $this->getLoadTreeUrl()?>' - }); - - categoryLoader.createNode = function(config) { - config.uiProvider = Ext.tree.CheckboxNodeUI; - var node; - if (config.children && !config.children.length) { - delete(config.children); - node = new Ext.tree.AsyncTreeNode(config); - - } else { - node = new Ext.tree.TreeNode(config); - } - return node; - }; - - categoryLoader.on("beforeload", function(treeLoader, node) { - treeLoader.baseParams.category = node.attributes.id; - }); - - categoryLoader.on("load", function(treeLoader, node, config) { - varienWindowOnload(); - }); - - var tree = new Ext.tree.TreePanel('product-categories', { - animate:true, - loader: categoryLoader, - enableDD:false, - containerScroll: true, - rootUIProvider: Ext.tree.CheckboxNodeUI, - selModel: new Ext.tree.CheckNodeMultiSelectionModel(), - rootVisible: '<?php echo $this->getRootNode()->getIsVisible() ?>' - }); - - tree.on('check', function(node) { - if(node.attributes.checked) { - categoryAdd(node.id); - } else { - categoryRemove(node.id); - } - varienElementMethods.setHasChanges(node.getUI().checkbox); - }, tree); - - // set the root node - var root = new Ext.tree.TreeNode({ - text: '<?php echo $this->jsQuoteEscape($this->getRootNode()->getName()) ?>', - draggable:false, - checked:'<?php echo $this->getRootNode()->getChecked() ?>', - id:'<?php echo $this->getRootNode()->getId() ?>', - disabled: <?php echo ($this->getRootNode()->getDisabled() ? 'true' : 'false') ?>, - uiProvider: Ext.tree.CheckboxNodeUI - }); - - tree.setRootNode(root); - bildCategoryTree(root, <?php echo $this->getTreeJson() ?>); - tree.addListener('click', categoryClick.createDelegate(this)); - - // render the tree - tree.render(); - root.expand(); - //tree.expandAll(); -}); - -function bildCategoryTree(parent, config){ - if (!config) return null; - - if (parent && config && config.length){ - for (var i = 0; i < config.length; i++){ - config[i].uiProvider = Ext.tree.CheckboxNodeUI; - var node; - var _node = Object.clone(config[i]); - if (_node.children && !_node.children.length) { - delete(_node.children); - node = new Ext.tree.AsyncTreeNode(_node); - - } else { - node = new Ext.tree.TreeNode(config[i]); - } - parent.appendChild(node); - node.loader = node.getOwnerTree().loader; - if(config[i].children){ - bildCategoryTree(node, config[i].children); - } - } - } -} - -function categoryClick(node, e){ - if (node.disabled) { - return; - } - node.getUI().check(!node.getUI().checked()); - varienElementMethods.setHasChanges(Event.element(e), e); -}; -function categoryAdd(id) { - var ids = $('product_categories').value.split(','); - ids.push(id); - $('product_categories').value = ids.join(','); -} -function categoryRemove(id) { - var ids = $('product_categories').value.split(','); - // bug #7654 fixed - while (-1 != ids.indexOf(id)) { - ids.splice(ids.indexOf(id), 1); - } - $('product_categories').value = ids.join(','); -} -</script> -<?php endif; ?> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit/super/config.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit/super/config.phtml index 3af9eba4ce81f381f63f8ff53fb9e2b6fdbdf457..3fd62ec4fce22eec7b432be60b468b13f1914a52 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit/super/config.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/edit/super/config.phtml @@ -23,6 +23,11 @@ * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ + +/** @var $this Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config */ +if (!count($this->getSelectedAttributes())) { + echo $this->getChildHtml('super_settings'); +} else { ?> <?php if (!$this->isReadonly()):?> <div class="entry-edit"> @@ -151,3 +156,4 @@ Validation.add( </script> <div><input type="hidden" name="affect_configurable_product_attributes" value="1" /></div> +<?php } ?> \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/images/image-placeholder.png b/app/code/core/Mage/Adminhtml/view/adminhtml/images/image-placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..0b7741b72e24b3934c9326a1550ccb350a0864c0 Binary files /dev/null and b/app/code/core/Mage/Adminhtml/view/adminhtml/images/image-placeholder.png differ diff --git a/app/code/core/Mage/Backend/Block/Widget/Form.php b/app/code/core/Mage/Backend/Block/Widget/Form.php index 5aab7cb87e264728f1e453cec0458079e2988704..1556ac1d1a25fc9a5240a4656a052b4d428b5bb6 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Form.php +++ b/app/code/core/Mage/Backend/Block/Widget/Form.php @@ -173,7 +173,7 @@ class Mage_Backend_Block_Widget_Form extends Mage_Backend_Block_Widget } if ( ($inputType = $attribute->getFrontend()->getInputType()) && !in_array($attribute->getAttributeCode(), $exclude) - && ('media_image' != $inputType) + && (('media_image' != $inputType) || ($attribute->getAttributeCode() == 'image')) ) { $fieldType = $inputType; diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php index b06c554f661f1b7637d20c43f11d293d79ccea5d..f285d14a806cf6ec950fffb12e87bdefcada3d11 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Date.php @@ -48,29 +48,31 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Date extends Mage_Backend_Blo { $htmlId = Mage::helper('Mage_Core_Helper_Data')->uniqHash($this->_getHtmlId()); $format = $this->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT); - $html = '<div class="range" id="'.$htmlId.'_range"><div class="range-line date">' - . '<span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('From').':</span>' - . '<input type="text" name="'.$this->_getHtmlName().'[from]" id="'.$htmlId.'_from"' - . ' value="'.$this->getEscapedValue('from').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/>' + $html = '<div class="range" id="' . $htmlId . '_range"><div class="range-line date">' + . '<span class="label">' . $this->__('From') . ':</span>' + . '<input type="text" name="' . $this->_getHtmlName() . '[from]" id="' . $htmlId . '_from"' + . ' value="' . $this->getEscapedValue('from') . '" class="input-text no-changes" ' + . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/>' . '</div>'; $html.= '<div class="range-line date">' - . '<span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('To').' :</span>' - . '<input type="text" name="'.$this->_getHtmlName().'[to]" id="'.$htmlId.'_to"' - . ' value="'.$this->getEscapedValue('to').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/>' + . '<span class="label">' . $this->__('To') . ' :</span>' + . '<input type="text" name="' . $this->_getHtmlName() . '[to]" id="' . $htmlId . '_to"' + . ' value="' . $this->getEscapedValue('to') . '" class="input-text no-changes" ' + . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/>' . '</div></div>'; - $html.= '<input type="hidden" name="'.$this->_getHtmlName().'[locale]"' - . ' value="'.$this->getLocale()->getLocaleCode().'"/>'; - $html.= '<script type="text/javascript"> + $html .= '<input type="hidden" name="'.$this->_getHtmlName() . '[locale]"' + . ' value="' . $this->getLocale()->getLocaleCode() . '"/>'; + $html .= '<script type="text/javascript"> (function( $ ) { - $("#'.$htmlId.'_range").dateRange({ - dateFormat: "'.$format.'", - buttonImage: "' . Mage::getDesign()->getViewFileUrl('images/grid-cal.gif') . '", - buttonText: "'.$this->escapeHtml(Mage::helper('Mage_Backend_Helper_Data')->__('Date selector')).'", + $("#' . $htmlId . '_range").dateRange({ + dateFormat: "' . $format . '", + buttonImage: "' . $this->getViewFileUrl('images/grid-cal.gif') . '", + buttonText: "' . $this->escapeHtml($this->__('Date selector')) . '", from: { - id: "'.$htmlId.'_from" + id: "' . $htmlId . '_from" }, to: { - id: "'.$htmlId.'_to" + id: "' . $htmlId . '_to" } }) })(jQuery) @@ -170,8 +172,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Date extends Mage_Backend_Blo $dateObj->setTimezone(Mage_Core_Model_Locale::DEFAULT_TIMEZONE); return $dateObj; - } - catch (Exception $e) { + } catch (Exception $e) { return null; } } diff --git a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Datetime.php b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Datetime.php index 7cd9bef0e88116e73b8dba2e196d222c87fd51dc..49d509242ef15132a731ed372a62cc1625dd5a2a 100644 --- a/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Datetime.php +++ b/app/code/core/Mage/Backend/Block/Widget/Grid/Column/Filter/Datetime.php @@ -34,13 +34,15 @@ */ class Mage_Backend_Block_Widget_Grid_Column_Filter_Datetime extends Mage_Backend_Block_Widget_Grid_Column_Filter_Date { - //full day is 86400, we need 23 hours:59 minutes:59 seconds = 86399 + /** + * full day is 86400, we need 23 hours:59 minutes:59 seconds = 86399 + */ const END_OF_DAY_IN_SECONDS = 86399; - public function getValue($index=null) + public function getValue($index = null) { if ($index) { - if ($data = $this->getData('value', 'orig_'.$index)) { + if ($data = $this->getData('value', 'orig_' . $index)) { return $data;//date('Y-m-d', strtotime($data)); } return null; @@ -91,12 +93,10 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Datetime extends Mage_Backend $dateObj->setTimezone(Mage_Core_Model_Locale::DEFAULT_TIMEZONE); return $dateObj; - } - catch (Exception $e) { + } catch (Exception $e) { return null; } } - return parent::_convertDate($date, $locale); } @@ -115,31 +115,33 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Datetime extends Mage_Backend $timeFormat = $this->getLocale()->getTimeFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT); } - $html = '<div class="range" id="'.$htmlId.'_range"><div class="range-line date">' - . '<span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('From').':</span>' - . '<input type="text" name="'.$this->_getHtmlName().'[from]" id="'.$htmlId.'_from"' - . ' value="'.$this->getEscapedValue('from').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/>' + $html = '<div class="range" id="' . $htmlId . '_range"><div class="range-line date">' + . '<span class="label">' . $this->__('From') . ':</span>' + . '<input type="text" name="' . $this->_getHtmlName() . '[from]" id="' . $htmlId . '_from"' + . ' value="' . $this->getEscapedValue('from') . '" class="input-text no-changes" ' + . $this->getUiId('filter', $this->_getHtmlName(), 'from') . '/>' . '</div>'; - $html.= '<div class="range-line date">' - . '<span class="label">' . Mage::helper('Mage_Backend_Helper_Data')->__('To').' :</span>' - . '<input type="text" name="'.$this->_getHtmlName().'[to]" id="'.$htmlId.'_to"' - . ' value="'.$this->getEscapedValue('to').'" class="input-text no-changes" ' . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/>' + $html .= '<div class="range-line date">' + . '<span class="label">' . $this->__('To') . ' :</span>' + . '<input type="text" name="' . $this->_getHtmlName() . '[to]" id="' . $htmlId . '_to"' + . ' value="' . $this->getEscapedValue('to') . '" class="input-text no-changes" ' + . $this->getUiId('filter', $this->_getHtmlName(), 'to') . '/>' . '</div></div>'; - $html.= '<input type="hidden" name="'.$this->_getHtmlName().'[locale]"' - . ' value="'.$this->getLocale()->getLocaleCode().'"/>'; - $html.= '<script type="text/javascript"> + $html .= '<input type="hidden" name="' . $this->_getHtmlName() . '[locale]"' + . ' value="' . $this->getLocale()->getLocaleCode() . '"/>'; + $html .= '<script type="text/javascript"> (function( $ ) { $("#'.$htmlId.'_range").dateRange({ dateFormat: "' . $format . '", timeFormat: "' . $timeFormat . '", - showsTime: '. ( $this->getColumn()->getFilterTime() ? 'true' : 'false') .', - buttonImage: "'. Mage::getDesign()->getViewFileUrl('images/grid-cal.gif') . '", - buttonText: "'.$this->escapeHtml(Mage::helper('Mage_Backend_Helper_Data')->__('Date selector')).'", + showsTime: ' . ($this->getColumn()->getFilterTime() ? 'true' : 'false') . ', + buttonImage: "' . $this->getViewFileUrl('images/grid-cal.gif') . '", + buttonText: "' . $this->escapeHtml($this->__('Date selector')) . '", from: { - id: "'.$htmlId.'_from" + id: "' . $htmlId . '_from" }, to: { - id: "'.$htmlId.'_to" + id: "' . $htmlId . '_to" } }) })(jQuery) @@ -153,7 +155,7 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Datetime extends Mage_Backend * @param string $index * @return string */ - public function getEscapedValue($index=null) + public function getEscapedValue($index = null) { if ($this->getColumn()->getFilterTime()) { $value = $this->getValue($index); @@ -167,5 +169,4 @@ class Mage_Backend_Block_Widget_Grid_Column_Filter_Datetime extends Mage_Backend return parent::getEscapedValue($index); } - } diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml index 83dd7233a638309268e25d340cfac44e809d31ac..008af9b93d8c76eea4bd56ae0c097c190d762cf0 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/button/split.phtml @@ -50,7 +50,7 @@ </ul> </div> <script type="text/javascript">//<[CDATA[ -jQuery(function() { +document.observe('dom:loaded', function() { (function($) { $('#<?php echo $this->getId(); ?> [data-toggle="dropdown"]').on('click.toggleDropdown', function() { $(this).toggleClass('active') diff --git a/app/code/core/Mage/Catalog/Model/Product.php b/app/code/core/Mage/Catalog/Model/Product.php index 6be2e3025f9f20a2b736eabac9465d6eddb84201..4adf34aca6a2ae7ee93d3515cbe0dde30fe4da14 100644 --- a/app/code/core/Mage/Catalog/Model/Product.php +++ b/app/code/core/Mage/Catalog/Model/Product.php @@ -326,29 +326,6 @@ class Mage_Catalog_Model_Product extends Mage_Catalog_Model_Abstract return $category; } - /** - * Set assigned category IDs array to product - * - * @param array|string $ids - * @return Mage_Catalog_Model_Product - */ - public function setCategoryIds($ids) - { - if (is_string($ids)) { - $ids = explode(',', $ids); - } elseif (!is_array($ids)) { - Mage::throwException(Mage::helper('Mage_Catalog_Helper_Data')->__('Invalid category IDs.')); - } - foreach ($ids as $i => $v) { - if (empty($v)) { - unset($ids[$i]); - } - } - - $this->setData('category_ids', $ids); - return $this; - } - /** * Retrieve assigned category Ids * @@ -356,7 +333,7 @@ class Mage_Catalog_Model_Product extends Mage_Catalog_Model_Abstract */ public function getCategoryIds() { - if (! $this->hasData('category_ids')) { + if (!$this->hasData('category_ids')) { $wasLocked = false; if ($this->isLockedAttribute('category_ids')) { $wasLocked = true; @@ -369,7 +346,7 @@ class Mage_Catalog_Model_Product extends Mage_Catalog_Model_Abstract } } - return (array) $this->_getData('category_ids'); + return (array)$this->_getData('category_ids'); } /** diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Category.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Category.php new file mode 100644 index 0000000000000000000000000000000000000000..cc0f013a263182d6233544dfe8a8bdc34a087a2c --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Category.php @@ -0,0 +1,47 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Catalog + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Catalog product categories backend attribute model + * + * @category Mage + * @package Mage_Catalog + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Catalog_Model_Product_Attribute_Backend_Category extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract +{ + /** + * Set category ids to product data + * + * @param Mage_Catalog_Model_Product $object + * @return Mage_Eav_Model_Entity_Attribute_Backend_Abstract + */ + public function afterLoad($object) + { + $object->setData($this->getAttribute()->getAttributeCode(), $object->getCategoryIds()); + return parent::afterLoad($object); + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Stock.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Stock.php new file mode 100644 index 0000000000000000000000000000000000000000..d776676ec260cabd7898b8a69b2ca49387e221aa --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Backend/Stock.php @@ -0,0 +1,84 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Catalog + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + + +/** + * Quantity and Stock Status attribute processing + * + * @category Mage + * @package Mage_Catalog + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Catalog_Model_Product_Attribute_Backend_Stock extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract +{ + /** + * @var Mage_CatalogInventory_Model_Stock_Item + */ + protected $_inventory; + + public function __construct(array $data = array()) + { + $this->_inventory = isset($data['inventory']) + ? $data['inventory'] + : Mage::getModel('Mage_CatalogInventory_Model_Stock_Item'); + } + + /** + * Set inventory data to custom attribute + * + * @param Varien_Object $object + * @return Mage_Eav_Model_Entity_Attribute_Backend_Abstract + */ + public function afterLoad($object) + { + $this->_inventory->loadByProduct($object); + $object->setData( + $this->getAttribute()->getAttributeCode(), + array( + 'is_in_stock' => $this->_inventory->getIsInStock(), + 'qty' => $this->_inventory->getQty(), + ) + ); + return parent::afterLoad($object); + } + + /** + * Prepare inventory data from custom atribute + * + * @param Varien_Object $object + * @return Mage_Eav_Model_Entity_Attribute_Backend_Abstract|void + */ + public function beforeSave($object) + { + /** @var $object Mage_Catalog_Model_Product */ + $stockData = $object->getData($this->getAttribute()->getAttributeCode()); + if ($object->getStockData() !== null || $stockData !== null) { + $object->setStockData(array_replace((array)$object->getStockData(), (array)$stockData)); + } + $object->unsetData($this->getAttribute()->getAttributeCode()); + parent::beforeSave($object); + } +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product.php b/app/code/core/Mage/Catalog/Model/Resource/Product.php index f6b8ebdcb8dc192407af89b5469d445126cdc7da..31567d11f6579fa1d7f0e55f5affe1410d74ae73 100755 --- a/app/code/core/Mage/Catalog/Model/Resource/Product.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Product.php @@ -191,7 +191,6 @@ class Mage_Catalog_Model_Resource_Product extends Mage_Catalog_Model_Resource_Ab { $this->_saveWebsiteIds($product) ->_saveCategories($product); - return parent::_afterSave($product); } @@ -692,4 +691,4 @@ class Mage_Catalog_Model_Resource_Product extends Mage_Catalog_Model_Resource_Ab $images = $read->fetchAll($select); return $images; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.17-1.6.0.0.18.php b/app/code/core/Mage/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.17-1.6.0.0.18.php new file mode 100644 index 0000000000000000000000000000000000000000..2fd31f8f84aedf9188e37d857148ba27723a359e --- /dev/null +++ b/app/code/core/Mage/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.17-1.6.0.0.18.php @@ -0,0 +1,55 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Catalog + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $this Mage_Catalog_Model_Resource_Setup */ + +$attribute = $this->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'category_ids'); + +if ($attribute) { + $this->addAttributeToSet( + $attribute['entity_type_id'], + $this->getAttributeSetId($attribute['entity_type_id'], 'Minimal'), + $this->getGeneralGroupName(), + $attribute['attribute_id'] + ); + $properties = array( + 'sort_order' => 9, + 'is_visible' => true, + 'frontend_label' => 'Categories', + 'input' => 'categories', + 'group' => 'General Information', + 'backend_model' => 'Mage_Catalog_Model_Product_Attribute_Backend_Category', + 'frontend_input_renderer' => 'Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Category', + ); + foreach ($properties as $key => $value) { + $this->updateAttribute( + $attribute['entity_type_id'], + $attribute['attribute_id'], + $key, + $value + ); + } +} diff --git a/app/code/core/Mage/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.18-1.6.0.0.19.php b/app/code/core/Mage/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.18-1.6.0.0.19.php new file mode 100644 index 0000000000000000000000000000000000000000..2ce817a8c860fa4c00e58b40da8a6020dc93b578 --- /dev/null +++ b/app/code/core/Mage/Catalog/data/catalog_setup/data-upgrade-1.6.0.0.18-1.6.0.0.19.php @@ -0,0 +1,54 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Catalog + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $this Mage_Catalog_Model_Resource_Setup */ + +$attribute = $this->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'image'); + +if ($attribute) { + $this->addAttributeToSet( + $attribute['entity_type_id'], + $this->getAttributeSetId($attribute['entity_type_id'], 'Minimal'), + $this->getGeneralGroupName(), + $attribute['attribute_id'], + 0 + ); + + $this->addAttributeToGroup( + $attribute['entity_type_id'], + $this->getAttributeSetId($attribute['entity_type_id'], 'Default'), + $this->getGeneralGroupName(), + $attribute['attribute_id'], + 0 + ); + + $this->updateAttribute( + $attribute['entity_type_id'], + $attribute['attribute_id'], + 'frontend_input_renderer', + 'Mage_Adminhtml_Block_Catalog_Product_Helper_Form_BaseImage' + ); +} diff --git a/app/code/core/Mage/Catalog/etc/config.xml b/app/code/core/Mage/Catalog/etc/config.xml index 94d0bcea86b3b694a992d9e868cbd04405982b4a..5b5e3daeb918c9484e30d077c21364f52890e15f 100644 --- a/app/code/core/Mage/Catalog/etc/config.xml +++ b/app/code/core/Mage/Catalog/etc/config.xml @@ -28,7 +28,7 @@ <config> <modules> <Mage_Catalog> - <version>1.6.0.0.17</version> + <version>1.6.0.0.19</version> <active>true</active> <codePool>core</codePool> <depends> @@ -211,6 +211,7 @@ </flat> <attributes> <unassignable> + <image/> <name/> <description/> <short_description/> @@ -219,6 +220,8 @@ <status/> <visibility/> <weight/> + <category_ids/> + <quantity_and_stock_status/> </unassignable> <used_in_autogeneration> <name/> diff --git a/app/code/core/Mage/Catalog/sql/catalog_setup/upgrade-1.6.0.0.17-1.6.0.0.18.php b/app/code/core/Mage/Catalog/sql/catalog_setup/upgrade-1.6.0.0.17-1.6.0.0.18.php new file mode 100644 index 0000000000000000000000000000000000000000..7cb575cf484f60e2eedc4f4132e509a3ecd71764 --- /dev/null +++ b/app/code/core/Mage/Catalog/sql/catalog_setup/upgrade-1.6.0.0.17-1.6.0.0.18.php @@ -0,0 +1,48 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Catalog + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $this Mage_Catalog_Model_Resource_Setup */ +$this->addAttribute(Mage_Catalog_Model_Product::ENTITY, 'quantity_and_stock_status', array( + 'group' => 'General', + 'type' => 'int', + 'backend' => 'Mage_Catalog_Model_Product_Attribute_Backend_Stock', + 'frontend' => '', + 'label' => 'Quantity', + 'input' => 'select', + 'class' => '', + 'input_renderer' => 'Mage_CatalogInventory_Block_Adminhtml_Form_Field_Stock', + 'source' => 'Mage_CatalogInventory_Model_Stock_Status', + 'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL, + 'default' => Mage_CatalogInventory_Model_Stock::STOCK_IN_STOCK, + 'user_defined' => false, + 'visible' => true, + 'required' => false, + 'searchable' => false, + 'filterable' => false, + 'comparable' => false, + 'unique' => false, + 'is_configurable' => false, +)); diff --git a/app/code/core/Mage/CatalogInventory/Block/Adminhtml/Form/Field/Stock.php b/app/code/core/Mage/CatalogInventory/Block/Adminhtml/Form/Field/Stock.php new file mode 100644 index 0000000000000000000000000000000000000000..fabec98ae872bd9a9125178ee99f9e2e5e05e00d --- /dev/null +++ b/app/code/core/Mage/CatalogInventory/Block/Adminhtml/Form/Field/Stock.php @@ -0,0 +1,213 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_CatalogInventory + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + + +/** + * HTML select element block + * + * @category Mage + * @package Mage_CatalogInventory + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_CatalogInventory_Block_Adminhtml_Form_Field_Stock extends Varien_Data_Form_Element_Select +{ + const QUANTITY_FIELD_HTML_ID = 'qty'; + + /** + * Quantity field element + * + * @var Varien_Data_Form_Element_Text + */ + protected $_qty; + + /** + * Is product composite (grouped or configurable) + * + * @var bool + */ + protected $_isProductComposite; + + public function __construct(array $data = array()) + { + $this->_qty = isset($data['qty']) ? $data['qty'] : $this->_createQtyElement(); + unset($data['qty']); + parent::__construct($data); + $this->setName($data['name']); + } + + /** + * Create quantity field + * + * @return Varien_Data_Form_Element_Text + */ + protected function _createQtyElement() + { + $element = Mage::getModel('Varien_Data_Form_Element_Text'); + $element->setId(self::QUANTITY_FIELD_HTML_ID)->setName('qty'); + return $element; + } + + /** + * Join quantity and in stock elements' html + * + * @return string + */ + public function getElementHtml() + { + $this->_disableFields(); + return $this->_qty->getElementHtml() . parent::getElementHtml() + . $this->_getJs(self::QUANTITY_FIELD_HTML_ID, $this->getId()); + } + + /** + * Set form to quantity element in addition to current element + * + * @param $form + * @return Varien_Data_Form + */ + public function setForm($form) + { + $this->_qty->setForm($form); + return parent::setForm($form); + } + + /** + * Set value to quantity element in addition to current element + * + * @param $value + * @return Varien_Data_Form_Element_Select + */ + public function setValue($value) + { + if (isset($value['qty'])) { + $this->_qty->setValue($value['qty']); + } + if (isset($value['is_in_stock'])) { + parent::setValue($value['is_in_stock']); + } + return $this; + } + + /** + * Set name to quantity element in addition to current element + * + * @param string $name + */ + public function setName($name) + { + $this->_qty->setName($name . '[qty]'); + parent::setName($name . '[is_in_stock]'); + } + + /** + * Get whether product is configurable or grouped + * + * @return bool + */ + protected function _isProductComposite() + { + if (null === $this->_isProductComposite) { + $this->_isProductComposite = $this->_qty->getForm()->getDataObject()->isComposite(); + } + return $this->_isProductComposite; + } + + /** + * Disable fields depending on product type + * + * @return Mage_CatalogInventory_Block_Adminhtml_Form_Field_Stock + */ + protected function _disableFields() + { + if (!$this->_isProductComposite() && null === $this->_qty->getValue()) { + $this->setDisabled('disabled'); + } + if ($this->_isProductComposite()) { + $this->_qty->setDisabled('disabled'); + } + return $this; + } + + /** + * Get js for quantity and in stock synchronisation + * + * @param $quantityFieldId + * @param $inStockFieldId + * @return string + */ + protected function _getJs($quantityFieldId, $inStockFieldId) + { + return " + <script> + //<![CDATA[ + jQuery(function($) { + var qty = $('#$quantityFieldId'); + var isInStock = $('#$inStockFieldId'); + var disabler = function(){ + if ('' === qty.val()) { + isInStock.attr('disabled', 'disabled'); + } else { + isInStock.removeAttr('disabled'); + } + }; + qty.bind('keyup change blur', disabler); + + //Associated fields + var fieldsAssociations = { + '$quantityFieldId' : 'inventory_qty', + '$inStockFieldId' : 'inventory_stock_availability' + }; + //Fill corresponding field + var filler = function() { + var id = $(this).attr('id'); + if ('undefined' !== typeof fieldsAssociations[id]) { + $('#' + fieldsAssociations[id]).val($(this).val()); + } else { + $('#' + getKeyByValue(fieldsAssociations, id)).val($(this).val()); + } + }; + //Get key by value form object + var getKeyByValue = function(object, value) { + var returnVal = false; + $.each(object, function(objKey, objValue){ + if (value === objValue) { + returnVal = objKey; + } + }); + return returnVal; + }; + $.each(fieldsAssociations, function(generalTabField, advancedTabField) { + $('#' + generalTabField + ', #' + advancedTabField) + .bind('focus blur change keyup click', filler); + filler.call($('#' + generalTabField)); + filler.call($('#' + advancedTabField)); + }); + }); + //]]> + </script> + "; + } +} diff --git a/app/code/core/Mage/CatalogInventory/Model/Stock/Status.php b/app/code/core/Mage/CatalogInventory/Model/Stock/Status.php index 77f5e84db3e97d59627b2846f93a822e60b9cb94..0bfb6e35aeef3ab96a6e6f7b3dfe1c14e525d078 100755 --- a/app/code/core/Mage/CatalogInventory/Model/Stock/Status.php +++ b/app/code/core/Mage/CatalogInventory/Model/Stock/Status.php @@ -536,4 +536,23 @@ class Mage_CatalogInventory_Model_Stock_Status extends Mage_Core_Model_Abstract $this->_getResource()->addIsInStockFilterToCollection($collection); return $this; } + + /** + * Get options for stock attribute in product creation + * + * @return array + */ + static public function getAllOptions() + { + return array( + array( + 'value' => Mage_CatalogInventory_Model_Stock::STOCK_IN_STOCK, + 'label' => Mage::helper('Mage_CatalogInventory_Helper_Data')->__('In Stock'), + ), + array( + 'value' => Mage_CatalogInventory_Model_Stock::STOCK_OUT_OF_STOCK, + 'label' => Mage::helper('Mage_CatalogInventory_Helper_Data')->__('Out of Stock') + ), + ); + } } diff --git a/app/code/core/Mage/CatalogSearch/Block/Layer/Filter/Attribute.php b/app/code/core/Mage/CatalogSearch/Block/Layer/Filter/Attribute.php index cdd775bcd0b30006c43c9910a967d0b3b6a6a67a..d2ec77ee4556eacd49985700ad0f7880644d29dd 100644 --- a/app/code/core/Mage/CatalogSearch/Block/Layer/Filter/Attribute.php +++ b/app/code/core/Mage/CatalogSearch/Block/Layer/Filter/Attribute.php @@ -34,9 +34,9 @@ class Mage_CatalogSearch_Block_Layer_Filter_Attribute extends Mage_Catalog_Block * Set filter model name * */ - protected function _construct() + public function __construct() { - parent::_construct(); - $this->_filterModelName = 'catalogsearch/layer_filter_attribute'; + parent::__construct(); + $this->_filterModelName = 'Mage_CatalogSearch_Model_Layer_Filter_Attribute'; } } diff --git a/app/code/core/Mage/Cms/Helper/Page.php b/app/code/core/Mage/Cms/Helper/Page.php index feada094239bee3ee438326841d156de4b5603e5..6810579fe5932638befbffc94befddb50965c182 100644 --- a/app/code/core/Mage/Cms/Helper/Page.php +++ b/app/code/core/Mage/Cms/Helper/Page.php @@ -52,14 +52,14 @@ class Mage_Cms_Helper_Page extends Mage_Core_Helper_Abstract return $this->_renderPage($action, $pageId); } - /** - * Renders CMS page - * - * @param Mage_Core_Controller_Front_Action $action - * @param integer $pageId - * @param bool $renderLayout - * @return boolean - */ + /** + * Renders CMS page + * + * @param Mage_Core_Controller_Front_Action|Mage_Core_Controller_Varien_Action $action + * @param integer $pageId + * @param bool $renderLayout + * @return boolean + */ protected function _renderPage(Mage_Core_Controller_Varien_Action $action, $pageId = null, $renderLayout = true) { @@ -103,7 +103,9 @@ class Mage_Cms_Helper_Page extends Mage_Core_Helper_Abstract $action->loadLayoutUpdates(); $layoutUpdate = ($page->getCustomLayoutUpdateXml() && $inRange) ? $page->getCustomLayoutUpdateXml() : $page->getLayoutUpdateXml(); - $action->getLayout()->getUpdate()->addUpdate($layoutUpdate); + if (!empty($layoutUpdate)) { + $action->getLayout()->getUpdate()->addUpdate($layoutUpdate); + } $action->generateLayoutXml()->generateLayoutBlocks(); $contentHeadingBlock = $action->getLayout()->getBlock('page_content_heading'); diff --git a/app/code/core/Mage/Core/Block/Abstract.php b/app/code/core/Mage/Core/Block/Abstract.php index 8c79d34a655f59c9e8279926fcc47d880ecbdeb2..d068d027a4d6580be960cea076b21a3fe8be5ca1 100644 --- a/app/code/core/Mage/Core/Block/Abstract.php +++ b/app/code/core/Mage/Core/Block/Abstract.php @@ -308,9 +308,6 @@ abstract class Mage_Core_Block_Abstract extends Varien_Object $this->unsetChild($alias); } if ($block instanceof self) { - if ($block->getIsAnonymous()) { - $block->setNameInLayout($this->getNameInLayout() . '.' . $alias); - } $block = $block->getNameInLayout(); } $layout->setChild($thisName, $block, $alias); @@ -319,10 +316,10 @@ abstract class Mage_Core_Block_Abstract extends Varien_Object } /** - * Create block and set as child + * Create block with name: {parent}.{alias} and set as child * * @param string $alias - * @param Mage_Core_Block_Abstract $block + * @param string $block * @param array $data * @return Mage_Core_Block_Abstract new block */ @@ -647,7 +644,7 @@ abstract class Mage_Core_Block_Abstract extends Varien_Object * Check framing options */ if ($this->_frameOpenTag) { - $html = '<'.$this->_frameOpenTag.'>'.$html.'<'.$this->_frameCloseTag.'>'; + $html = '<' . $this->_frameOpenTag . '>' . $html . '<' . $this->_frameCloseTag . '>'; } return $html; @@ -682,7 +679,7 @@ abstract class Mage_Core_Block_Abstract extends Varien_Object */ public function getUiId() { - return ' data-ui-id="' . call_user_func_array(array($this, 'getJsId'), func_get_args()). '" '; + return ' data-ui-id="' . call_user_func_array(array($this, 'getJsId'), func_get_args()) . '" '; } /** @@ -739,10 +736,28 @@ abstract class Mage_Core_Block_Abstract extends Varien_Object * @param string $file path to file in theme * @param array $params * @return string + * @throws Magento_Exception */ public function getViewFileUrl($file = null, array $params = array()) { - return Mage::getDesign()->getViewFileUrl($file, $params); + try { + return Mage::getDesign()->getViewFileUrl($file, $params); + } catch (Magento_Exception $e) { + Mage::logException($e); + return $this->_getNotFoundUrl(); + } + } + + /** + * Get 404 file not found url + * + * @param string $route + * @param array $params + * @return string + */ + protected function _getNotFoundUrl($route = '', $params = array('_direct' => 'core/index/notfound')) + { + return $this->getUrl($route, $params); } /** diff --git a/app/code/core/Mage/Core/Controller/Varien/Action.php b/app/code/core/Mage/Core/Controller/Varien/Action.php index f30fa6121fd55f71bdfd66377286eef3c676c1a3..edc727d62a6395acce9fb80f9093ac6a37458804 100755 --- a/app/code/core/Mage/Core/Controller/Varien/Action.php +++ b/app/code/core/Mage/Core/Controller/Varien/Action.php @@ -215,18 +215,16 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle * @param string $flag * @return bool */ - public function getFlag($action, $flag='') + public function getFlag($action, $flag = '') { - if (''===$action) { + if ('' === $action) { $action = $this->getRequest()->getActionName(); } - if (''===$flag) { + if ('' === $flag) { return $this->_flags; - } - elseif (isset($this->_flags[$action][$flag])) { + } elseif (isset($this->_flags[$action][$flag])) { return $this->_flags[$action][$flag]; - } - else { + } else { return false; } } @@ -241,7 +239,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle */ public function setFlag($action, $flag, $value) { - if (''===$action) { + if ('' === $action) { $action = $this->getRequest()->getActionName(); } $this->_flags[$action][$flag] = $value; @@ -255,7 +253,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle * @param string $delimiter * @return string */ - public function getFullActionName($delimiter='_') + public function getFullActionName($delimiter = '_') { return $this->getRequest()->getRequestedRouteName().$delimiter. $this->getRequest()->getRequestedControllerName().$delimiter. @@ -283,7 +281,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle public function loadLayout($handles = null, $generateBlocks = true, $generateXml = true) { // if handles were specified in arguments load them first - if (false!==$handles && ''!==$handles) { + if (false !== $handles && '' !== $handles) { $this->getLayout()->getUpdate()->addHandle($handles ? $handles : 'default'); } @@ -353,7 +351,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle // dispatch event for adding handles to layout update Mage::dispatchEvent( 'controller_action_layout_load_before', - array('action'=>$this, 'layout'=>$this->getLayout()) + array('action' => $this, 'layout' => $this->getLayout()) ); // load layout updates by specified handles @@ -370,10 +368,10 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle Magento_Profiler::start('LAYOUT'); // dispatch event for adding text layouts - if(!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) { + if (!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) { Mage::dispatchEvent( 'controller_action_layout_generate_xml_before', - array('action'=>$this, 'layout'=>$this->getLayout()) + array('action' => $this, 'layout' => $this->getLayout()) ); } @@ -394,7 +392,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle if(!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) { Mage::dispatchEvent( 'controller_action_layout_generate_blocks_before', - array('action'=>$this, 'layout'=>$this->getLayout()) + array('action' => $this, 'layout' => $this->getLayout()) ); } @@ -403,10 +401,10 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle $this->getLayout()->generateElements(); Magento_Profiler::stop('layout_generate_blocks'); - if(!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) { + if (!$this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) { Mage::dispatchEvent( 'controller_action_layout_generate_blocks_after', - array('action'=>$this, 'layout'=>$this->getLayout()) + array('action' => $this, 'layout' => $this->getLayout()) ); } @@ -420,7 +418,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle * @param string $output * @return Mage_Core_Controller_Varien_Action */ - public function renderLayout($output='') + public function renderLayout($output = '') { if ($this->getFlag('', 'no-renderLayout')) { return; @@ -436,14 +434,13 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle Magento_Profiler::start('layout_render'); - if (''!==$output) { + if ('' !== $output) { $this->getLayout()->addOutputElement($output); } Mage::dispatchEvent('controller_action_layout_render_before'); - Mage::dispatchEvent('controller_action_layout_render_before_'.$this->getFullActionName()); + Mage::dispatchEvent('controller_action_layout_render_before_' . $this->getFullActionName()); - #ob_implicit_flush(); $this->getLayout()->setDirectOutput(false); $output = $this->getLayout()->getOutput(); @@ -489,8 +486,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle } Magento_Profiler::stop($profilerKey); - } - catch (Mage_Core_Controller_Varien_Exception $e) { + } catch (Mage_Core_Controller_Varien_Exception $e) { // set prepared flags foreach ($e->getResultFlags() as $flagData) { list($action, $flag, $value) = $flagData; @@ -579,7 +575,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle /** * Dispatch event before action * - * @return void + * @return null */ public function preDispatch() { @@ -622,8 +618,6 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle /** * Fire predispatch events, execute extra logic after predispatch - * - * @return void */ protected function _firePreDispatchEvents() { @@ -644,14 +638,14 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle } Mage::dispatchEvent( - 'controller_action_postdispatch_'.$this->getFullActionName(), - array('controller_action'=>$this) + 'controller_action_postdispatch_' . $this->getFullActionName(), + array('controller_action' => $this) ); Mage::dispatchEvent( - 'controller_action_postdispatch_'.$this->getRequest()->getRouteName(), - array('controller_action'=>$this) + 'controller_action_postdispatch_' . $this->getRequest()->getRouteName(), + array('controller_action' => $this) ); - Mage::dispatchEvent('controller_action_postdispatch', array('controller_action'=>$this)); + Mage::dispatchEvent('controller_action_postdispatch', array('controller_action' => $this)); } public function norouteAction($coreRoute = null) @@ -661,11 +655,12 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle $status = new Varien_Object(); } - Mage::dispatchEvent('controller_action_noroute', array('action'=>$this, 'status'=>$status)); + Mage::dispatchEvent('controller_action_noroute', array('action' => $this, 'status' => $status)); if ($status->getLoaded() !== true || $status->getForwarded() === true - || !is_null($coreRoute) ) { + || !is_null($coreRoute) + ) { $this->loadLayout(array('default', 'noRoute')); $this->renderLayout(); } else { @@ -688,11 +683,9 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle if ($url = $redirect->getRedirectUrl()) { $this->_redirectUrl($url); - } - elseif ($redirect->getRedirect()) { + } elseif ($redirect->getRedirect()) { $this->_redirect($redirect->getPath(), $redirect->getArguments()); - } - else { + } else { $this->loadLayout(array('default', 'noCookie')); $this->renderLayout(); } @@ -749,10 +742,9 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle $block->addMessages($storage->getMessages(true)); $block->setEscapeMessageFlag($storage->getEscapeMessages(true)); $block->addStorageType($storageName); - } - else { + } else { Mage::throwException( - Mage::helper('Mage_Core_Helper_Data')->__('Invalid messages storage "%s" for layout messages initialization', (string) $storageName) + Mage::helper('Mage_Core_Helper_Data')->__('Invalid messages storage "%s" for layout messages initialization', (string)$storageName) ); } } @@ -883,13 +875,16 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle protected function _getRefererUrl() { $refererUrl = $this->getRequest()->getServer('HTTP_REFERER'); - if ($url = $this->getRequest()->getParam(self::PARAM_NAME_REFERER_URL)) { + $url = $this->getRequest()->getParam(self::PARAM_NAME_REFERER_URL); + if ($url) { $refererUrl = $url; } - if ($url = $this->getRequest()->getParam(self::PARAM_NAME_BASE64_URL)) { + $url = $this->getRequest()->getParam(self::PARAM_NAME_BASE64_URL); + if ($url) { $refererUrl = Mage::helper('Mage_Core_Helper_Data')->urlDecode($url); } - if ($url = $this->getRequest()->getParam(self::PARAM_NAME_URL_ENCODED)) { + $url = $this->getRequest()->getParam(self::PARAM_NAME_URL_ENCODED); + if ($url) { $refererUrl = Mage::helper('Mage_Core_Helper_Data')->urlDecode($url); } @@ -970,28 +965,28 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle $controller = $this->getRequest()->getControllerName(); $action = $this->getRequest()->getActionName(); - $rewrite = Mage::getConfig()->getNode('global/routers/'.$route.'/rewrite/'.$controller); + $rewrite = Mage::getConfig()->getNode('global/routers/' . $route . '/rewrite/' . $controller); if (!$rewrite) { return false; } if (!($rewrite->actions && $rewrite->actions->$action) || $rewrite->is('override_actions')) { $t = explode('/', (string)$rewrite->to); - if (sizeof($t)!==2 || empty($t[0]) || empty($t[1])) { + if (sizeof($t) !== 2 || empty($t[0]) || empty($t[1])) { return false; } $t[2] = $action; } else { $t = explode('/', (string)$rewrite->actions->$action->to); - if (sizeof($t)!==3 || empty($t[0]) || empty($t[1]) || empty($t[2])) { + if (sizeof($t) !== 3 || empty($t[0]) || empty($t[1]) || empty($t[2])) { return false; } } $this->_forward( - $t[2]==='*' ? $action : $t[2], - $t[1]==='*' ? $controller : $t[1], - $t[0]==='*' ? $route : $t[0] + $t[2] === '*' ? $action : $t[2], + $t[1] === '*' ? $controller : $t[1], + $t[0] === '*' ? $route : $t[0] ); return true; @@ -1005,7 +1000,8 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle protected function _validateFormKey() { if (!($formKey = $this->getRequest()->getParam('form_key', null)) - || $formKey != Mage::getSingleton('Mage_Core_Model_Session')->getFormKey()) { + || $formKey != Mage::getSingleton('Mage_Core_Model_Session')->getFormKey() + ) { return false; } return true; diff --git a/app/code/core/Mage/Core/Model/Layout.php b/app/code/core/Mage/Core/Model/Layout.php index 7cf32306c152df91800b8778a98472604cd520b9..16c11eb06dd4d0113e33ef8e7c680f85599a5b8e 100644 --- a/app/code/core/Mage/Core/Model/Layout.php +++ b/app/code/core/Mage/Core/Model/Layout.php @@ -1237,10 +1237,8 @@ class Mage_Core_Model_Layout extends Varien_Simplexml_Config */ public function createBlock($type, $name = '', array $attributes = array()) { - $isAnonymousBlock = empty($name); $name = $this->_createStructuralElement($name, self::TYPE_BLOCK, $type); $block = $this->_createBlock($type, $name, $attributes); - $block->setIsAnonymous($isAnonymousBlock); return $block; } diff --git a/app/code/core/Mage/Core/Model/Resource/Session.php b/app/code/core/Mage/Core/Model/Resource/Session.php index fced3db7a26f5bcc209c5e8fb0808eaf63b15ea2..ec65534b56dde909993744c36de46839a431266f 100644 --- a/app/code/core/Mage/Core/Model/Resource/Session.php +++ b/app/code/core/Mage/Core/Model/Resource/Session.php @@ -150,9 +150,10 @@ class Mage_Core_Model_Resource_Session implements Zend_Session_SaveHandler_Inter $bind = array('session_id' => $sessionId); $data = $this->_write->fetchOne($select, $bind); - // if session data is a base64 encoded string - if (base64_decode($data, true) !== false) { - $data = base64_decode($data); + // check if session data is a base64 encoded string + $decodedData = base64_decode($data, true); + if ($decodedData !== false) { + $data = $decodedData; } return $data; } @@ -174,9 +175,10 @@ class Mage_Core_Model_Resource_Session implements Zend_Session_SaveHandler_Inter $exists = $this->_write->fetchOne($select, $bindValues); // encode session serialized data to prevent insertion of incorrect symbols + $sessionData = base64_encode($sessionData); $bind = array( 'session_expires' => time(), - 'session_data' => base64_encode($sessionData), + 'session_data' => $sessionData, ); if ($exists) { diff --git a/app/code/core/Mage/Core/controllers/IndexController.php b/app/code/core/Mage/Core/controllers/IndexController.php index ae0a7de8abe409947f9a764ef8d013a9007c74b2..e37e01e276602d08d271def4b7193a822189f86c 100644 --- a/app/code/core/Mage/Core/controllers/IndexController.php +++ b/app/code/core/Mage/Core/controllers/IndexController.php @@ -29,6 +29,16 @@ class Mage_Core_IndexController extends Mage_Core_Controller_Front_Action { function indexAction() { - + + } + + /** + * 404 not found action + */ + public function notFoundAction() + { + $this->getResponse()->setHeader('HTTP/1.1', '404 Not Found'); + $this->getResponse()->setHttpResponseCode(404); + $this->getResponse()->setBody($this->__('Requested resource not found')); } } diff --git a/app/code/core/Mage/Downloadable/Model/Observer.php b/app/code/core/Mage/Downloadable/Model/Observer.php index daa6aed5ae7ba89942a13ebe675166b5e87e6807..af934d18aeebaeba4b3750de16b40438c9523a5f 100644 --- a/app/code/core/Mage/Downloadable/Model/Observer.php +++ b/app/code/core/Mage/Downloadable/Model/Observer.php @@ -35,6 +35,19 @@ class Mage_Downloadable_Model_Observer { const XML_PATH_DISABLE_GUEST_CHECKOUT = 'catalog/downloadable/disable_guest_checkout'; + /** + * @var Mage_Core_Helper_Data + */ + protected $_helper; + + /** + * @param array $data + */ + public function __construct(array $data = array()) + { + $this->_helper = isset($data['helper']) ? $data['helper'] : Mage::helper('Mage_Core_Helper_Data'); + } + /** * Prepare product to save * @@ -70,7 +83,9 @@ class Mage_Downloadable_Model_Observer if ($product && $product->getTypeId() != Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) { return $this; } - if (Mage::getModel('Mage_Downloadable_Model_Link_Purchased')->load($orderItem->getId(), 'order_item_id')->getId()) { + $purchasedLink = Mage::getModel('Mage_Downloadable_Model_Link_Purchased') + ->load($orderItem->getId(), 'order_item_id'); + if ($purchasedLink->getId()) { return $this; } if (!$product) { @@ -253,7 +268,7 @@ class Mage_Downloadable_Model_Observer } /** - * Check is allowed guest checkuot if quote contain downloadable product(s) + * Check is allowed guest checkout if quote contain downloadable product(s) * * @param Varien_Event_Observer $observer * @return Mage_Downloadable_Model_Observer @@ -313,27 +328,48 @@ class Mage_Downloadable_Model_Observer foreach ($type->getLinks($currentProduct) as $link) { $linkData = $link->getData(); $downloadableData['link'][] = array( - 'file' => $linkData['link_file'], + 'is_delete' => false, + 'link_id' => null, + 'title' => $linkData['title'], 'is_shareable' => $linkData['is_shareable'], + 'sample' => array( + 'type' => $linkData['sample_type'], + 'url' => $linkData['sample_url'], + 'file' => $this->_helper->jsonEncode(array(array( + 'file' => $linkData['sample_file'], + 'name' => $linkData['sample_file'], + 'size' => 0, + 'status' => null, + ))) + ), + 'file' => $this->_helper->jsonEncode(array(array( + 'file' => $linkData['link_file'], + 'name' => $linkData['link_file'], + 'size' => 0, + 'status' => null, + ))), + 'type' => $linkData['link_type'], 'link_url' => $linkData['link_url'], + 'sort_order' => $linkData['sort_order'], 'number_of_downloads' => $linkData['number_of_downloads'], 'price' => $linkData['price'], - 'sample' => array( - 'file' => $linkData['sample_file'], - 'type' => $linkData['sample_type'], - 'url' => $linkData['sample_url']), - 'sort_order' => $linkData['sort_order'], - 'title' => $linkData['title'], - 'type' => $linkData['link_type'], ); } - foreach ($type->getSamples($currentProduct)->getData() as $sample) { + foreach ($type->getSamples($currentProduct) as $sample) { + $sampleData = $sample->getData(); $downloadableData['sample'][] = array( - 'file' => $sample['sample_file'], - 'sample_url' => $sample['sample_url'], - 'sort_order' => $sample['sort_order'], - 'title' => $sample['title'], - 'type' => $sample['sample_type'], + 'is_delete' => false, + 'sample_id' => null, + 'title' => $sampleData['title'], + 'type' => $sampleData['sample_type'], + 'file' => $this->_helper->jsonEncode(array(array( + 'file' => $sampleData['sample_file'], + 'name' => $sampleData['sample_file'], + 'size' => 0, + 'status' => null, + ))), + 'sample_url' => $sampleData['sample_url'], + 'sort_order' => $sampleData['sort_order'], ); } $newProduct->setDownloadableData($downloadableData); diff --git a/app/code/core/Mage/Eav/Model/Resource/Entity/Attribute.php b/app/code/core/Mage/Eav/Model/Resource/Entity/Attribute.php index b00b2d7d31b44d88b4e2dad751c78d21ff2609e8..1a1554c2eb4451dc900f7766bab3dda80dc30d1d 100755 --- a/app/code/core/Mage/Eav/Model/Resource/Entity/Attribute.php +++ b/app/code/core/Mage/Eav/Model/Resource/Entity/Attribute.php @@ -362,7 +362,7 @@ class Mage_Eav_Model_Resource_Entity_Attribute extends Mage_Core_Model_Resource_ return $this; } - $defaultValue = null; + $defaultValue = $object->getDefault() ?: array(); if (isset($option['value'])) { if (!is_array($object->getDefault())) { $object->setDefault(array()); diff --git a/app/code/core/Mage/Index/Model/Lock/Storage.php b/app/code/core/Mage/Index/Model/Lock/Storage.php new file mode 100644 index 0000000000000000000000000000000000000000..645e69fda5d1a54acda76b9e4657e57b1fa23ec0 --- /dev/null +++ b/app/code/core/Mage/Index/Model/Lock/Storage.php @@ -0,0 +1,81 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Index + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Lock file storage for index processes + */ +class Mage_Index_Model_Lock_Storage +{ + /** + * @var Mage_Core_Model_Config + */ + protected $_configuration; + + /** + * @var Mage_Index_Model_Process_FileFactory + */ + protected $_fileFactory; + + /** + * File handlers by process IDs + * + * @var array + */ + protected $_fileHandlers = array(); + + /** + * @param Mage_Core_Model_Config $configuration + * @param Mage_Index_Model_Process_FileFactory $fileFactory + */ + public function __construct( + Mage_Core_Model_Config $configuration, + Mage_Index_Model_Process_FileFactory $fileFactory + ) { + $this->_configuration = $configuration; + $this->_fileFactory = $fileFactory; + } + + /** + * Get file handler by process ID + * + * @param $processId + * @return Mage_Index_Model_Process_File + */ + public function getFile($processId) + { + if (!isset($this->_fileHandlers[$processId])) { + $file = $this->_fileFactory->createFromArray(); + $varDirectory = $this->_configuration->getVarDir('locks'); + $file->setAllowCreateFolders(true); + $file->open(array('path' => $varDirectory)); + $fileName = 'index_process_' . $processId . '.lock'; + $file->streamOpen($fileName); + $file->streamWrite(date('r')); + $this->_fileHandlers[$processId] = $file; + } + return $this->_fileHandlers[$processId]; + } +} diff --git a/app/code/core/Mage/Index/Model/Process.php b/app/code/core/Mage/Index/Model/Process.php index e5a531bd22f4a02530a1d50b035646134f977d2b..443167a2e988dabe2cfe37399074bbf59c4bd4db 100644 --- a/app/code/core/Mage/Index/Model/Process.php +++ b/app/code/core/Mage/Index/Model/Process.php @@ -77,10 +77,38 @@ class Mage_Index_Model_Process extends Mage_Core_Model_Abstract protected $_indexer = null; /** - * Process lock properties + * Lock file entity storage + * + * @var Mage_Index_Model_Lock_Storage + */ + protected $_lockStorage; + + /** + * Instance of current process file + * + * @var Mage_Index_Model_Process_File */ - protected $_isLocked = null; - protected $_lockFile = null; + protected $_processFile; + + /** + * @param Mage_Core_Model_Event_Manager $eventDispatcher + * @param Mage_Core_Model_Cache $cacheManager + * @param Mage_Core_Model_Resource_Abstract $resource + * @param Varien_Data_Collection_Db $resourceCollection + * @param Mage_Index_Model_Lock_Storage $lockStorage + * @param array $data + */ + public function __construct( + Mage_Core_Model_Event_Manager $eventDispatcher, + Mage_Core_Model_Cache $cacheManager, + Mage_Index_Model_Lock_Storage $lockStorage, + Mage_Core_Model_Resource_Abstract $resource = null, + Varien_Data_Collection_Db $resourceCollection = null, + array $data = array() + ) { + parent::__construct($eventDispatcher, $cacheManager, $resource, $resourceCollection, $data); + $this->_lockStorage = $lockStorage; + } /** * Initialize resource @@ -234,6 +262,7 @@ class Mage_Index_Model_Process extends Mage_Core_Model_Abstract $this->setForcePartialReindex(count($unprocessedEvents) > 0 && $this->getStatus() == self::STATUS_PENDING); if ($this->getDepends()) { + /** @var $indexer Mage_Index_Model_Indexer */ $indexer = Mage::getSingleton('Mage_Index_Model_Indexer'); foreach ($this->getDepends() as $code) { $process = $indexer->getProcessByCode($code); @@ -399,35 +428,27 @@ class Mage_Index_Model_Process extends Mage_Core_Model_Abstract } /** - * Get lock file resource + * Get process file instance * - * @return resource + * @return Mage_Index_Model_Process_File */ - protected function _getLockFile() + protected function _getProcessFile() { - if ($this->_lockFile === null) { - $varDir = Mage::getConfig()->getVarDir('locks'); - $file = $varDir . DS . 'index_process_'.$this->getId().'.lock'; - if (is_file($file)) { - $this->_lockFile = fopen($file, 'w'); - } else { - $this->_lockFile = fopen($file, 'x'); - } - fwrite($this->_lockFile, date('r')); + if (!$this->_processFile) { + $this->_processFile = $this->_lockStorage->getFile($this->getId()); } - return $this->_lockFile; + return $this->_processFile; } /** * Lock process without blocking. - * This method allow protect multiple process runing and fast lock validation. + * This method allow protect multiple process running and fast lock validation. * * @return Mage_Index_Model_Process */ public function lock() { - $this->_isLocked = true; - flock($this->_getLockFile(), LOCK_EX | LOCK_NB); + $this->_getProcessFile()->processLock(); return $this; } @@ -440,8 +461,7 @@ class Mage_Index_Model_Process extends Mage_Core_Model_Abstract */ public function lockAndBlock() { - $this->_isLocked = true; - flock($this->_getLockFile(), LOCK_EX); + $this->_getProcessFile()->processLock(false); return $this; } @@ -452,38 +472,19 @@ class Mage_Index_Model_Process extends Mage_Core_Model_Abstract */ public function unlock() { - $this->_isLocked = false; - flock($this->_getLockFile(), LOCK_UN); + $this->_getProcessFile()->processUnlock(); return $this; } /** - * Check if process is locked + * Check if process is locked by another user * + * @param bool $needUnlock * @return bool */ - public function isLocked() - { - if ($this->_isLocked !== null) { - return $this->_isLocked; - } else { - $fp = $this->_getLockFile(); - if (flock($fp, LOCK_EX | LOCK_NB)) { - flock($fp, LOCK_UN); - return false; - } - return true; - } - } - - /** - * Close file resource if it was opened - */ - public function __destruct() + public function isLocked($needUnlock = false) { - if ($this->_lockFile) { - fclose($this->_lockFile); - } + return $this->_getProcessFile()->isProcessLocked($needUnlock); } /** @@ -572,6 +573,7 @@ class Mage_Index_Model_Process extends Mage_Core_Model_Abstract * * @param Mage_Index_Model_Event $event * @return Mage_Index_Model_Process + * @throws Exception */ public function safeProcessEvent(Mage_Index_Model_Event $event) { diff --git a/app/code/core/Mage/Index/Model/Process/File.php b/app/code/core/Mage/Index/Model/Process/File.php new file mode 100644 index 0000000000000000000000000000000000000000..536473973bb40c3aa3746bd239d314d0abb27082 --- /dev/null +++ b/app/code/core/Mage/Index/Model/Process/File.php @@ -0,0 +1,101 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Index + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Process file entity + */ +class Mage_Index_Model_Process_File extends Varien_Io_File +{ + /** + * Process lock flag: + * - true - if process is already locked by another user + * - false - if process is locked by us + * - null - unknown lock status + * + * @var bool + */ + protected $_processLocked = null; + + /** + * Lock process file + * + * @param bool $nonBlocking + * @return bool + */ + public function processLock($nonBlocking = true) + { + if (!$this->_streamHandler) { + return false; + } + $this->_streamLocked = true; + $lock = LOCK_EX; + if ($nonBlocking) { + $lock = $lock | LOCK_NB; + } + $result = flock($this->_streamHandler, $lock); + // true if process is locked by other user + $this->_processLocked = !$result; + return $result; + } + + /** + * Unlock process file + * + * @return bool + */ + public function processUnlock() + { + $this->_processLocked = null; + return parent::streamUnlock(); + } + + /** + * Check if process is locked by another user + * + * @param bool $needUnlock + * @return bool|null + */ + public function isProcessLocked($needUnlock = false) + { + if (!$this->_streamHandler) { + return null; + } + + if ($this->_processLocked !== null) { + return $this->_processLocked; + } else { + if (flock($this->_streamHandler, LOCK_EX | LOCK_NB)) { + if ($needUnlock) { + flock($this->_streamHandler, LOCK_UN); + } else { + $this->_streamLocked = true; + } + return false; + } + return true; + } + } +} diff --git a/app/code/core/Mage/Index/Model/Process/FileFactory.php b/app/code/core/Mage/Index/Model/Process/FileFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..300338aab3a29837c9cbb32ca1e2659f3b420ab2 --- /dev/null +++ b/app/code/core/Mage/Index/Model/Process/FileFactory.php @@ -0,0 +1,58 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Index + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Process file entity + */ +class Mage_Index_Model_Process_FileFactory implements Magento_ObjectManager_Factory +{ + /** + * Entity class name + */ + const CLASS_NAME = 'Mage_Index_Model_Process_File'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * @param array $arguments + * @return Mage_Index_Model_Process_File + */ + public function createFromArray(array $arguments = array()) + { + return $this->_objectManager->create(self::CLASS_NAME, $arguments, false); + } +} diff --git a/app/code/core/Mage/Page/Block/Html/Head.php b/app/code/core/Mage/Page/Block/Html/Head.php index dcc556601a0025d22b21c0214cd4e94375dc5870..1c9ee12391724d8e6a6842ad3049a155d549824a 100644 --- a/app/code/core/Mage/Page/Block/Html/Head.php +++ b/app/code/core/Mage/Page/Block/Html/Head.php @@ -34,6 +34,11 @@ */ class Mage_Page_Block_Html_Head extends Mage_Core_Block_Template { + /** + * Block template + * + * @var string + */ protected $_template = 'html/head.phtml'; /** @@ -183,21 +188,19 @@ class Mage_Page_Block_Html_Head extends Mage_Core_Block_Template $params = ' ' . $params; } switch ($contentType) { - case 'css': - foreach (Mage::getDesign()->getOptimalCssUrls($items) as $url) { - $html .= sprintf('<link%s href="%s" />' . "\n", $params, $url); - } + case Mage_Core_Model_Design_Package::CONTENT_TYPE_CSS: + $html .= $this->_generateCssHtml($items, $params); break; - case 'js': - foreach (Mage::getDesign()->getOptimalJsUrls($items) as $url) { - $html .= sprintf('<script%s type="text/javascript" src="%s"></script>' . "\n", $params, $url); - } + case Mage_Core_Model_Design_Package::CONTENT_TYPE_JS: + $html .= $this->_generateJsHtml($items, $params); break; case 'link': foreach ($items as $file) { $html .= sprintf('<link%s href="%s" />' . "\n", $params, $file); } break; + default: + break; } if (!empty($if)) { $html .= '<![endif]-->' . "\n"; @@ -206,6 +209,48 @@ class Mage_Page_Block_Html_Head extends Mage_Core_Block_Template return $html; } + /** + * Generate css links + * + * @param array $items + * @param array $params + * @return string + */ + protected function _generateCssHtml($items, $params) + { + $html = ''; + $pattern = '<link%s href="%s" />' . "\n"; + try { + foreach (Mage::getDesign()->getOptimalCssUrls($items) as $url) { + $html .= sprintf($pattern, $params, $url); + } + } catch (Magento_Exception $e) { + $html .= sprintf($pattern, $params, $this->_getNotFoundUrl()); + } + return $html; + } + + /** + * Generate js links + * + * @param array $items + * @param array $params + * @return string + */ + protected function _generateJsHtml($items, $params) + { + $html = ''; + $pattern = '<script%s type="text/javascript" src="%s"></script>' . "\n"; + try { + foreach (Mage::getDesign()->getOptimalJsUrls($items) as $url) { + $html .= sprintf($pattern, $params, $url); + } + } catch (Magento_Exception $e) { + $html .= sprintf($pattern, $params, $this->_getNotFoundUrl()); + } + return $html; + } + /** * Retrieve Content Type * @@ -321,7 +366,7 @@ class Mage_Page_Block_Html_Head extends Mage_Core_Block_Template } /** - * Get miscellanious scripts/styles to be included in head before head closing tag + * Get miscellaneous scripts/styles to be included in head before head closing tag * * @return string */ diff --git a/app/code/core/Mage/Reports/Model/Resource/Report/Product/Viewed.php b/app/code/core/Mage/Reports/Model/Resource/Report/Product/Viewed.php index f9ea9587a2d9627c47fe974e0cd3dcf3c974a6a6..4b7dbb24ad18d215c569e73f217bded8f80168c2 100644 --- a/app/code/core/Mage/Reports/Model/Resource/Report/Product/Viewed.php +++ b/app/code/core/Mage/Reports/Model/Resource/Report/Product/Viewed.php @@ -34,9 +34,9 @@ */ class Mage_Reports_Model_Resource_Report_Product_Viewed extends Mage_Sales_Model_Resource_Report_Abstract { - const AGGREGATION_DAILY = 'reports_viewed_aggregated_daily'; - const AGGREGATION_MONTHLY = 'reports_viewed_aggregated_monthly'; - const AGGREGATION_YEARLY = 'reports_viewed_aggregated_yearly'; + const AGGREGATION_DAILY = 'report_viewed_product_aggregated_daily'; + const AGGREGATION_MONTHLY = 'report_viewed_product_aggregated_monthly'; + const AGGREGATION_YEARLY = 'report_viewed_product_aggregated_yearly'; /** * Model initialization diff --git a/app/code/core/Mage/Reports/etc/config.xml b/app/code/core/Mage/Reports/etc/config.xml index 734826eb3b953ba0107ccbbc10d58e7021fd37b3..4fcb0458d44e55ceffcf1a8d43e1c97a5d1d3e61 100644 --- a/app/code/core/Mage/Reports/etc/config.xml +++ b/app/code/core/Mage/Reports/etc/config.xml @@ -28,7 +28,7 @@ <config> <modules> <Mage_Reports> - <version>1.6.0.0.1</version> + <version>1.6.0.0.2</version> <active>true</active> <codePool>core</codePool> <depends> @@ -184,4 +184,4 @@ </dashboard> </reports> </default> -</config> \ No newline at end of file +</config> diff --git a/app/code/core/Mage/Reports/sql/reports_setup/upgrade-1.6.0.0.1-1.6.0.0.2.php b/app/code/core/Mage/Reports/sql/reports_setup/upgrade-1.6.0.0.1-1.6.0.0.2.php new file mode 100644 index 0000000000000000000000000000000000000000..2e790a9810b860dd7872ed858eb773028cbd8792 --- /dev/null +++ b/app/code/core/Mage/Reports/sql/reports_setup/upgrade-1.6.0.0.1-1.6.0.0.2.php @@ -0,0 +1,46 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage_Reports + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $installer Mage_Core_Model_Resource_Setup */ +$installer = $this; +/* + * Rename incorrectly named tables in early magento 2 development version + */ +$installer->startSetup(); + +$aggregationTablesToRename = array( + 'reports_viewed_aggregated_daily' => Mage_Reports_Model_Resource_Report_Product_Viewed::AGGREGATION_DAILY, + 'reports_viewed_aggregated_monthly' => Mage_Reports_Model_Resource_Report_Product_Viewed::AGGREGATION_MONTHLY, + 'reports_viewed_aggregated_yearly' => Mage_Reports_Model_Resource_Report_Product_Viewed::AGGREGATION_YEARLY, +); + +foreach ($aggregationTablesToRename as $wrongName => $rightName) { + if ($installer->tableExists($wrongName)) { + $installer->getConnection()->renameTable($installer->getTable($wrongName), $installer->getTable($rightName)); + } +} + +$installer->endSetup(); diff --git a/app/code/core/Mage/Sales/Block/Adminhtml/Report/Filter/Form/Coupon.php b/app/code/core/Mage/Sales/Block/Adminhtml/Report/Filter/Form/Coupon.php index 11e5d826cd3a5d8f04b65b045794529c32c3481e..6e9c1639798fdd2de5c3369953c2c03fb59614e6 100644 --- a/app/code/core/Mage/Sales/Block/Adminhtml/Report/Filter/Form/Coupon.php +++ b/app/code/core/Mage/Sales/Block/Adminhtml/Report/Filter/Form/Coupon.php @@ -33,6 +33,13 @@ */ class Mage_Sales_Block_Adminhtml_Report_Filter_Form_Coupon extends Mage_Sales_Block_Adminhtml_Report_Filter_Form { + /** + * Flag that keep info should we render specific dependent element or not + * + * @var bool + */ + protected $_renderDependentElement = false; + /** * Prepare form * @@ -42,9 +49,6 @@ class Mage_Sales_Block_Adminhtml_Report_Filter_Form_Coupon extends Mage_Sales_Bl { parent::_prepareForm(); - $form = $this->getForm(); - $htmlIdPrefix = $form->getHtmlIdPrefix(); - /** @var Varien_Data_Form_Element_Fieldset $fieldset */ $fieldset = $this->getForm()->getElement('base_fieldset'); @@ -77,13 +81,39 @@ class Mage_Sales_Block_Adminhtml_Report_Filter_Form_Coupon extends Mage_Sales_Bl 'display' => 'none' ), 'price_rule_type'); - $this->setChild('form_after', $this->getLayout()->createBlock('Mage_Adminhtml_Block_Widget_Form_Element_Dependence') - ->addFieldMap($htmlIdPrefix . 'price_rule_type', 'price_rule_type') - ->addFieldMap($htmlIdPrefix . 'rules_list', 'rules_list') - ->addFieldDependence('rules_list', 'price_rule_type', '1') - ); + $this->_renderDependentElement = true; } return $this; } + + /** + * Processing block html after rendering + * + * @param string $html + * @return string + */ + protected function _afterToHtml($html) + { + if ($this->_renderDependentElement) { + $form = $this->getForm(); + $htmlIdPrefix = $form->getHtmlIdPrefix(); + + /** + * Form template has possibility to render child block 'form_after', but we can't use it because parent + * form creates appropriate child block and uses this alias. In this case we can't use the same alias + * without core logic changes, that's why the code below was moved inside method '_afterToHtml'. + */ + /** @var $formAfterBlock Mage_Adminhtml_Block_Widget_Form_Element_Dependence */ + $formAfterBlock = $this->getLayout()->createBlock('Mage_Adminhtml_Block_Widget_Form_Element_Dependence', + 'adminhtml.block.widget.form.element.dependence' + ); + $formAfterBlock->addFieldMap($htmlIdPrefix . 'price_rule_type', 'price_rule_type') + ->addFieldMap($htmlIdPrefix . 'rules_list', 'rules_list') + ->addFieldDependence('rules_list', 'price_rule_type', '1'); + $html = $html . $formAfterBlock->toHtml(); + } + + return $html; + } } diff --git a/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php b/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php index 29957b4c98d0956e0038651c5d59978f3f37df13..d66ae96759be37603cb9802d968de6feee1dc5c6 100644 --- a/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php +++ b/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php @@ -177,6 +177,16 @@ class Mage_Sales_Model_Order_Shipment_Track extends Mage_Sales_Model_Abstract return Mage::app()->getStore(); } + /** + * Get store id + * + * @return int + */ + public function getStoreId() + { + return $this->getStore()->getId(); + } + /** * Before object save * diff --git a/app/code/core/Mage/SalesRule/Model/Resource/Report/Rule.php b/app/code/core/Mage/SalesRule/Model/Resource/Report/Rule.php index 9df8497b10fba0f95306e7044bb2366aa3f769ca..f8b5ed30fd4f59a0080a8507b86a4eba77352376 100755 --- a/app/code/core/Mage/SalesRule/Model/Resource/Report/Rule.php +++ b/app/code/core/Mage/SalesRule/Model/Resource/Report/Rule.php @@ -74,7 +74,7 @@ class Mage_SalesRule_Model_Resource_Report_Rule extends Mage_Reports_Model_Resou new Zend_Db_Expr('DISTINCT rule_name') ) ->where('rule_name IS NOT NULL') - ->where('rule_name <> ""') + ->where('rule_name <> ?', '') ->order('rule_name ASC'); $rulesNames = $adapter->fetchAll($select); diff --git a/app/code/core/Mage/Theme/etc/config.xml b/app/code/core/Mage/Theme/etc/config.xml index d36e4c1ae93271e1127e72713b3f27f6aaf0c2c6..697953bfe90736de7524768b36747afcda9cfc96 100644 --- a/app/code/core/Mage/Theme/etc/config.xml +++ b/app/code/core/Mage/Theme/etc/config.xml @@ -46,15 +46,6 @@ </routers> </admin> <adminhtml> - <translate> - <modules> - <Mage_Theme> - <files> - <default>Mage_Theme.csv</default> - </files> - </Mage_Theme> - </modules> - </translate> <layout> <updates> <theme module="Mage_Theme"> diff --git a/app/code/core/Mage/Theme/locale/de_DE/Mage_Theme.csv b/app/code/core/Mage/Theme/locale/de_DE/Mage_Theme.csv deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/code/core/Mage/Theme/locale/en_US/Mage_Theme.csv b/app/code/core/Mage/Theme/locale/en_US/Mage_Theme.csv deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/code/core/Mage/Theme/locale/es_ES/Mage_Theme.csv b/app/code/core/Mage/Theme/locale/es_ES/Mage_Theme.csv deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/code/core/Mage/Theme/locale/fr_FR/Mage_Theme.csv b/app/code/core/Mage/Theme/locale/fr_FR/Mage_Theme.csv deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/code/core/Mage/Theme/locale/nl_NL/Mage_Theme.csv b/app/code/core/Mage/Theme/locale/nl_NL/Mage_Theme.csv deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/code/core/Mage/Theme/locale/pt_BR/Mage_Theme.csv b/app/code/core/Mage/Theme/locale/pt_BR/Mage_Theme.csv deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/app/code/core/Mage/Theme/locale/zh_CN/Mage_Theme.csv b/app/code/core/Mage/Theme/locale/zh_CN/Mage_Theme.csv deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/dev/build/publication/extruder/ce.txt b/dev/build/publication/extruder/ce.txt index d3c75b75ad2c95b5b0e04f06a0eed58ef613632d..c557d608ff99001e21da91edd815177622d46c25 100644 --- a/dev/build/publication/extruder/ce.txt +++ b/dev/build/publication/extruder/ce.txt @@ -36,6 +36,7 @@ dev/tests/integration/etc/modules/XEnterprise_Enabler.xml dev/tests/integration/testsuite/Enterprise dev/tests/integration/testsuite/integrity/modular/ViewFilesTest.php dev/tests/integration/testsuite/integrity/theme/RenderersTest.php +dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/_files/customer_composite_update_reward.csv dev/tests/integration/testsuite/Theme dev/tests/static/testsuite/Integrity/Enterprise dev/tests/static/testsuite/Legacy/ProductTypeModelTest.php @@ -48,6 +49,7 @@ dev/tests/static/testsuite/Php/_files/{whitelist,blacklist}/ee.txt dev/tests/unit/testsuite/Enterprise dev/tools/migration/factory_table_names/replace_ee.php dev/tools/migration/aliases_map/composite_modules_ee.php +dev/tools/migration/aliases_map/cms_content_tables_ee.php downloader/Maged/Model/Config/Enterprise.php downloader/Maged/Model/Config/Professional.php downloader/skin/install/images/enterprise.gif diff --git a/dev/tests/integration/framework/Magento/Test/ClearProperties.php b/dev/tests/integration/framework/Magento/Test/ClearProperties.php new file mode 100644 index 0000000000000000000000000000000000000000..5245193ce08788031a66473e42aa3807a5c68521 --- /dev/null +++ b/dev/tests/integration/framework/Magento/Test/ClearProperties.php @@ -0,0 +1,55 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Clear test method properties, it isn't needed to unset properties manually in tearDown() anymore + */ +class Magento_Test_ClearProperties +{ + /** + * Clear test method properties after each test suite + * + * @param PHPUnit_Framework_TestSuite $suite + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $tests = $suite->tests(); + + foreach ($tests as $test) { + $reflectionClass = new ReflectionClass($test); + $properties = $reflectionClass->getProperties(); + foreach ($properties as $property) { + $property->setAccessible(true); + $value = $property->getValue($test); + if (is_object($value) && method_exists($value, '__destruct')) { + $value->__destruct(); + } + $property->setValue($test, null); + } + } + } +} diff --git a/dev/tests/integration/framework/Magento/Test/Event/PhpUnit.php b/dev/tests/integration/framework/Magento/Test/Event/PhpUnit.php index e8ed31281c830597ecbcd0d2f4961dd3b400f279..9b4b936e290569cd95104d4452f4194edd72b2b6 100644 --- a/dev/tests/integration/framework/Magento/Test/Event/PhpUnit.php +++ b/dev/tests/integration/framework/Magento/Test/Event/PhpUnit.php @@ -153,7 +153,7 @@ class Magento_Test_Event_PhpUnit implements PHPUnit_Framework_TestListener if ($suite instanceof PHPUnit_Framework_TestSuite_DataProvider) { return; } - $this->_eventManager->fireEvent('endTestSuite', array(), true); + $this->_eventManager->fireEvent('endTestSuite', array($suite), true); } /** diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php index 8bc39d41230938c24e9c964fc899bcf46f33e56f..2a57c3bfaa2cce0e29381997b8f885805855b758 100644 --- a/dev/tests/integration/framework/bootstrap.php +++ b/dev/tests/integration/framework/bootstrap.php @@ -91,6 +91,7 @@ if (defined('TESTS_BAMBOO_PROFILER_FILE') && defined('TESTS_BAMBOO_PROFILER_METR * To allow config fixtures to deal with fixture stores, data fixtures should be processed before config fixtures. */ $eventManager = new Magento_Test_EventManager(array( + new Magento_Test_ClearProperties(), new Magento_Test_Annotation_AppIsolation(), new Magento_Test_Event_Transaction(new Magento_Test_EventManager(array( new Magento_Test_Annotation_DbIsolation(), diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/ClearPropertiesTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/ClearPropertiesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2e04fa483288075fe02ebab72601c17942c817f3 --- /dev/null +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/ClearPropertiesTest.php @@ -0,0 +1,118 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for Magento_Test_ClearProperties. + */ +class Magento_Test_ClearPropertiesTest extends PHPUnit_Framework_TestCase +{ + /** + * @var array + */ + protected $_properties = array( + array( + 'name' => 'testPublic', + 'is_static' => false, + 'expectedValue' => 'public', + ), + array( + 'name' => '_testPrivate', + 'is_static' => false, + 'expectedValue' => 'private', + ), + array( + 'name' => '_testPropertyBoolean', + 'is_static' => false, + 'expectedValue' => true, + ), + array( + 'name' => '_testPropertyInteger', + 'is_static' => false, + 'expectedValue' => 10, + ), + array( + 'name' => '_testPropertyFloat', + 'is_static' => false, + 'expectedValue' => 1.97, + ), + array( + 'name' => '_testPropertyString', + 'is_static' => false, + 'expectedValue' => 'string', + ), + array( + 'name' => '_testPropertyArray', + 'is_static' => false, + 'expectedValue' => array('test', 20), + ), + array( + 'name' => 'testPublicStatic', + 'is_static' => true, + 'expectedValue' => 'static public', + ), + array( + 'name' => '_testProtectedStatic', + 'is_static' => true, + 'expectedValue' => 'static protected', + ), + array( + 'name' => '_testPrivateStatic', + 'is_static' => true, + 'expectedValue' => 'static private', + ), + ); + + public function testEndTestSuiteDestruct() + { + $clearProperties = new Magento_Test_ClearProperties(); + $phpUnitTestSuite = new PHPUnit_Framework_TestSuite(); + $phpUnitTestSuite->addTestFile(__DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR + . 'DummyTestCase.php' + ); + // Because addTestFile() adds classes from file to tests array, use first testsuite + /** @var $testSuite PHPUnit_Framework_TestSuite */ + $testSuite = $phpUnitTestSuite->testAt(0); + $testSuite->run(); + $testClass = $testSuite->testAt(0); + foreach ($this->_properties as $property) { + if ($property['is_static']) { + $this->assertAttributeEquals($property['expectedValue'], $property['name'], get_class($testClass)); + } else { + $this->assertAttributeEquals($property['expectedValue'], $property['name'], $testClass); + } + } + $clearProperties->endTestSuite($testSuite); + $this->assertTrue(Magento_Test_ClearProperties_Stub::$isDestructCalled); + foreach ($this->_properties as $property) { + if ($property['is_static']) { + $this->assertAttributeEmpty($property['name'], get_class($testClass)); + } else { + $this->assertAttributeEmpty($property['name'], $testClass); + } + } + } +} diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/_files/DummyTestCase.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/_files/DummyTestCase.php new file mode 100644 index 0000000000000000000000000000000000000000..3ba8d49817386bdfe31c0ade5ccb645386d56e96 --- /dev/null +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/_files/DummyTestCase.php @@ -0,0 +1,89 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +require_once __DIR__ . DIRECTORY_SEPARATOR . 'Stub.php'; + +class Magento_Test_ClearProperties_DummyTestCase extends PHPUnit_Framework_TestCase +{ + /** + * @var string + */ + public $testPublic; + private $_testPrivate; + + /** + * @var boolean + */ + protected $_testPropertyBoolean; + + /** + * @var integer + */ + protected $_testPropertyInteger; + + /** + * @var float + */ + protected $_testPropertyFloat; + + /** + * @var string + */ + protected $_testPropertyString; + + /** + * @var array + */ + protected $_testPropertyArray; + + /** + * @var mixed + */ + protected $_testPropertyObject; + + /** + * @var string + */ + static public $testPublicStatic; + static protected $_testProtectedStatic; + static private $_testPrivateStatic; + + public function testDummy() + { + $this->testPublic = 'public'; + $this->_testPrivate = 'private'; + $this->_testPropertyBoolean = true; + $this->_testPropertyInteger = 10; + $this->_testPropertyFloat = 1.97; + $this->_testPropertyString = 'string'; + $this->_testPropertyArray = array('test', 20); + $this->_testPropertyObject = new Magento_Test_ClearProperties_Stub(); + self::$testPublicStatic = 'static public'; + self::$_testProtectedStatic = 'static protected'; + self::$_testPrivateStatic = 'static private'; + } +} diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/_files/Stub.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/_files/Stub.php new file mode 100644 index 0000000000000000000000000000000000000000..1a6462e654ae0c9a0c8fa2ee07db453aa1708987 --- /dev/null +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/_files/Stub.php @@ -0,0 +1,39 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Magento_Test_ClearProperties_Stub +{ + /** + * @var boolean + */ + public static $isDestructCalled = false; + + public function __destruct() + { + self::$isDestructCalled = true; + } +} diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/ConfigTest.php b/dev/tests/integration/testsuite/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/ConfigTest.php index aa1ee06d3305fc27ecc5108c0a3c2be881727730..d70bce6f211a7193bdf4d7010f10c36ba16306df 100644 --- a/dev/tests/integration/testsuite/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/ConfigTest.php +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/ConfigTest.php @@ -39,4 +39,22 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_ConfigTest extends PHP $block = $layout->createBlock('Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config', 'block'); $this->assertEquals('super_product_linksJsObject', $block->getGridJsObject()); } + + /** + * @magentoAppIsolation enabled + */ + public function testGetSelectedAttributes() + { + $productType = $this->getMock('stdClass', array('getUsedProductAttributes')); + $product = $this->getMock('Varien_Object', array('getTypeInstance')); + + $product->expects($this->once())->method('getTypeInstance')->will($this->returnValue($productType)); + $productType->expects($this->once())->method('getUsedProductAttributes')->with($this->equalTo($product)) + ->will($this->returnValue(array('', 'a'))); + + Mage::register('current_product', $product); + $layout = Mage::getModel('Mage_Core_Model_Layout'); + $block = $layout->createBlock('Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config', 'block'); + $this->assertEquals(array(1 => 'a'), $block->getSelectedAttributes()); + } } diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/SettingsTest.php b/dev/tests/integration/testsuite/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/SettingsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..58e3172bed26ab69568f7d5e6225039eec9ffc60 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/SettingsTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Adminhtml + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_SettingsTest extends PHPUnit_Framework_TestCase +{ + /** + * @magentoAppIsolation enabled + * @dataProvider getGetContinueUrlProvider + */ + public function testGetContinueUrl($productId, $expectedUrl) + { + $product = $this->getMockBuilder('Mage_Catalog_Model_Product') + ->disableOriginalConstructor() + ->setMethods(array('getId')) + ->getMock(); + $product->expects($this->any())->method('getId')->will($this->returnValue($productId)); + + $urlModel = $this->getMockBuilder('Mage_Backend_Model_Url') + ->disableOriginalConstructor() + ->setMethods(array('getUrl')) + ->getMock(); + $urlModel->expects($this->at(2))->method('getUrl')->with($this->equalTo($expectedUrl)) + ->will($this->returnValue('url')); + + Mage::register('current_product', $product); + + $layout = Mage::getModel('Mage_Core_Model_Layout'); + $block = $layout->createBlock( + 'Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Settings', + 'block', + array( + 'urlBuilder' => $urlModel + ) + ); + $this->assertEquals('url', $block->getContinueUrl()); + } + + /** + * @return array + */ + public function getGetContinueUrlProvider() + { + return array( + array(null, '*/*/new'), + array(1, '*/*/edit'), + ); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Bundle/Model/ProductTest.php b/dev/tests/integration/testsuite/Mage/Bundle/Model/ProductTest.php index c8d2cb8f51c3798ba42a41152d607a4839688d0f..5e1460291ae652e1af52be60817422889ae67daf 100644 --- a/dev/tests/integration/testsuite/Mage/Bundle/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Mage/Bundle/Model/ProductTest.php @@ -71,6 +71,7 @@ class Mage_Bundle_Model_ProductTest extends PHPUnit_Framework_TestCase } /** + * @magentoDbIsolation enabled * @magentoAppIsolation enabled */ public function testCRUD() diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/CategoryTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/CategoryTest.php index b7b5da4892a85c91ce10b585342a9d7bbf8049f1..41d05e1b5c0e3bc33942da18e3ac8fdee18eb034 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/CategoryTest.php +++ b/dev/tests/integration/testsuite/Mage/Catalog/Model/CategoryTest.php @@ -34,19 +34,116 @@ */ class Mage_Catalog_Model_CategoryTest extends PHPUnit_Framework_TestCase { + /** + * @var Magento_Test_ObjectManager + */ + protected static $_objectManager; + + /** + * Default flat category indexer mode + * + * @var string + */ + protected static $_indexerMode; + + /** + * List of index tables to create/delete + * + * @var array + */ + protected static $_indexerTables = array(); + + /** + * @var Mage_Core_Model_Store + */ + protected $_store; + /** * @var Mage_Catalog_Model_Category */ protected $_model; + public static function setUpBeforeClass() + { + self::$_objectManager = Mage::getObjectManager(); + + // get list of not existing tables + /** @var $application Mage_Core_Model_App */ + $application = self::$_objectManager->get('Mage_Core_Model_App'); + /** @var $categoryResource Mage_Catalog_Model_Resource_Category_Flat */ + $categoryResource = self::$_objectManager->create('Mage_Catalog_Model_Resource_Category_Flat'); + /** @var $setupModel Mage_Core_Model_Resource_Setup */ + $setupModel = self::$_objectManager->create('Mage_Core_Model_Resource_Setup', + array('resourceName' => Mage_Core_Model_Resource_Setup::DEFAULT_SETUP_CONNECTION) + ); + $stores = $application->getStores(); + /** @var $store Mage_Core_Model_Store */ + foreach ($stores as $store) { + $tableName = $categoryResource->getMainStoreTable($store->getId()); + if (!$setupModel->getConnection()->isTableExists($tableName)) { + self::$_indexerTables[] = $tableName; + } + } + + // create flat tables + /** @var $indexer Mage_Catalog_Model_Category_Indexer_Flat */ + $indexer = self::$_objectManager->create('Mage_Catalog_Model_Category_Indexer_Flat'); + $indexer->reindexAll(); + + // set real time indexer mode + $process = self::_getCategoryIndexerProcess(); + self::$_indexerMode = $process->getMode(); + $process->setMode(Mage_Index_Model_Process::MODE_REAL_TIME); + $process->save(); + } + + public static function tearDownAfterClass() + { + // revert default indexer mode + $process = self::_getCategoryIndexerProcess(); + $process->setMode(self::$_indexerMode); + $process->save(); + + // remove flat tables + /** @var $setupModel Mage_Core_Model_Resource_Setup */ + $setupModel = self::$_objectManager->create('Mage_Core_Model_Resource_Setup', + array('resourceName' => Mage_Core_Model_Resource_Setup::DEFAULT_SETUP_CONNECTION) + ); + foreach (self::$_indexerTables as $tableName) { + if ($setupModel->getConnection()->isTableExists($tableName)) { + $setupModel->getConnection()->dropTable($tableName); + } + } + + self::$_objectManager = null; + self::$_indexerMode = null; + self::$_indexerTables = null; + } + + /** + * @static + * @return Mage_Index_Model_Process + */ + protected static function _getCategoryIndexerProcess() + { + /** @var $process Mage_Index_Model_Process */ + $process = self::$_objectManager->create('Mage_Index_Model_Process'); + $process->load(Mage_Catalog_Helper_Category_Flat::CATALOG_CATEGORY_FLAT_PROCESS_CODE, 'indexer_code'); + return $process; + } + protected function setUp() { - $this->_model = Mage::getModel('Mage_Catalog_Model_Category'); + /** @var $application Mage_Core_Model_App */ + $application = self::$_objectManager->get('Mage_Core_Model_App'); + $this->_store = $application->getStore(); + $this->_model = self::$_objectManager->create('Mage_Catalog_Model_Category'); } protected function tearDown() { - $this->_model = null; + unset($this->_store); + unset($this->_model); } public function testGetUrlInstance() @@ -246,4 +343,38 @@ class Mage_Catalog_Model_CategoryTest extends PHPUnit_Framework_TestCase { $this->assertNotEmpty($this->_model->validate()); } + + /** + * @magentoConfigFixture current_store catalog/frontend/flat_catalog_category 1 + * @magentoDbIsolation enabled + */ + public function testSaveWithFlatIndexer() + { + $categoryName = 'Indexer Category Name ' . uniqid(); + + /** @var $parentCategory Mage_Catalog_Model_Category */ + $parentCategory = self::$_objectManager->create('Mage_Catalog_Model_Category'); + $parentCategory->load($this->_store->getRootCategoryId()); + + // init category model with EAV entity resource model + $resourceModel = self::$_objectManager->create('Mage_Catalog_Model_Resource_Category'); + $this->_model = self::$_objectManager->create('Mage_Catalog_Model_Category', + array('resource' => $resourceModel) + ); + $this->_model->setName($categoryName) + ->setParentId($parentCategory->getId()) + ->setPath($parentCategory->getPath()) + ->setLevel(2) + ->setPosition(1) + ->setAvailableSortBy('name') + ->setDefaultSortBy('name') + ->setIsActive(true) + ->save(); + + // check if category record exists in flat table + /** @var $collection Mage_Catalog_Model_Resource_Category_Flat_Collection */ + $collection = self::$_objectManager->create('Mage_Catalog_Model_Resource_Category_Flat_Collection'); + $collection->addFieldToFilter('name', $categoryName); + $this->assertCount(1, $collection->getItems()); + } } diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductExternalTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductExternalTest.php index d03d0456ee08e28718c7438c771f1f3ae138b61a..90010f9eb867e13bfb5a8deb02494cfe2bcd93a8 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductExternalTest.php +++ b/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductExternalTest.php @@ -98,20 +98,6 @@ class Mage_Catalog_Model_ProductExternalTest extends PHPUnit_Framework_TestCase $this->assertSame($categoryTwo, $this->_model->getCategory()); } - public function testSetCategoryIds() - { - $this->_model->setCategoryIds('1,2,,3'); - $this->assertEquals(array(0 => 1, 1 => 2, 3 => 3), $this->_model->getData('category_ids')); - } - - /** - * @expectedException Mage_Core_Exception - */ - public function testSetCategoryIdsException() - { - $this->_model->setCategoryIds(1); - } - public function testGetCategoryIds() { // none diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductTest.php index 680639e4bff183eb1f6154486fe3dc5ea7d69ce5..d1fd3d287f5ec81559637bcf2ae58fef653d57b4 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Mage/Catalog/Model/ProductTest.php @@ -66,6 +66,7 @@ class Mage_Catalog_Model_ProductTest extends PHPUnit_Framework_TestCase } /** + * @magentoDbIsolation enabled * @magentoAppIsolation enabled */ public function testCRUD() diff --git a/dev/tests/integration/testsuite/Mage/Catalog/_files/product_special_price.php b/dev/tests/integration/testsuite/Mage/Catalog/_files/product_special_price.php index 0cd5faa1b54949122c4cae1ab95da996aa586845..79a4b0a8d29f1bb741b458466364538fa3048f5f 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/_files/product_special_price.php +++ b/dev/tests/integration/testsuite/Mage/Catalog/_files/product_special_price.php @@ -25,5 +25,26 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -require __DIR__ . '/products.php'; -$product->setStockData()->setSpecialPrice('5.99')->save(); +/** @var $product Mage_Catalog_Model_Product */ +$product = Mage::getModel('Mage_Catalog_Model_Product'); +$product->setTypeId('simple') + ->setId(1) + ->setAttributeSetId(4) + ->setWebsiteIds(array(1)) + ->setName('Simple Product') + ->setSku('simple') + ->setPrice(10) + + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + + ->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) + ->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED) + + ->setStockData(array( + 'use_config_manage_stock' => 0, + )) + ->setStockData() + ->setSpecialPrice('5.99') + ->save(); diff --git a/dev/tests/integration/testsuite/Mage/Cms/_files/pages.php b/dev/tests/integration/testsuite/Mage/Cms/_files/pages.php index d3714f8ab0d10224c497d2437d5def7f6ab951eb..a954c6dc93bf47f5e784018c5c227666fb99b15a 100644 --- a/dev/tests/integration/testsuite/Mage/Cms/_files/pages.php +++ b/dev/tests/integration/testsuite/Mage/Cms/_files/pages.php @@ -34,8 +34,7 @@ $page//->setId(100) // doesn't work: it triggers update ->setIsActive(1) ->setContent('<h1>Cms Page 100 Title</h1>') ->setRootTemplate('one_column') - ->save() -; + ->save(); $page = Mage::getModel('Mage_Cms_Model_Page'); $page->setTitle('Cms Page Design Modern') @@ -45,5 +44,4 @@ $page->setTitle('Cms Page Design Modern') ->setContent('<h1>Cms Page Design Modern Title</h1>') ->setRootTemplate('one_column') ->setCustomTheme('default/modern') - ->save() -; + ->save(); diff --git a/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php b/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php index 9269c00fe9e380e79991dc46f64fd3ada62f5d02..270576bc6ad1bac9e42040a926d58f756acf059b 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php @@ -24,7 +24,9 @@ * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - +/** + * @magentoAppIsolation enabled + */ class Mage_Core_Block_AbstractTest extends PHPUnit_Framework_TestCase { /** @@ -94,6 +96,19 @@ class Mage_Core_Block_AbstractTest extends PHPUnit_Framework_TestCase $this->assertSame($parentBlock, $childBlock->getParentBlock()); } + /** + * @covers Mage_Core_Block_Abstract::addChild + */ + public function testAddChild() + { + $parentBlock = $this->_createBlockWithLayout('testAddChild', 'testAddChild', 'Mage_Core_Block_Text'); + $child = $parentBlock->addChild('testAddChildAlias', 'Mage_Core_Block_Text', array('content' => 'content')); + $this->assertInstanceOf('Mage_Core_Block_Text', $child); + $this->assertEquals('testAddChild.testAddChildAlias', $child->getNameInLayout()); + $this->assertEquals($child, $parentBlock->getChildBlock('testAddChildAlias')); + $this->assertEquals('content', $child->getContent()); + } + public function testSetGetNameInLayout() { // Basic setting/getting @@ -220,6 +235,7 @@ class Mage_Core_Block_AbstractTest extends PHPUnit_Framework_TestCase $this->assertFalse($this->_block->getChildBlock($childAlias)); // With layout + /** @var $layout Mage_Core_Model_Layout */ $layout = Mage::getModel('Mage_Core_Model_Layout'); $layout->addBlock($this->_block, $parentName); $layout->addBlock($child, $childName); @@ -227,7 +243,7 @@ class Mage_Core_Block_AbstractTest extends PHPUnit_Framework_TestCase $this->_block->setChild($childAlias, $child); $result = $this->_block->getChildBlock($childAlias); $this->assertInstanceOf('Mage_Core_Block_Text', $result); - $this->assertEquals($parentName . '.' . $childAlias, $result->getNameInLayout()); + $this->assertEquals($childName, $result->getNameInLayout()); $this->assertEquals($child, $result); } @@ -465,6 +481,13 @@ class Mage_Core_Block_AbstractTest extends PHPUnit_Framework_TestCase { $this->assertStringStartsWith('http://localhost/pub/media/theme/frontend/', $this->_block->getViewFileUrl()); $this->assertStringEndsWith('css/styles.css', $this->_block->getViewFileUrl('css/styles.css')); + + /** + * File is not exist + */ + $this->assertStringEndsWith( + '/core/index/notfound', $this->_block->getViewFileUrl('not_exist_folder/wrong_bad_file.xyz') + ); } public function testGetSetMessagesBlock() @@ -656,6 +679,14 @@ class Mage_Core_Block_AbstractTest extends PHPUnit_Framework_TestCase return array($blocks, $names); } + /** + * Create Block with Layout + * + * @param string $name + * @param null|string $alias + * @param null|string $type + * @return Mage_Core_Block_Abstract + */ protected function _createBlockWithLayout($name = 'block', $alias = null, $type = 'Mage_Core_Block_Abstract' ) { diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/LayoutTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/LayoutTest.php index d0dad9f7b1476bb60bd9b1a4215127efbb166eae..c10717db260989d674cedad6e386411b38ed815a 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/LayoutTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/LayoutTest.php @@ -301,7 +301,6 @@ class Mage_Core_Model_LayoutTest extends Mage_Core_Model_LayoutTestBase array( 'type' => 'Mage_Core_Block_Text_List', 'key1' => 'value1', - 'is_anonymous' => true ), '/text_list/' ), diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/Resource/SessionTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/SessionTest.php index 5350fc9a4d9854fe6323905f68f72b482f28534e..3196b217c6451f8ea2bf3e63f9feb72ec222f22b 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/Resource/SessionTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/SessionTest.php @@ -52,11 +52,18 @@ class Mage_Core_Model_Resource_SessionTest extends PHPUnit_Framework_TestCase * * @var array */ - protected $_sessionData = array( + protected $_sourceData = array( self::SESSION_NEW => array('new key' => 'new value'), self::SESSION_EXISTS => array('existing key' => 'existing value'), ); + /** + * Data as objects for serialization + * + * @var array + */ + protected $_sessionData; + /** * @var Magento_Test_ObjectManager */ @@ -92,6 +99,12 @@ class Mage_Core_Model_Resource_SessionTest extends PHPUnit_Framework_TestCase $resource = $this->_objectManager->get('Mage_Core_Model_Resource'); $this->_connection = $resource->getConnection('core_write'); $this->_sessionTable = $resource->getTableName('core_session'); + + // session stores serialized objects with protected properties + // we need to test this case to ensure that DB adapter successfully processes "\0" symbols in serialized data + foreach ($this->_sourceData as $key => $data) { + $this->_sessionData[$key] = new Varien_Object($data); + } } protected function tearDown() @@ -100,6 +113,7 @@ class Mage_Core_Model_Resource_SessionTest extends PHPUnit_Framework_TestCase unset($this->_model); unset($this->_connection); unset($this->_sessionTable); + unset($this->_sessionData); } public function testHasConnection() @@ -164,7 +178,9 @@ class Mage_Core_Model_Resource_SessionTest extends PHPUnit_Framework_TestCase */ public function readEncodedDataProvider() { - $sessionData = serialize($this->_sessionData[self::SESSION_NEW]); + // we can't use object data as a fixture because not encoded serialized object + // might cause DB adapter fatal error, so we have to use array as a fixture + $sessionData = serialize($this->_sourceData[self::SESSION_NEW]); return array( 'session_encoded' => array('$sessionData' => base64_encode($sessionData)), 'session_not_encoded' => array('$sessionData' => $sessionData), @@ -187,6 +203,6 @@ class Mage_Core_Model_Resource_SessionTest extends PHPUnit_Framework_TestCase $this->_connection->insertOnDuplicate($this->_sessionTable, $sessionRecord, array(self::COLUMN_SESSION_DATA)); $sessionData = $this->_model->read(self::SESSION_ID); - $this->assertEquals($this->_sessionData[self::SESSION_NEW], unserialize($sessionData)); + $this->assertEquals($this->_sourceData[self::SESSION_NEW], unserialize($sessionData)); } } diff --git a/dev/tests/integration/testsuite/Mage/Core/_files/design_change.php b/dev/tests/integration/testsuite/Mage/Core/_files/design_change.php index 3e71e4ad4c78ec66e5e903a3f0c59931b18d3b3c..c3185a8fcb0f8862523db446b7bee194f4a2be64 100644 --- a/dev/tests/integration/testsuite/Mage/Core/_files/design_change.php +++ b/dev/tests/integration/testsuite/Mage/Core/_files/design_change.php @@ -26,9 +26,9 @@ */ $storeId = Mage::app()->getAnyStoreView()->getId(); +/** @var $change Mage_Core_Model_Design */ $change = Mage::getModel('Mage_Core_Model_Design'); $change->setStoreId($storeId) ->setDesign('default/modern') ->setDateFrom('2001-01-01 01:01:01') - ->save() // creating with predefined ID doesn't work for some reason -; + ->save(); // creating with predefined ID doesn't work for some reason diff --git a/dev/tests/integration/testsuite/Mage/Core/controllers/IndexControllerTest.php b/dev/tests/integration/testsuite/Mage/Core/controllers/IndexControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..90a5483f5975ec35238c0307fc99e15a4e902826 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Core/controllers/IndexControllerTest.php @@ -0,0 +1,36 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Core + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Core_IndexControllerTest extends Magento_Test_TestCase_ControllerAbstract +{ + public function testNotFoundAction() + { + $this->dispatch('core/index/notfound'); + $this->assertEquals('404', $this->getResponse()->getHttpResponseCode()); + $this->assertEquals('Requested resource not found', $this->getResponse()->getBody()); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Downloadable/Model/ObserverTest.php b/dev/tests/integration/testsuite/Mage/Downloadable/Model/ObserverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4f90e14e448a457feb0fc2adbdac38db84000886 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Downloadable/Model/ObserverTest.php @@ -0,0 +1,51 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Downloadable + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for Mage_Downloadable_Model_Observer (duplicate downloadable data) + */ +class Mage_Downloadable_Model_ObserverTest extends PHPUnit_Framework_TestCase +{ + /** + * @magentoDataFixture Mage/Downloadable/_files/product_with_files.php + */ + public function testDuplicateProductDownloadableProductWithFilesSuccessfullyDuplicated() + { + $currentProduct = Mage::getModel('Mage_Catalog_Model_Product'); + $currentProduct->load(1); // fixture for initial product + $currentLinks = $currentProduct->getTypeInstance($currentProduct)->getLinks($currentProduct); + $currentSamples = $currentProduct->getTypeInstance($currentProduct)->getSamples($currentProduct); + + $newProduct = $currentProduct->duplicate(); + + $newLinks = $newProduct->getTypeInstance($newProduct)->getLinks($newProduct); + $newSamples = $newProduct->getTypeInstance($newProduct)->getSamples($newProduct); + + $this->assertEquals($currentLinks, $newLinks); + $this->assertEquals($currentSamples, $newSamples); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Downloadable/_files/product_with_files.php b/dev/tests/integration/testsuite/Mage/Downloadable/_files/product_with_files.php new file mode 100644 index 0000000000000000000000000000000000000000..7ab80948201ccc9d78bdf5ecfd0dc0bcccad4d4b --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Downloadable/_files/product_with_files.php @@ -0,0 +1,82 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Downloadable + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +$product = Mage::getModel('Mage_Catalog_Model_Product'); +$product->setTypeId(Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) + ->setId(1) + ->setAttributeSetId(4) + ->setWebsiteIds(array(1)) + ->setName('Downloadable Product') + ->setSku('downloadable-product') + ->setPrice(10) + ->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) + ->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED) + ->setDownloadableData(array( + 'link' => array(array( + 'link_id' => 0, + 'product_id' => 1, + 'sort_order' => '0', + 'title' => 'Downloadable Product Link', + 'sample' => array( + 'type' => Mage_Downloadable_Helper_Download::LINK_TYPE_FILE, + 'url' => null, + 'file' => json_encode(array(array( + 'file' => '/n/d/jellyfish_1_3.jpg', + 'name' => 'jellyfish_1_3.jpg', + 'size' => 54565, + 'status' => 0, + ))), + ), + 'file' => json_encode(array(array( + 'file' => '/j/e/jellyfish_2_4.jpg', + 'name' => 'jellyfish_2_4.jpg', + 'size' => 56644, + 'status' => 0, + ))), + 'type' => Mage_Downloadable_Helper_Download::LINK_TYPE_FILE, + 'is_shareable' => Mage_Downloadable_Model_Link::LINK_SHAREABLE_CONFIG, + 'link_url' => null, + 'is_delete' => 0, + 'number_of_downloads' => 15, + 'price' => 15.00, + )), + 'sample' => array(array( + 'is_delete' => 0, + 'sample_id' => 0, + 'title' => 'Downloadable Product Sample Title', + 'type' => Mage_Downloadable_Helper_Download::LINK_TYPE_FILE, + 'file' => json_encode(array(array( + 'file' => '/f/u/jellyfish_1_4.jpg', + 'name' => 'jellyfish_1_4.jpg', + 'size' => 1024, + 'status' => 0, + ))), + 'sample_url' => null, + 'sort_order' => '0', + )) + )) + ->save(); diff --git a/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/CustomerCompositeTest.php b/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/CustomerCompositeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e0fe8f4ced505ddf6553eb20b3235906a5d8f62c --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/CustomerCompositeTest.php @@ -0,0 +1,236 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_ImportExport + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_ImportExport_Model_Import_Entity_CustomerCompositeTest extends PHPUnit_Framework_TestCase +{ + /**#@+ + * Attributes used in test assertions + */ + const ATTRIBUTE_CODE_FIRST_NAME = 'firstname'; + const ATTRIBUTE_CODE_LAST_NAME = 'lastname'; + /**#@-*/ + + /**#@+ + * Source *.csv file names for different behaviors + */ + const UPDATE_FILE_PATTERN = 'customer_composite_update.*?\.csv'; + const DELETE_FILE_NAME = 'customer_composite_delete.csv'; + /**#@-*/ + + /** + * Object Manager instance + * + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * Composite customer entity adapter instance + * + * @var Mage_ImportExport_Model_Import_Entity_CustomerComposite + */ + protected $_entityAdapter; + + /** + * Additional customer attributes for assertion + * + * @var array + */ + protected $_customerAttributes = array( + self::ATTRIBUTE_CODE_FIRST_NAME, + self::ATTRIBUTE_CODE_LAST_NAME, + ); + + /** + * Customers and addresses before import, address ID is postcode + * + * @var array + */ + protected $_beforeImport = array( + 'betsyparker@example.com' => array( + 'addresses' => array('19107', '72701'), + 'data' => array( + self::ATTRIBUTE_CODE_FIRST_NAME => 'Betsy', + self::ATTRIBUTE_CODE_LAST_NAME => 'Parker', + ), + ), + ); + + /** + * Customers and addresses after import, address ID is postcode + * + * @var array + */ + protected $_afterImport = array( + 'betsyparker@example.com' => array( + 'addresses' => array('19107', '72701', '19108'), + 'data' => array( + self::ATTRIBUTE_CODE_FIRST_NAME => 'NotBetsy', + self::ATTRIBUTE_CODE_LAST_NAME => 'NotParker', + ), + ), + 'anthonyanealy@magento.com' => array('addresses' => array('72701', '92664')), + 'loribbanks@magento.com' => array('addresses' => array('98801')), + 'kellynilson@magento.com' => array('addresses' => array()), + ); + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_entityAdapter = $this->_objectManager + ->create('Mage_ImportExport_Model_Import_Entity_CustomerComposite'); + } + + protected function tearDown() + { + unset($this->_objectManager); + unset($this->_entityAdapter); + } + + /** + * Assertion of current customer and address data + * + * @param array $expectedData + */ + protected function _assertCustomerData(array $expectedData) + { + /** @var $collection Mage_Customer_Model_Resource_Customer_Collection */ + $collection = $this->_objectManager->create('Mage_Customer_Model_Resource_Customer_Collection'); + $collection->addAttributeToSelect($this->_customerAttributes); + $customers = $collection->getItems(); + + $this->assertSameSize($expectedData, $customers); + + /** @var $customer Mage_Customer_Model_Customer */ + foreach ($customers as $customer) { + // assert customer existence + $email = strtolower($customer->getEmail()); + $this->assertArrayHasKey($email, $expectedData); + + // assert customer data (only for required customers) + if (isset($expectedData[$email]['data'])) { + foreach ($expectedData[$email]['data'] as $attribute => $expectedValue) { + $this->assertEquals($expectedValue, $customer->getData($attribute)); + } + } + + // assert address data + $addresses = $customer->getAddresses(); + $this->assertSameSize($expectedData[$email]['addresses'], $addresses); + /** @var $address Mage_Customer_Model_Address */ + foreach ($addresses as $address) { + $this->assertContains($address->getData('postcode'), $expectedData[$email]['addresses']); + } + } + } + + /** + * @param string $behavior + * @param string $sourceFile + * @param array $dataBefore + * @param array $dataAfter + * @param array $errors + * + * @magentoDataFixture Mage/ImportExport/_files/customers_for_address_import.php + * @magentoAppIsolation enabled + * + * @dataProvider importDataDataProvider + * @covers Mage_ImportExport_Model_Import_Entity_CustomerComposite::_importData + */ + public function testImportData($behavior, $sourceFile, array $dataBefore, array $dataAfter, array $errors = array()) + { + // set entity adapter parameters + $this->_entityAdapter->setParameters(array('behavior' => $behavior)); + + // set fixture CSV file + $result = $this->_entityAdapter + ->setSource(Mage_ImportExport_Model_Import_Adapter::findAdapterFor($sourceFile)) + ->isDataValid(); + if ($errors) { + $this->assertFalse($result); + } else { + $this->assertTrue($result); + } + + // assert validation errors + // can't use error codes because entity adapter gathers only error messages from aggregated adapters + $actualErrors = array_values($this->_entityAdapter->getErrorMessages()); + $this->assertEquals($errors, $actualErrors); + + // assert data before import + $this->_assertCustomerData($dataBefore); + + // import data + $this->_entityAdapter->importData(); + + // assert data after import + $this->_assertCustomerData($dataAfter); + } + + /** + * Data provider for testImportData + * + * @return array + */ + public function importDataDataProvider() + { + $filesDirectory = __DIR__ . '/_files/'; + $sourceData = array( + 'delete_behavior' => array( + '$behavior' => Mage_ImportExport_Model_Import::BEHAVIOR_DELETE, + '$sourceFile' => $filesDirectory. self::DELETE_FILE_NAME, + '$dataBefore' => $this->_beforeImport, + '$dataAfter' => array(), + ), + ); + + $directoryIterator = new DirectoryIterator($filesDirectory); + $iteratorIterator = new IteratorIterator($directoryIterator); + $regexIterator = new RegexIterator( + $iteratorIterator, '/' . self::UPDATE_FILE_PATTERN . '/i', RegexIterator::GET_MATCH + ); + + // get last matched update file + $updateFiles = array(); + foreach ($regexIterator as $fileInfo) { + $updateFiles[] = $fileInfo[0]; + } + if ($updateFiles) { + sort($updateFiles); + $updateFileName = end($updateFiles); + $sourceData['add_update_behavior'] = array( + '$behavior' => Mage_ImportExport_Model_Import::BEHAVIOR_ADD_UPDATE, + '$sourceFile' => $filesDirectory . $updateFileName, + '$dataBefore' => $this->_beforeImport, + '$dataAfter' => $this->_afterImport, + '$errors' => array(array(6)), // row #6 has no website + ); + } + + return $sourceData; + } +} diff --git a/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/_files/customer_composite_delete.csv b/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/_files/customer_composite_delete.csv new file mode 100644 index 0000000000000000000000000000000000000000..50320a747b7a180b08df4976201f00cbefb3577c --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/_files/customer_composite_delete.csv @@ -0,0 +1,2 @@ +"email","_website","_store" +"BetsyParker@example.com","admin","admin" diff --git a/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/_files/customer_composite_update.csv b/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/_files/customer_composite_update.csv new file mode 100644 index 0000000000000000000000000000000000000000..96fa62191dff9e415d3602e6ddb05328d726f4eb --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/ImportExport/Model/Import/Entity/_files/customer_composite_update.csv @@ -0,0 +1,7 @@ +"email","_website","_store","confirmation","created_at","created_in","disable_auto_group_change","dob","firstname","gender","group_id","lastname","middlename","password_hash","prefix","rp_token","rp_token_created_at","store_id","suffix","taxvat","website_id","password","_address_city","_address_company","_address_country_id","_address_fax","_address_firstname","_address_lastname","_address_middlename","_address_postcode","_address_prefix","_address_region","_address_street","_address_suffix","_address_telephone","_address_vat_id","_address_default_billing_","_address_default_shipping_" +"AnthonyANealy@magento.com","base","admin",,"05/06/2012 15:53","Admin",0,,"Anthony","Male",1,"Nealy","A.","6a9c9bfb2ba88a6ad2a64e7402df44a763e0c48cd21d7af9e7e796cd4677ee28:RF",,,,0,,,1,,"Fayetteville",,"US",,"Anthony","Nealy",,72701,,"Arkansas","3176 Cambridge Court",,"479-899-9849",,1,1 +,,,,,,,,,,,,,,,,,,,,,,"Irvine",,"US",,"Anthony","Nealy",,92664,,"California","4709 Pleasant Hill Road",,"562-208-2310",,, +"LoriBBanks@magento.com","admin","admin",,"05/06/2012 15:59","Admin",0,,"Lori","Female",1,"Banks","B.","7ad6dbdc83d3e9f598825dc58b84678c7351e4281f6bc2b277a32dcd88b9756b:pz",,,,0,,,0,,"Wenatchee",,"US",,"Lori","Banks",,98801,,"Washington","2573 Goodwin Avenue",,"509-421-4364",,1,1 +"BetsyParker@example.com","admin","admin",,"05/06/2012 16:13","Admin",0,,"NotBetsy","Female",1,"NotParker","H.","145d12bfff8a6a279eb61e277e3d727c0ba95acc1131237f1594ddbb7687a564:l1",,,,0,,,2,,"Philadelphia",,"US",,"Betsy","Parker",,19108,,"Pennsylvania","1079 Rocky Road 1079 Rocky Road 2",,"215-629-9720",,1,1 +"KellyNIlson@magento.com","base","admin",,"05/06/2012 17:11","Admin",0,,"Kelly","Female",1,"Nilson","H.","145d12bfff8a6a279eb61e277e3d727c0ba95acc1131237f1594ddbb7687a564:l1",,,,0,,,2,,,,,,,,,,,,,,,,, +"MichaelJackson@magento.com",,"admin",,"05/06/2012 17:11","Admin",0,,"Michael","Male",1,"Jackson","J.","145d12bfff8a6a279eb61e277e3d727c0ba95acc1131237f1594ddbb7687a564:l1",,,,0,,,2,,,,,,,,,,,,,,,,, diff --git a/dev/tests/integration/testsuite/Mage/Index/Model/Process/FileTest.php b/dev/tests/integration/testsuite/Mage/Index/Model/Process/FileTest.php new file mode 100644 index 0000000000000000000000000000000000000000..45b81a0fa6fed0b3d617c832ae56a3c0755fd9e5 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Index/Model/Process/FileTest.php @@ -0,0 +1,193 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Index + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for Mage_Index_Model_Process_File + */ +class Mage_Index_Model_Process_FileTest extends PHPUnit_Framework_TestCase +{ + /** + * Test lock name + */ + const FILE_NAME = 'index_test.lock'; + + /** + * @var Magento_Test_ObjectManager + */ + protected $_objectManager; + + /** + * @var string + */ + protected $_fileDirectory; + + /** + * @var resource + */ + protected $_testFileHandler; + + /** + * @var Mage_Index_Model_Process_File + */ + protected $_model; + + protected function setUp() + { + $this->_objectManager = Mage::getObjectManager(); + $this->_model = $this->_objectManager->create('Mage_Index_Model_Process_File'); + /** @var $configuration Mage_Core_Model_Config */ + $configuration = $this->_objectManager->get('Mage_Core_Model_Config'); + $this->_fileDirectory = $configuration->getVarDir('locks'); + $fullFileName = $this->_fileDirectory . DIRECTORY_SEPARATOR . self::FILE_NAME; + $this->_testFileHandler = fopen($fullFileName, 'w'); + } + + protected function tearDown() + { + unset($this->_objectManager); + unset($this->_model); + unset($this->_fileDirectory); + fclose($this->_testFileHandler); + unset($this->_testFileHandler); + } + + /** + * Open test file + */ + protected function _openFile() + { + $this->_model->cd($this->_fileDirectory); + $this->_model->streamOpen(self::FILE_NAME); + } + + /** + * Get shared lock for test file handler + * + * @return bool + */ + protected function _tryGetSharedLock() + { + return flock($this->_testFileHandler, LOCK_SH | LOCK_NB); + } + + /** + * Unlock test file handler + */ + protected function _unlock() + { + flock($this->_testFileHandler, LOCK_UN); + } + + public function testProcessLockNoStream() + { + $this->assertFalse($this->_model->processLock()); + } + + /** + * This test can't check non blocking lock case because its required two parallel test processes + */ + public function testProcessLockSuccessfulLock() + { + $this->_openFile(); + + // can't take shared lock if file has exclusive lock + $this->assertTrue($this->_model->processLock()); + $this->assertFalse($this->_tryGetSharedLock(), 'File must be locked'); + $this->assertAttributeSame(true, '_streamLocked', $this->_model); + $this->assertAttributeSame(false, '_processLocked', $this->_model); + + $this->_model->processUnlock(); + } + + public function testProcessFailedLock() + { + $this->_openFile(); + + // can't take exclusive lock if file has shared lock + $this->assertTrue($this->_tryGetSharedLock(), 'File must not be locked'); + $this->assertFalse($this->_model->processLock()); + $this->assertAttributeSame(true, '_streamLocked', $this->_model); + $this->assertAttributeSame(true, '_processLocked', $this->_model); + + $this->_unlock(); + } + + public function testProcessUnlock() + { + $this->_openFile(); + $this->_model->processLock(); + + $this->assertTrue($this->_model->processUnlock()); + $this->assertAttributeSame(false, '_streamLocked', $this->_model); + $this->assertAttributeSame(null, '_processLocked', $this->_model); + } + + public function testIsProcessLockedNoStream() + { + $this->assertNull($this->_model->isProcessLocked()); + } + + public function testIsProcessLockedStoredFlag() + { + $this->_openFile(); + $this->_model->processLock(); + $this->assertFalse($this->_model->isProcessLocked()); + $this->_model->processUnlock(); + } + + public function testIsProcessLockedTrue() + { + $this->_openFile(); + + $this->assertTrue($this->_tryGetSharedLock(), 'File must not be locked'); + $this->assertTrue($this->_model->isProcessLocked()); + + $this->_unlock(); + } + + public function testIsProcessLockedFalseWithUnlock() + { + $this->_openFile(); + + $this->assertFalse($this->_model->isProcessLocked(true)); + $this->assertTrue($this->_tryGetSharedLock(), 'File must not be locked'); + $this->assertAttributeSame(false, '_streamLocked', $this->_model); + + $this->_unlock(); + } + + public function testIsProcessLockedFalseWithoutUnlock() + { + $this->_openFile(); + + $this->assertFalse($this->_model->isProcessLocked()); + $this->assertFalse($this->_tryGetSharedLock(), 'File must be locked'); + $this->assertAttributeSame(true, '_streamLocked', $this->_model); + + $this->_model->processUnlock(); + } +} diff --git a/dev/tests/integration/testsuite/Mage/Page/Block/Html/HeadTest.php b/dev/tests/integration/testsuite/Mage/Page/Block/Html/HeadTest.php index 27ce1759987396811509fa041328df8f4d41912d..9a17fbcd9b8f797277e4011b79963bf6c5d2c69a 100644 --- a/dev/tests/integration/testsuite/Mage/Page/Block/Html/HeadTest.php +++ b/dev/tests/integration/testsuite/Mage/Page/Block/Html/HeadTest.php @@ -69,6 +69,24 @@ class Mage_Page_Block_Html_HeadTest extends PHPUnit_Framework_TestCase $this->_block->addCss(''); } + public function testGetCssJsHtmlBadLink() + { + $this->_block->addJs('varien/js.js') + ->addJs('varien/form.js', '', 'lt IE 7') + ->addCss('not_exist_folder/wrong_bad_file.xyz') + ->addCss('css/styles.css', ' media="print" ') + ->addJs('not_exist_folder/wrong_bad_file2.xyz'); + + $this->assertEquals('<script type="text/javascript" src="http://localhost/index.php/core/index/notfound">' + . '</script>' . "\n" . '<!--[if lt IE 7]>' . "\n" + . '<script type="text/javascript" src="http://localhost/pub/lib/varien/form.js"></script>' . "\n" + . '<![endif]-->' . "\n" . '<link rel="stylesheet" type="text/css" media="all"' + . ' href="http://localhost/index.php/core/index/notfound" />' . "\n" + . '<link rel="stylesheet" type="text/css" media="print"' + . ' href="http://localhost/pub/media/theme/frontend/default/demo/en_US/css/styles.css" />' + . "\n", $this->_block->getCssJsHtml()); + } + public function testGetCssJsHtml() { $this->_block->addJs('zero.js', '', null, 'nonexisting_condition') diff --git a/dev/tests/integration/testsuite/Mage/Sales/Block/Adminhtml/Report/Filter/Form/CouponTest.php b/dev/tests/integration/testsuite/Mage/Sales/Block/Adminhtml/Report/Filter/Form/CouponTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ba145b41b96c0ba9e83dcfc334596422cd0f3c71 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Sales/Block/Adminhtml/Report/Filter/Form/CouponTest.php @@ -0,0 +1,69 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Sales + * @subpackage integration_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Mage_Index_Model_Lock_Storage + */ +class Mage_Sales_Block_Adminhtml_Report_Filter_Form_CouponTest extends PHPUnit_Framework_TestCase +{ + /** + * Application object + * + * @var Mage_Core_Model_App + */ + protected $_application; + + protected function setUp() + { + $this->_application = Mage::getObjectManager()->get('Mage_Core_Model_App'); + } + + protected function tearDown() + { + unset($this->_application); + } + + /** + * @covers Mage_Sales_Block_Adminhtml_Report_Filter_Form_Coupon::_afterToHtml + */ + public function testAfterToHtml() + { + /** @var $block Mage_Sales_Block_Adminhtml_Report_Filter_Form_Coupon */ + $block = $this->_application->getLayout()->createBlock('Mage_Sales_Block_Adminhtml_Report_Filter_Form_Coupon'); + $block->setFilterData(new Varien_Object()); + $html = $block->toHtml(); + + $expectedStrings = array( + 'FormElementDependenceController', + 'sales_report_rules_list', + 'sales_report_price_rule_type' + ); + foreach ($expectedStrings as $expectedString) { + $this->assertContains($expectedString, $html); + } + } +} diff --git a/dev/tests/static/testsuite/Php/_files/whitelist/common.txt b/dev/tests/static/testsuite/Php/_files/whitelist/common.txt index d8a5d726266c8e12add7475cb06641fd85324954..c8dc36d4700049356d0ff2832288fa87be80f664 100644 --- a/dev/tests/static/testsuite/Php/_files/whitelist/common.txt +++ b/dev/tests/static/testsuite/Php/_files/whitelist/common.txt @@ -8,8 +8,15 @@ app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tab/Account.php app/code/core/Mage/Adminhtml/Model/Observer.php app/code/core/Mage/Adminhtml/Block/Urlrewrite app/code/core/Mage/Adminhtml/Block/Page/System/Config/Robots/Reset.php +app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Category.php app/code/core/Mage/Adminhtml/Block/System/Store/Edit app/code/core/Mage/Adminhtml/Block/System/Store/Edit.php +app/code/core/Mage/Backend/Model/Acl/Config.php +app/code/core/Mage/Backend/Block/Widget/Grid/ColumnSet.php +app/code/core/Mage/Backend/Block/Widget/Grid/Export.php +app/code/core/Mage/Backend/Block/Widget/Grid/ExportInterface.php +app/code/core/Mage/CatalogInventory/Block/Adminhtml/Form/Field/Stock.php +app/code/core/Mage/Backend/controllers/Adminhtml/SystemController.php app/code/core/Mage/Adminhtml/controllers/UrlrewriteController.php app/code/core/Mage/Core/Block/Abstract.php app/code/core/Mage/Core/data diff --git a/dev/tests/unit/testsuite/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/BaseImageTest.php b/dev/tests/unit/testsuite/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/BaseImageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dfb1c1803339cba2a56c88791bf5f211b2aa4c21 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/BaseImageTest.php @@ -0,0 +1,166 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Adminhtml + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Adminhtml_Block_Catalog_Product_Helper_Form_BaseImageTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Adminhtml_Block_Catalog_Product_Helper_Form_BaseImage + */ + protected $_model; + + /** + * @var Mage_Adminhtml_Model_Url + */ + protected $_url; + + /** + * @var Mage_Core_Model_Design_Package + */ + protected $_design; + + /** + * @var Mage_Catalog_Model_Product_Media_Config + */ + protected $_mediaConfig; + + /** + * @var Mage_Core_Helper_Data + */ + protected $_helperData; + + protected function setUp() + { + $mediaUploader = $this->getMockBuilder('Mage_Adminhtml_Block_Media_Uploader') + ->disableOriginalConstructor() + ->setMethods(array('getDataMaxSizeInBytes')) + ->getMock(); + $this->_url = $this->getMockBuilder('Mage_Adminhtml_Model_Url') + ->disableOriginalConstructor() + ->setMethods(array('getUrl')) + ->getMock(); + $this->_mediaConfig = $this->getMockBuilder('Mage_Catalog_Model_Product_Media_Config') + ->disableOriginalConstructor() + ->setMethods(array('getMediaUrl', 'getTmpMediaUrl')) + ->getMock(); + $this->_design = $this->getMockBuilder('Mage_Core_Model_Design_Package') + ->disableOriginalConstructor() + ->setMethods(array('getViewFileUrl')) + ->getMock(); + $this->_helperData = $this->getMockBuilder('Mage_Core_Helper_Data') + ->disableOriginalConstructor() + ->setMethods(array('escapeHtml', 'jsonEncode')) + ->getMock(); + $form = $this->getMockBuilder('Varien_Data_Form') + ->disableOriginalConstructor() + ->getMock(); + + $attributes = array( + 'name' => 'image', + 'label' => "Base Image", + 'mediaUploader' => $mediaUploader, + 'url' => $this->_url, + 'mediaConfig' => $this->_mediaConfig, + 'design' => $this->_design, + 'helperData' => $this->_helperData + ); + + $mediaUploader->expects($this->once())->method('getDataMaxSizeInBytes')->will($this->returnValue('999')); + $this->_model = new Mage_Adminhtml_Block_Catalog_Product_Helper_Form_BaseImage($attributes); + $this->_model->setForm($form); + $this->_model->setHtmlId('image'); + $this->_url->expects($this->once())->method('getUrl') + ->will($this->returnValue('http://example.com/pub/images/catalog_product_gallery/upload/')); + $this->_helperData->expects($this->any())->method('jsonEncode')->will($this->returnArgument(0)); + } + + /** + * Test to get valid html code for 'image' attribute + * + * @param mixed $imageValue + * @param string $methodName + * @param string $urlPath + * @dataProvider validateImageUrlDataProvider + */ + public function testGetElementHtml($imageValue, $methodName, $urlPath) + { + $this->_model->setValue($imageValue); + $this->_helperData->expects($this->any())->method('escapeHtml')->will($this->returnArgument(0)); + $this->_mediaConfig->expects($this->once())->method($methodName)->will($this->returnValue($urlPath)); + $html = $this->_createHtmlCode($imageValue, $urlPath); + $this->assertXmlStringEqualsXmlString("<test>{$html}</test>", "<test>{$this->_model->getElementHtml()}</test>", + 'Another BaseImage html code is expected'); + } + + public function validateImageUrlDataProvider() + { + return array( + array( + '/f/i/file_666.png', + 'getMediaUrl', + 'http://example.com/pub/media/tmp/catalog/product/f/i/file_78.png' + ), + array( + '/f/i/file_666.png.tmp', + 'getTmpMediaUrl', + 'http://example.com/pub/images/image-placeholder.png' + ) + ); + } + + /** + * Test to get valid html code for 'image' with placeholder + */ + public function testImagePlaceholder() + { + $urlPath = 'http://example.com/pub/images/image-placeholder.png'; + $this->_model->setValue(null); + $this->_design->expects($this->once())->method('getViewFileUrl')->will($this->returnValue($urlPath)); + $this->_helperData->expects($this->any())->method('escapeHtml')->will($this->returnArgument(0)); + $html = $this->_createHtmlCode('', $urlPath); + $this->assertXmlStringEqualsXmlString("<test>{$html}</test>", "<test>{$this->_model->getElementHtml()}</test>", + 'Another BaseImage html code is expected'); + } + + /** + * Create html code for expected result + * + * @param string $imageValue + * @param string $urlPath + * + * @return string + */ + protected function _createHtmlCode($imageValue, $urlPath) + { + $html = file_get_contents(__DIR__ . '/_files/BaseImageHtml.txt'); + $html = str_replace('%htmlId%', $this->_model->getHtmlId(), $html); + $html = str_replace('%imageValue%', $imageValue, $html); + $html = str_replace('%uploadImage%', 'http://example.com/pub/images/catalog_product_gallery/upload/', $html); + $html = str_replace('%imageUrl%', $urlPath, $html); + + return $html; + } +} diff --git a/dev/tests/unit/testsuite/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/_files/BaseImageHtml.txt b/dev/tests/unit/testsuite/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/_files/BaseImageHtml.txt new file mode 100644 index 0000000000000000000000000000000000000000..232024baaae45ea9b8e37a9fac1ec0bf92d3bcb5 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/_files/BaseImageHtml.txt @@ -0,0 +1,4 @@ +<input id="%htmlId%_upload" type="file" name="image" data-url="%uploadImage%" style="display: none;" /> +<input id="%htmlId%" name="%htmlId%" data-ui-id="form-element-%htmlId%" value="%imageValue%" type="hidden"/> +<img align="left" src="%imageUrl%" id="%htmlId%_image" title="%imageUrl%" alt="%imageUrl%" class="base-image-uploader" onclick="jQuery('#%htmlId%_upload').trigger('click')"/> +<script>/* <![CDATA[ */jQuery(function(){BaseImageUploader(%htmlId%, 999); });/*]]>*/</script> diff --git a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php index 397c1665523188a9e95859ba449e8d81f58bad75..c0178b5bbc753e6ed7e904c4d24c392b8dab9493 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/Block/System/Config/EditTest.php @@ -130,7 +130,6 @@ class Mage_Backend_Block_System_Config_EditTest extends PHPUnit_Framework_TestCa ); $block->expects($this->once())->method('initForm'); $block->expects($this->once())->method('getNameInLayout')->will($this->returnValue('test_block_name')); - $block->expects($this->once())->method('getIsAnonymous')->will($this->returnValue(false)); $this->_layoutMock->expects($this->once()) ->method('createBlock') diff --git a/dev/tests/unit/testsuite/Mage/Catalog/Model/Product/Attribute/Backend/CategoryTest.php b/dev/tests/unit/testsuite/Mage/Catalog/Model/Product/Attribute/Backend/CategoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0f8e02e43a75637503e76aede6349866f96a4adf --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Catalog/Model/Product/Attribute/Backend/CategoryTest.php @@ -0,0 +1,53 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Catalog + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Catalog_Model_Product_Attribute_Backend_CategoryTest extends PHPUnit_Framework_TestCase +{ + public function testAfterLoad() + { + $categoryIds = array(1,2,3,4,5); + + $product = $this->getMock('Varien_Object', array('getCategoryIds', 'setData')); + $product->expects($this->once()) + ->method('getCategoryIds') + ->will($this->returnValue($categoryIds)); + + $product->expects($this->once()) + ->method('setData') + ->with('category_ids', $categoryIds); + + $categoryAttribute = $this->getMock('Varien_Object', array('getAttributeCode')); + $categoryAttribute->expects($this->once()) + ->method('getAttributeCode') + ->will($this->returnValue('category_ids')); + + $model = new Mage_Catalog_Model_Product_Attribute_Backend_Category(); + $model->setAttribute($categoryAttribute); + + $model->afterLoad($product); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Catalog/Model/Product/Attribute/Backend/StockTest.php b/dev/tests/unit/testsuite/Mage/Catalog/Model/Product/Attribute/Backend/StockTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3ee7c02ad2bed3955b0645a9fe6333a60069f443 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Catalog/Model/Product/Attribute/Backend/StockTest.php @@ -0,0 +1,84 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Catalog + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Catalog_Model_Product_Attribute_Backend_StockTest extends PHPUnit_Framework_TestCase +{ + const ATTRIBUTE_NAME = 'quantity_and_stock_status'; + + /** + * @var Mage_Catalog_Model_Product_Attribute_Backend_Stock + */ + protected $_model; + + /** + * @var Mage_CatalogInventory_Model_Stock_Item + */ + protected $_inventory; + + protected function setUp() + { + $this->_inventory = $this->getMock('Mage_CatalogInventory_Model_Stock_Item', + array('getIsInStock', 'getQty', 'loadByProduct'), array(), '', false); + $this->_model = $this->getMock('Mage_Catalog_Model_Product_Attribute_Backend_Stock', array('getAttribute'), + array(array('inventory' => $this->_inventory)) + ); + $attribute = $this->getMock('Varien_Object', array('getAttributeCode')); + $attribute->expects($this->atLeastOnce())->method('getAttributeCode') + ->will($this->returnValue(self::ATTRIBUTE_NAME)); + $this->_model->expects($this->atLeastOnce())->method('getAttribute')->will($this->returnValue($attribute)); + } + + public function testAfterLoad() + { + $this->_inventory->expects($this->once())->method('getIsInStock')->will($this->returnValue(1)); + $this->_inventory->expects($this->once())->method('getQty')->will($this->returnValue(5)); + $object = new Varien_Object(); + $this->_model->afterLoad($object); + $data = $object->getData(); + $this->assertEquals(1, $data[self::ATTRIBUTE_NAME]['is_in_stock']); + $this->assertEquals(5, $data[self::ATTRIBUTE_NAME]['qty']); + } + + public function testBeforeSave() + { + $object = new Varien_Object(array( + self::ATTRIBUTE_NAME => array('is_in_stock' => 1, 'qty' => 5), + 'stock_data' => array('is_in_stock' => 2, 'qty' => 2) + )); + $stockData = $object->getStockData(); + $this->assertEquals(2, $stockData['is_in_stock']); + $this->assertEquals(2, $stockData['qty']); + $this->assertNotEmpty($object->getData(self::ATTRIBUTE_NAME)); + + $this->_model->beforeSave($object); + + $stockData = $object->getStockData(); + $this->assertEquals(1, $stockData['is_in_stock']); + $this->assertEquals(5, $stockData['qty']); + $this->assertNull($object->getData(self::ATTRIBUTE_NAME)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/CatalogInventory/Block/Adminhtml/Form/Field/StockTest.php b/dev/tests/unit/testsuite/Mage/CatalogInventory/Block/Adminhtml/Form/Field/StockTest.php new file mode 100644 index 0000000000000000000000000000000000000000..163be2bbd9827e2d48cc439b24aa9ec4668e087c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/CatalogInventory/Block/Adminhtml/Form/Field/StockTest.php @@ -0,0 +1,78 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Catalog + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_CatalogInventory_Block_Adminhtml_Form_Field_StockTest extends PHPUnit_Framework_TestCase +{ + const ATTRIBUTE_NAME = 'quantity_and_stock_status'; + + /** + * @var Mage_CatalogInventory_Block_Adminhtml_Form_Field_Stock + */ + protected $_model; + + /** + * @var Varien_Data_Form_Element_Text + */ + protected $_qty; + + protected function setUp() + { + $this->_qty = $this->getMock('Varien_Data_Form_Element_Text', + array('getElementHtml', 'setForm', 'setValue', 'setName') + ); + $this->_model = $this->getMock('Mage_CatalogInventory_Block_Adminhtml_Form_Field_Stock', + array('getElementHtml'), array(array('qty' => $this->_qty, 'name' => self::ATTRIBUTE_NAME))); + } + + public function testGetElementHtml() + { + $this->_qty->expects($this->once())->method('getElementHtml')->will($this->returnValue('html')); + $this->_model->expects($this->once())->method('getElementHtml') + ->will($this->returnValue($this->_qty->getElementHtml())); + $this->assertEquals('html', $this->_model->getElementHtml()); + } + + public function testSetForm() + { + $this->_qty->expects($this->once())->method('setForm') + ->with($this->isInstanceOf('Varien_Data_Form_Element_Abstract')); + $this->_model->setForm(new Varien_Data_Form_Element_Text()); + } + + public function testSetValue() + { + $value = array('qty' => 1, 'is_in_stock' => 0); + $this->_qty->expects($this->once())->method('setValue')->with($this->equalTo(1)); + $this->_model->setValue($value); + } + + public function testSetName() + { + $this->_qty->expects($this->once())->method('setName')->with(self::ATTRIBUTE_NAME . '[qty]'); + $this->_model->setName(self::ATTRIBUTE_NAME); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Downloadable/Model/ObserverTest.php b/dev/tests/unit/testsuite/Mage/Downloadable/Model/ObserverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5b423f70022f08666da7fa82cef40407b80bd9ee --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Downloadable/Model/ObserverTest.php @@ -0,0 +1,234 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Magento_Downloadable + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Downloadable_Model_ObserverTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Varien_Event_Observer + */ + protected $_observer; + + /** + * @var Mage_Downloadable_Model_Observer + */ + protected $_model; + + /** + * @var Mage_Core_Helper_Data + */ + protected $_helperJsonEncode; + + protected function setUp() + { + $this->_helperJsonEncode = $this->getMockBuilder('Mage_Core_Helper_Data') + ->setMethods(array('jsonEncode')) + ->disableOriginalConstructor() + ->getMock(); + $this->_model = new Mage_Downloadable_Model_Observer(array('helper' => $this->_helperJsonEncode)); + } + + protected function tearDown() + { + $this->_helperJsonEncode = null; + $this->_model = null; + $this->_observer = null; + } + + public function testDuplicateProductNotDownloadable() + { + $currentProduct = $this->getMock('Mage_Catalog_Model_Product', array('getTypeId'), array(), '', false); + + $currentProduct->expects($this->once()) + ->method('getTypeId') + ->will($this->returnValue(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE)); + $currentProduct->expects($this->never()) + ->method('getTypeInstance'); + + $this->_setObserverExpectedMethods($currentProduct, new Varien_Object()); + + $this->_model->duplicateProduct($this->_observer); + } + + public function testDuplicateProductEmptyLinks() + { + $currentProduct = $this->getMock('Mage_Catalog_Model_Product', + array('getTypeId', 'getTypeInstance'), array(), '', false); + $currentProduct->expects($this->once()) + ->method('getTypeId') + ->will($this->returnValue(Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE)); + $newProduct = $this->getMock('Mage_Catalog_Model_Product', + array('getTypeId', 'getTypeInstance'), array(), '', false); + + $typeInstance = $this->getMock('Mage_Downloadable_Model_Product_Type', + array('getLinks', 'getSamples'), array(), '', false); + $typeInstance->expects($this->once()) + ->method('getLinks') + ->will($this->returnValue(array())); + $typeInstance->expects($this->once()) + ->method('getSamples') + ->will($this->returnValue(new Varien_Object())); + + $currentProduct->expects($this->once()) + ->method('getTypeInstance') + ->will($this->returnValue($typeInstance)); + + $this->_setObserverExpectedMethods($currentProduct, $newProduct); + + $this->assertNull($newProduct->getDownloadableData()); + $this->_model->duplicateProduct($this->_observer); + $this->assertEmpty($newProduct->getDownloadableData()); + } + + public function testDuplicateProductTypeFile() + { + $currentProduct = $this->getMock('Mage_Catalog_Model_Product', + array('getTypeId', 'getTypeInstance'), array(), '', false); + $currentProduct->expects($this->once()) + ->method('getTypeId') + ->will($this->returnValue(Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE)); + + $newProduct = $this->getMock('Mage_Catalog_Model_Product', + array('getTypeId', 'getTypeInstance'), array(), '', false); + + $links = $this->_getLinks(); + + $samples = $this->_getSamples(); + + $getLinks = new Varien_Object($links); + + $getSamples = new Varien_Object($samples); + + $typeInstance = $this->getMock('Mage_Downloadable_Model_Product_Type', + array('getLinks', 'getSamples'), array(), '', false); + $typeInstance->expects($this->atLeastOnce()) + ->method('getLinks') + ->will($this->returnValue(array($getLinks))); + $typeInstance->expects($this->atLeastOnce()) + ->method('getSamples') + ->will($this->returnValue(array($getSamples))); + + $currentProduct->expects($this->atLeastOnce()) + ->method('getTypeInstance') + ->will($this->returnValue($typeInstance)); + + $this->_setObserverExpectedMethods($currentProduct, $newProduct); + + $callbackJsonEncode = function($arg) + { + return json_encode($arg); + }; + $this->_helperJsonEncode->expects($this->atLeastOnce()) + ->method('jsonEncode') + ->will($this->returnCallback($callbackJsonEncode)); + + $this->assertNull($newProduct->getDownloadableData($newProduct)); + $this->_model->duplicateProduct($this->_observer); + + $newDownloadableData = $newProduct->getDownloadableData(); + $fileData = json_decode($newDownloadableData['link'][0]['file'], true); + + $this->assertEquals($links['price'], $newDownloadableData['link'][0]['price']); + $this->assertEquals($links['link_file'][0], $fileData[0]['file'][0]); + $this->assertEquals($samples['title'], $newDownloadableData['sample'][0]['title']); + $this->assertEquals(false, $newDownloadableData['link'][0]['is_delete']); + $this->assertEquals($links['number_of_downloads'], $newDownloadableData['link'][0]['number_of_downloads']); + } + + /** + * Set products to observer + * + * @param array $currentProduct + * @param array $newProduct + */ + protected function _setObserverExpectedMethods($currentProduct, $newProduct) + { + $this->_observer = $this->getMock('Varien_Event_Observer', + array('getCurrentProduct', 'getNewProduct'), array(), '', false); + $this->_observer->expects($this->once()) + ->method('getCurrentProduct') + ->will($this->returnValue($currentProduct)); + $this->_observer->expects($this->once()) + ->method('getNewProduct') + ->will($this->returnValue($newProduct)); + } + + /** + * Get Downloadable Link Data + * + * @return array + */ + protected function _getLinks() + { + return array( + 'link_id' => '36', + 'product_id' => '141', + 'sort_order' => '0', + 'number_of_downloads' => '0', + 'is_shareable' => '2', + 'link_url' => null, + 'link_file' => array(array( + 'file' => '/l/i/lighthouse_3.jpg', + 'name' => 'lighthouse_3.jpg', + 'size' => 56665, + 'status' => 'new', + )), + 'link_type' => 'file', + 'sample_url' => null, + 'sample_file' => array(array( + 'file' => '/a/b/lighthouse_3.jpg', + 'name' => 'lighthouse_3.jpg', + 'size' => 56665, + 'status' => 'new', + )), + 'sample_type' => 'file', + 'title' =>'Link Title', + 'price' =>'15.00', + ); + } + + /** + * Get Downloadable Sample Data + * + * @return array + */ + protected function _getSamples() + { + return array( + 'sample_id' => '42', + 'sample_url' => null, + 'sample_file' => array(array( + 'file' => '/b/r/lighthouse_3.jpg', + 'name' => 'lighthouse_3.jpg', + 'size' => 56665, + 'status' => 'new', + )), + 'sample_type' => 'file', + 'sort_order' => '0', + 'title' => 'Sample Title', + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Eav/Model/Resource/Entity/AttributeTest.php b/dev/tests/unit/testsuite/Mage/Eav/Model/Resource/Entity/AttributeTest.php index ffe5a8fc84cd0bff0bcf68a3c46a79911059b543..018202a0a66fcca27027050e4e0149f714a44280 100644 --- a/dev/tests/unit/testsuite/Mage/Eav/Model/Resource/Entity/AttributeTest.php +++ b/dev/tests/unit/testsuite/Mage/Eav/Model/Resource/Entity/AttributeTest.php @@ -65,10 +65,6 @@ class Mage_Eav_Model_Resource_Entity_AttributeTest extends PHPUnit_Framework_Tes array('eav_attribute', $attributeData, 1), ))); - //this line causes crash on windows environment - //$adapter->expects($this->never())->method('update'); - $adapter->expects($this->never())->method('delete'); - $adapter->expects($this->once()) ->method('fetchRow') ->will($this->returnValueMap(array( @@ -78,6 +74,10 @@ class Mage_Eav_Model_Resource_Entity_AttributeTest extends PHPUnit_Framework_Tes $attributeData ), ))); + $adapter->expects($this->once()) + ->method('update') + ->with('eav_attribute', array('default_value' => 2), array('attribute_id = ?' => null)); + $adapter->expects($this->never())->method('delete'); $resourceModel->save($model); } diff --git a/dev/tests/unit/testsuite/Mage/Index/Model/Lock/StorageTest.php b/dev/tests/unit/testsuite/Mage/Index/Model/Lock/StorageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f9376c8f26ec6b0f1ce63ce83043e0fa28f73e23 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Index/Model/Lock/StorageTest.php @@ -0,0 +1,115 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Index + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for Mage_Index_Model_Lock_Storage + */ +class Mage_Index_Model_Lock_StorageTest extends PHPUnit_Framework_TestCase +{ + /** + * Test var directory + */ + const VAR_DIRECTORY = 'test'; + + /** + * Locks storage model + * + * @var Mage_Index_Model_Lock_Storage + */ + protected $_storage; + + /** + * Keep current process id for tests + * + * @var integer + */ + protected $_currentProcessId; + + protected function setUp() + { + $config = $this->getMock('Mage_Core_Model_Config', array('getVarDir'), array(), '', false); + $config->expects($this->exactly(2)) + ->method('getVarDir') + ->will($this->returnValue(self::VAR_DIRECTORY)); + + $fileModel = $this->getMock('Mage_Index_Model_Process_File', + array( + 'setAllowCreateFolders', + 'open', + 'streamOpen', + 'streamWrite', + ) + ); + + $fileModel->expects($this->exactly(2)) + ->method('setAllowCreateFolders') + ->with(true); + $fileModel->expects($this->exactly(2)) + ->method('open') + ->with(array('path' => self::VAR_DIRECTORY)); + $fileModel->expects($this->exactly(2)) + ->method('streamOpen') + ->will($this->returnCallback(array($this, 'checkFilenameCallback'))); + $fileModel->expects($this->exactly(2)) + ->method('streamWrite') + ->with($this->isType('string')); + + $fileFactory = $this->getMock('Mage_Index_Model_Process_FileFactory', array('createFromArray'), array(), '', + false + ); + $fileFactory->expects($this->exactly(2)) + ->method('createFromArray') + ->will($this->returnValue($fileModel)); + + $this->_storage = new Mage_Index_Model_Lock_Storage($config, $fileFactory); + } + + public function testGetFile() + { + /** + * List if test process IDs. + * We need to test cases when new ID and existed ID passed into tested method. + */ + $processIdList = array(1, 2, 2); + foreach ($processIdList as $processId) { + $this->_currentProcessId = $processId; + $this->assertInstanceOf('Mage_Index_Model_Process_File', $this->_storage->getFile($processId)); + } + $this->assertAttributeCount(2, '_fileHandlers', $this->_storage); + } + + /** + * Check file name + * + * @param string $filename + */ + public function checkFilenameCallback($filename) + { + $expected = 'index_process_' . $this->_currentProcessId . '.lock'; + $this->assertEquals($expected, $filename); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Index/Model/Process/FileFactoryTest.php b/dev/tests/unit/testsuite/Mage/Index/Model/Process/FileFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b7d86330ef550f9dea411dc60525b5756b036b9c --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Index/Model/Process/FileFactoryTest.php @@ -0,0 +1,61 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Index + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Unit test for Mage_Index_Model_Process_FileFactory + */ +class Mage_Index_Model_Process_FileFactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * Bogus string to return from object manager's create() method + */ + const CREATE_RESULT = 'create_result'; + + /** + * Expected class name + */ + const EXPECTED_CLASS_NAME = 'Mage_Index_Model_Process_File'; + + /** + * @var array + */ + protected $_arguments = array( + 'key' => 'value' + ); + + public function testCreateFromArray() + { + $objectManagerMock = $this->getMock('Magento_ObjectManager', array(), array(), '', false); + $objectManagerMock->expects($this->once()) + ->method('create') + ->with(self::EXPECTED_CLASS_NAME, $this->_arguments, false) + ->will($this->returnValue(self::CREATE_RESULT)); + + $factory = new Mage_Index_Model_Process_FileFactory($objectManagerMock); + $this->assertEquals(self::CREATE_RESULT, $factory->createFromArray($this->_arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Index/Model/ProcessTest.php b/dev/tests/unit/testsuite/Mage/Index/Model/ProcessTest.php new file mode 100644 index 0000000000000000000000000000000000000000..837710190a7b2597435a8ed7af176b97aa2c356d --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Index/Model/ProcessTest.php @@ -0,0 +1,163 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_Index + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for Mage_Index_Model_Process + */ +class Mage_Index_Model_ProcessTest extends PHPUnit_Framework_TestCase +{ + /** + * Process ID for tests + */ + const PROCESS_ID = 'testProcessId'; + + /** + * @var PHPUnit_Framework_MockObject_MockObject|Mage_Index_Model_Process_File + */ + protected $_processFile; + + /** + * @var PHPUnit_Framework_MockObject_MockObject|Mage_Index_Model_Process + */ + protected $_indexProcess; + + protected function tearDown() + { + unset($this->_processFile); + unset($this->_indexProcess); + } + + public function testLock() + { + $this->_prepareMocksForTestLock(true); + + $result = $this->_indexProcess->lock(); + $this->assertEquals($this->_indexProcess, $result); + } + + public function testLockAndBlock() + { + $this->_prepareMocksForTestLock(false); + + $result = $this->_indexProcess->lockAndBlock(); + $this->assertEquals($this->_indexProcess, $result); + } + + public function testGetProcessFile() + { + $this->_processFile = $this->getMock('Mage_Index_Model_Process_File'); + $this->_prepareIndexProcess(); + + // assert that process file is stored in process entity instance and isn't changed after several invocations + // lock method is used as invocation of _getProcessFile + for ($i = 1; $i <= 2; $i++) { + $this->_indexProcess->lock(); + $this->assertAttributeEquals($this->_processFile, '_processFile', $this->_indexProcess); + } + } + + /** + * Create Mage_Index_Model_Process instance for lock tests + * + * @param bool $nonBlocking + */ + protected function _prepareMocksForTestLock($nonBlocking) + { + $this->_processFile = $this->getMock('Mage_Index_Model_Process_File', array('processLock')); + $this->_processFile->expects($this->once()) + ->method('processLock') + ->with($nonBlocking); + + $this->_prepareIndexProcess(); + } + + /** + * Create index process instance + */ + protected function _prepareIndexProcess() + { + /** @var $eventDispatcher Mage_Core_Model_Event_Manager */ + $eventDispatcher = $this->getMock('Mage_Core_Model_Event_Manager', array(), array(), '', false); + /** @var $cacheManager Mage_Core_Model_Cache */ + $cacheManager = $this->getMock('Mage_Core_Model_Cache', array(), array(), '', false); + + $lockStorage = $this->getMock('Mage_Index_Model_Lock_Storage', array('getFile'), array(), '', false); + $lockStorage->expects($this->once()) + ->method('getFile') + ->with(self::PROCESS_ID) + ->will($this->returnValue($this->_processFile)); + + $this->_indexProcess = new Mage_Index_Model_Process( + $eventDispatcher, + $cacheManager, + $lockStorage, + null, + null, + array('process_id' => self::PROCESS_ID) + ); + } + + public function testUnlock() + { + $this->_processFile = $this->getMock('Mage_Index_Model_Process_File', array('processUnlock')); + $this->_processFile->expects($this->once()) + ->method('processUnlock'); + $this->_prepareIndexProcess(); + + $result = $this->_indexProcess->unlock(); + $this->assertEquals($this->_indexProcess, $result); + } + + /** + * Data Provider for testIsLocked + * + * @return array + */ + public function isLockedDataProvider() + { + return array( + 'need to unlock process' => array('$needUnlock' => true), + 'no need to unlock process' => array('$needUnlock' => false), + ); + } + + /** + * @dataProvider isLockedDataProvider + * @param bool $needUnlock + */ + public function testIsLocked($needUnlock) + { + $this->_processFile = $this->getMock('Mage_Index_Model_Process_File', array('isProcessLocked')); + $this->_processFile->expects($this->once()) + ->method('isProcessLocked') + ->with($needUnlock) + ->will($this->returnArgument(0)); + $this->_prepareIndexProcess(); + + $this->assertEquals($needUnlock, $this->_indexProcess->isLocked($needUnlock)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Sales/Model/Order/Shipment/TrackTest.php b/dev/tests/unit/testsuite/Mage/Sales/Model/Order/Shipment/TrackTest.php index 50e38e821d5f66f3c45b1327cf4e1a90e026325a..7548c20da7dc02fd0f262c161d1edca1abdf1a1a 100644 --- a/dev/tests/unit/testsuite/Mage/Sales/Model/Order/Shipment/TrackTest.php +++ b/dev/tests/unit/testsuite/Mage/Sales/Model/Order/Shipment/TrackTest.php @@ -34,7 +34,8 @@ class Mage_Sales_Model_Order_Shipment_TrackTest extends PHPUnit_Framework_TestCa protected function setUp() { - $this->_model = $this->getMock('Mage_Sales_Model_Order_Shipment_Track', null, array(), '', false); + $helper = new Magento_Test_Helper_ObjectManager($this); + $this->_model = $helper->getModel('Mage_Sales_Model_Order_Shipment_Track'); } public function testAddData() @@ -49,4 +50,20 @@ class Mage_Sales_Model_Order_Shipment_TrackTest extends PHPUnit_Framework_TestCa $this->assertTrue($this->_model->getTest()); $this->assertEquals($number, $this->_model->getTrackNumber()); } + + public function testGetStoreId() + { + $storeId = 10; + $storeObject = new Varien_Object( + array('id' => $storeId) + ); + + $shipmentMock = $this->getMock('Mage_Sales_Model_Order_Shipment', array('getStore'), array(), '', false); + $shipmentMock->expects($this->once()) + ->method('getStore') + ->will($this->returnValue($storeObject)); + + $this->_model->setShipment($shipmentMock); + $this->assertEquals($storeId, $this->_model->getStoreId()); + } } diff --git a/dev/tests/unit/testsuite/Mage/SalesRule/Model/Resource/Report/RuleTest.php b/dev/tests/unit/testsuite/Mage/SalesRule/Model/Resource/Report/RuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6c177b1cd2eb88ae4b1012a0c95dada93717e558 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/SalesRule/Model/Resource/Report/RuleTest.php @@ -0,0 +1,103 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Magento + * @package Mage_SalesRule + * @subpackage unit_tests + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_SalesRule_Model_Resource_Report_RuleTest extends PHPUnit_Framework_TestCase +{ + /** + * Test table name + */ + const TABLE_NAME = 'test'; + + /** + * List of test rules; + * + * @var array + */ + protected $_rules = array( + array('rule_name' => 'test1'), + array('rule_name' => 'test2'), + array('rule_name' => 'test3') + ); + + public function testGetUniqRulesNamesList() + { + $dbAdapterMock = $this->getMockForAbstractClass('Zend_Db_Adapter_Abstract', array(), '', false); + $select = $this->getMock('Varien_Db_Select', array('from'), array($dbAdapterMock)); + $select->expects($this->once()) + ->method('from') + ->with(self::TABLE_NAME, $this->isInstanceOf('Zend_Db_Expr')) + ->will($this->returnValue($select)); + + $adapterMock = $this->getMock('Varien_Db_Adapter_Pdo_Mysql', array('select', 'fetchAll'), array(), '', false); + $adapterMock->expects($this->once()) + ->method('select') + ->will($this->returnValue($select)); + $adapterMock->expects($this->once()) + ->method('fetchAll') + ->with($select) + ->will($this->returnCallback(array($this, 'fetchAllCallback'))); + + $resourceMock = $this->getMock('Mage_Core_Model_Resource', array('getConnection', 'getTableName'), array(), '', + false + ); + $resourceMock->expects($this->any()) + ->method('getConnection') + ->will($this->returnValue($adapterMock)); + $resourceMock->expects($this->once()) + ->method('getTableName') + ->will($this->returnValue(self::TABLE_NAME)); + + $model = new Mage_SalesRule_Model_Resource_Report_Rule($resourceMock); + + $expectedRuleNames = array(); + foreach ($this->_rules as $rule) { + $expectedRuleNames[] = $rule['rule_name']; + } + $this->assertEquals($expectedRuleNames, $model->getUniqRulesNamesList()); + } + + /** + * Check structure of sql query + * + * @param Varien_Db_Select $select + * @return array + */ + public function fetchAllCallback(Varien_Db_Select $select) + { + $whereParts = $select->getPart(Varien_Db_Select::WHERE); + $this->assertCount(2, $whereParts); + $this->assertContains("rule_name IS NOT NULL", $whereParts[0]); + $this->assertContains("rule_name <> ''", $whereParts[1]); + + $orderParts = $select->getPart(Varien_Db_Select::ORDER); + $this->assertCount(1, $orderParts); + $expectedOrderParts = array('rule_name', 'ASC'); + $this->assertEquals($expectedOrderParts, $orderParts[0]); + + return $this->_rules; + } +} diff --git a/dev/tests/unit/testsuite/Varien/Io/FileTest.php b/dev/tests/unit/testsuite/Varien/Io/FileTest.php index 7a71401351276e475d2e257d66522620d69da169..74bf22ad612f2c10b013b9027ebadbfda2b82c49 100644 --- a/dev/tests/unit/testsuite/Varien/Io/FileTest.php +++ b/dev/tests/unit/testsuite/Varien/Io/FileTest.php @@ -37,72 +37,54 @@ class Varien_Io_FileTest extends PHPUnit_Framework_TestCase */ protected $_file; - public function testChmodRecursive() + protected function setUp() { try { - $this->_prepare(); - if (substr(PHP_OS, 0, 3) == 'WIN') { - $this->markTestSkipped("chmod may not work for Windows"); + $this->_dir = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'directory'; + $this->_file = $this->_dir . DIRECTORY_SEPARATOR . 'file.txt'; + mkdir($this->_dir, 0700, true); + if (touch($this->_file)) { + chmod($this->_file, 0700); } - $permsBefore = 0700; - $expected = 0777; - $this->assertEquals($permsBefore, fileperms($this->_dir) & $permsBefore, - "Wrong permissions set for " . $this->_dir); - $this->assertEquals($permsBefore, fileperms($this->_file) & $permsBefore, - "Wrong permissions set for " . $this->_file); - Varien_Io_File::chmodRecursive($this->_dir, $expected); - $this->assertEquals($expected, fileperms($this->_dir) & $expected, - "Directory permissions were changed incorrectly."); - $this->assertEquals($expected, fileperms($this->_file) & $expected, - "File permissions were changed incorrectly."); - } catch (Exception $e) { - } - - $this->_cleanup(); - if (isset($e)) { - throw $e; + } catch (PHPUnit_Framework_Error_Warning $exception) { + $this->markTestSkipped("Problem with prepare test: " . $exception->getMessage()); } } - public function testRmdirRecursive() + protected function tearDown() { - try { - $this->_prepare(); - $this->assertFileExists($this->_file); - Varien_Io_File::rmdirRecursive($this->_dir); - $this->assertFileNotExists($this->_dir); - } catch (Exception $e) { + if (@file_exists($this->_file)) { + @unlink($this->_file); } - - $this->_cleanup(); - if (isset($e)) { - throw $e; + if (@file_exists($this->_dir)) { + @rmdir($this->_dir); } } - /** - * Create files for tests - */ - protected function _prepare() + public function testChmodRecursive() { - $this->_dir = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'directory'; - $this->_file = $this->_dir . DIRECTORY_SEPARATOR . 'file.txt'; - @mkdir($this->_dir, 0700, true); - if (@touch($this->_file)) { - chmod($this->_file, 0700); + if (substr(PHP_OS, 0, 3) == 'WIN') { + $this->markTestSkipped("chmod may not work for Windows"); } + + $permsBefore = 0700; + $expected = 0777; + $this->assertEquals($permsBefore, fileperms($this->_dir) & $permsBefore, + "Wrong permissions set for " . $this->_dir); + $this->assertEquals($permsBefore, fileperms($this->_file) & $permsBefore, + "Wrong permissions set for " . $this->_file); + Varien_Io_File::chmodRecursive($this->_dir, $expected); + $this->assertEquals($expected, fileperms($this->_dir) & $expected, + "Directory permissions were changed incorrectly."); + $this->assertEquals($expected, fileperms($this->_file) & $expected, + "File permissions were changed incorrectly."); + } - /** - * Remove fixture files - */ - protected function _cleanup() + public function testRmdirRecursive() { - if (file_exists($this->_file)) { - @unlink($this->_file); - } - if (file_exists($this->_dir)) { - @rmdir($this->_dir); - } + $this->assertFileExists($this->_file); + Varien_Io_File::rmdirRecursive($this->_dir); + $this->assertFileNotExists($this->_dir); } } diff --git a/dev/tools/migration/aliases_map/cms_content_tables_ce.php b/dev/tools/migration/aliases_map/cms_content_tables_ce.php new file mode 100644 index 0000000000000000000000000000000000000000..af025c2146bba2ff1e9b8f34578802f2537216da --- /dev/null +++ b/dev/tools/migration/aliases_map/cms_content_tables_ce.php @@ -0,0 +1,33 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Mage + * @package Mage + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * List of tables and fields with cms content Magento CE + */ +return array( + 'cms_page' => 'content', + 'cms_block' => 'content', +); diff --git a/dev/tools/migration/themes_view.php b/dev/tools/migration/themes_view.php new file mode 100644 index 0000000000000000000000000000000000000000..f0e5e8581905ff0554fccdb533b1a7ddf8f80bc7 --- /dev/null +++ b/dev/tools/migration/themes_view.php @@ -0,0 +1,122 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @category Tools + * @package system_configuration + * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Constants definition + */ +define('DS', DIRECTORY_SEPARATOR); +define('BP', realpath(__DIR__ . '/../../..')); +/** + * Require necessary files + */ +require_once BP . '/lib/Magento/Autoload.php'; +require_once BP . '/app/code/core/Mage/Core/functions.php'; +require_once BP . '/app/Mage.php'; + +$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local'; +$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community'; +$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core'; +$paths[] = BP . DS . 'lib'; +Magento_Autoload::getInstance()->addIncludePath($paths); +Mage::setRoot(); +Mage::setIsDeveloperMode(true); + +try { + Mage::getConfig()->cleanCache(); + Mage::getConfig()->reinit(); + $config = array(); + + foreach (glob(dirname(__FILE__) . '/aliases_map/cms_content_tables_*.php', GLOB_BRACE) as $configFile) { + $config = array_merge($config, include($configFile)); + } + + foreach ($config as $table => $field) { + updateFieldForTable($table, $field); + } +} catch (Exception $e) { + echo "Make sure that you launch this script with Magento 2 configured sources. \n\n"; + echo $e->getMessage(); +} + +/** + * Replace {{skin url=""}} with {{view url=""}} for given table field + * + * @param string $table + * @param string $col + */ +function updateFieldForTable($table, $col) +{ + /** @var $installer Mage_Core_Model_Resource_Setup */ + $installer = Mage::getResourceModel('Mage_Core_Model_Resource_Setup', array('resourceName' => 'core_setup')); + $installer->startSetup(); + + $table = $installer->getTable($table); + print '-----' . "\n"; + if ($installer->getConnection()->isTableExists($table)) { + print 'Table `' . $table . "` processed\n"; + + $indexList = $installer->getConnection()->getIndexList($table); + $pkField = array_shift($indexList[$installer->getConnection()->getPrimaryKeyName($table)]['fields']); + /** @var $select Varien_Db_Select */ + $select = $installer->getConnection()->select()->from($table, array('id' => $pkField, 'content' => $col)); + $result = $installer->getConnection()->fetchPairs($select); + + print 'Records count: ' . count($result) . ' in table: `' . $table . "`\n"; + + $logMessages = array(); + foreach ($result as $recordId => $string) { + $content = str_replace('{{skin', '{{view', $string, $count); + if ($count) { + $installer->getConnection()->update($table, array($col => $content), + $installer->getConnection()->quoteInto($pkField . '=?', $recordId)); + $logMessages['replaced'][] = 'Replaced -- Id: ' . $recordId . ' in table `' . $table . '`'; + } else { + $logMessages['skipped'][] = 'Skipped -- Id: ' . $recordId . ' in table `' . $table . '`'; + } + } + if (count($result)) { + printLog($logMessages); + } + } else { + print 'Table `' . $table . "` was not found\n"; + } + $installer->endSetup(); + print '-----' . "\n"; +} + +/** + * Print array of messages + * + * @param array $logMessages + */ +function printLog($logMessages) +{ + foreach ($logMessages as $stringsArray) { + print "\n"; + print implode("\n", $stringsArray); + print "\n"; + } +}