diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 571d65fc847878f40390ee20a6d82e366fb3e0b3..8769957444946b6ffd90f199740b907afa1f3d75 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -1,3 +1,24 @@ +2.0.0.0-dev36 +============= +* Visual design editor refactored + * VDE controls and VDE actions moved to backend area + * Added IFRAME that allows to navigate through frontend pages in Navigation Mode and to modify blocks position in Design Mode + * Inline JavaScript code is disabled in Design Mode + * Store selection is performed on saving instead of reviewing the theme. List of all available stores is shown during assigning the theme to a store + * `System -> Design -> Editor` page divided into two tabs: + * "Available Themes" tab contains all available themes + * "My Customizations" tab contains themes customized by the store administrator and consists of area with themes assigned to stores and area with unassigned themes + * Added `vde` area code and `Mage_DesignEditor_Controller_Varien_Router_Standard` to handle requests from design editor + * Added ability to use custom layout instance in controllers to use specific layout, when design editor is launched +* JavaScript updates + * Replaced `varienTabs` class with an analogous jQuery widget + * Displaying of loader during AJAX requests became optional +* Removed `dev/api-tests` directory added by mistake +* Bug fixes + * Impossible to login to backend with APC enabled. Added call of `session_write_close()` in the session model destructor + * Unnecessary regions shown when no country is selected in `System -> Sales -> Shipping Settings -> Origin` + * Fixed various bugs caused by virtual themes implementation and other themes improvements + 2.0.0.0-dev35 ============= * Enhancements of System Configuration: @@ -206,11 +227,10 @@ 2.0.0.0-dev29 ============= -* Added scripts that allow upgrading database from CE 1.7 (EE 1.12) to 2.x +* Implemented and verified ability to upgrade DB from CE 1.7 (EE 1.12) to 2.x * Replaced calendar UI component with jQuery calendar -* Removed store scope selector from backend customers management -* Renamed `pub/js` (was known as `js` in Magento 1.x) into `pub/lib` * Restored back the public access to `pub/cron.php` entry point (in the previous patch it was denied by mistake) +* Fixed typo in label of "Catalog Search" index in UI 2.0.0.0-dev28 ============= @@ -658,7 +678,7 @@ ============= * Implemented a tool for migrating factory table names from 1.x to 2.x. The tool replaces table names by list of names associations * Changed Unit tests suite running from usage AllTests.php in each directory to configuration in phpunit.xml.dist. Now all tests in `testsuite` directory are launched, there is no necessity to add new tests to the config -* Implemented in Visual Desig Editor: +* Implemented in Visual Design Editor: * Containers highlighting * Dropping of elements * Fixed some issues: @@ -732,10 +752,10 @@ 2.0.0.0-dev02 ============= Deprecated code & minor fixes update: -* eliminated remnants of `htmlescape` implementation -* eliminated usage of `pub/js/index.php` entry point (used to be `js/index.php`) -* disbanded the shell root directory: moved scripts into `dev/shell` and classes into app -* minor refactoring of data fixtures rollback capability in integration testing framework +* Eliminated remnants of `htmlescape` implementation +* Eliminated usage of `pub/js/index.php` entry point (used to be `js/index.php`) +* Disbanded the shell root directory: moved scripts into `dev/shell` and classes into app +* Minor refactoring of data fixtures rollback capability in integration testing framework 2.0.0.0-dev01 ============= diff --git a/app/Mage.php b/app/Mage.php index d5c8e4988e61df908957a92721bad32ed1d5bb63..bb77e5463389e6adaa3d69de61c40223aeb21c47 100644 --- a/app/Mage.php +++ b/app/Mage.php @@ -170,7 +170,7 @@ final class Mage 'revision' => '0', 'patch' => '0', 'stability' => 'dev', - 'number' => '35', + 'number' => '36', ); } @@ -563,24 +563,6 @@ final class Mage return self::registry($registryKey); } - /** - * Retrieve Controller instance by ClassName - * - * @param string $class - * @param Mage_Core_Controller_Request_Http $request - * @param Mage_Core_Controller_Response_Http $response - * @param array $invokeArgs - * @return Mage_Core_Controller_Front_Action - */ - public static function getControllerInstance($class, $request, $response, array $invokeArgs = array()) - { - return self::getObjectManager()->create($class, array( - 'request' => $request, - 'response' => $response, - 'invokeArgs' => $invokeArgs - )); - } - /** * Returns block singleton instance, if current action exists. Otherwise returns FALSE. * diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Helper/Form/Wysiwyg.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Helper/Form/Wysiwyg.php index 20da88b8b256b37f935008c3538dc2e578f08be1..114546ed60afb9e715c9a6fe2c00d015b8b25859 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Helper/Form/Wysiwyg.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Helper/Form/Wysiwyg.php @@ -43,7 +43,7 @@ class Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg extends Varien_Data_Form_ $html = parent::getAfterElementHtml(); if ($this->getIsWysiwygEnabled()) { $disabled = ($this->getDisabled() || $this->getReadonly()); - $html .= Mage::getSingleton('Mage_Core_Model_Layout') + $html .= Mage::app()->getLayout() ->createBlock('Mage_Adminhtml_Block_Widget_Button', '', array( 'label' => Mage::helper('Mage_Catalog_Helper_Data')->__('WYSIWYG Editor'), 'type' => 'button', diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/New/Product/Created.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/New/Product/Created.php index f999b084631bea4a842e4623eca0f45fdff1464a..f883b1c8280c1a34b8d1c9bdbef3d34bae428070 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/New/Product/Created.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/New/Product/Created.php @@ -92,7 +92,7 @@ class Mage_Adminhtml_Block_Catalog_Product_Attribute_New_Product_Created extends public function getAttributesBlockJson() { $result = array( - $this->getRequest()->getParam('tab') => $this->getChildHtml('attributes') + $this->getRequest()->getParam('product_tab') => $this->getChildHtml('attributes') ); $newAttributeSetId = $this->getRequest()->getParam('new_attribute_set_id'); if ($newAttributeSetId) { diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Attributes/Create.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Attributes/Create.php index 81259edd8a503a2218b94cebffd95f7ac6224488..7dc6f5b136c3e942e970cea1dd78c198c19a0c37 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Attributes/Create.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Attributes/Create.php @@ -66,13 +66,13 @@ class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Attributes_Create extends Ma ->setUrl($this->getUrl( '*/catalog_product_attribute/new', array( - 'group' => $this->getConfig()->getGroupId(), - 'tab' => $this->getConfig()->getTabId(), - 'store' => $this->getConfig()->getStoreId(), - 'product' => $this->getConfig()->getProductId(), - 'set' => $this->getConfig()->getAttributeSetId(), - 'type' => $this->getConfig()->getTypeId(), - 'popup' => 1 + 'group' => $this->getConfig()->getGroupId(), + 'product_tab' => $this->getConfig()->getTabId(), + 'store' => $this->getConfig()->getStoreId(), + 'product' => $this->getConfig()->getProductId(), + 'set' => $this->getConfig()->getAttributeSetId(), + 'type' => $this->getConfig()->getTypeId(), + 'popup' => 1 ) )); diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Gallery.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Gallery.php index 77264848dc56df7878605c6fbb3c6b4ee1e69ac9..7b9aaeb37f3a443090c101721b2c179d2ad38d02 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Gallery.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Gallery.php @@ -50,7 +50,7 @@ class Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Gallery extends Varien_Da { /* @var $content Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Gallery_Content */ - $content = Mage::getSingleton('Mage_Core_Model_Layout') + $content = Mage::app()->getLayout() ->createBlock('Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Gallery_Content'); $content->setId($this->getHtmlId() . '_content')->setElement($this); diff --git a/app/code/core/Mage/Adminhtml/Block/Cms/Page/Edit.php b/app/code/core/Mage/Adminhtml/Block/Cms/Page/Edit.php index 5a1d00a4ebc29e7cd7f2b8e76757f108d981ab05..b9a40077e99d548273fcd6ead1cebd3dc5ca62fb 100644 --- a/app/code/core/Mage/Adminhtml/Block/Cms/Page/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/Cms/Page/Edit.php @@ -130,8 +130,11 @@ class Mage_Adminhtml_Block_Cms_Page_Edit extends Mage_Adminhtml_Block_Widget_For tinyMCE.execCommand('mceRemoveControl', false, 'page_content'); } } - " . $tabsBlockJsObject . ".tabsBlockPrefix = '" . $tabsBlockPrefix . "'; - " . $tabsBlockJsObject . ".tabIdArgument = 'active_tab'; + jQuery(function() { + jQuery(\"#" . $tabsBlock->getId() ."\") + .tabs('option', 'tabsBlockPrefix', '" . $tabsBlockPrefix . "') + .tabs('option', 'tabIdArgument', 'active_tab'); + }); "; return parent::_prepareLayout(); } diff --git a/app/code/core/Mage/Adminhtml/Controller/Action.php b/app/code/core/Mage/Adminhtml/Controller/Action.php index af8401c57563993a6bb5e238b95b4fe00cbe0917..47d9b5ef84fe07df75325ec38415b02c9580f9f9 100644 --- a/app/code/core/Mage/Adminhtml/Controller/Action.php +++ b/app/code/core/Mage/Adminhtml/Controller/Action.php @@ -29,7 +29,6 @@ */ class Mage_Adminhtml_Controller_Action extends Mage_Backend_Controller_ActionAbstract { - /** * Used module name in current adminhtml controller */ @@ -48,21 +47,26 @@ class Mage_Adminhtml_Controller_Action extends Mage_Backend_Controller_ActionAbs protected $_translator; /** - * Constructor - * - * @param Zend_Controller_Request_Abstract $request - * @param Zend_Controller_Response_Abstract $response + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Controller_Response_Http $response + * @param string $areaCode * @param Magento_ObjectManager $objectManager * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Layout_Factory $layoutFactory * @param array $invokeArgs */ - public function __construct(Zend_Controller_Request_Abstract $request, - Zend_Controller_Response_Abstract $response, + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Controller_Response_Http $response, + $areaCode = null, Magento_ObjectManager $objectManager, Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Layout_Factory $layoutFactory, array $invokeArgs = array() ) { - parent::__construct($request, $response, $objectManager, $frontController, $invokeArgs); + parent::__construct($request, $response, $areaCode, $objectManager, $frontController, $layoutFactory, + $invokeArgs + ); $this->_translator = isset($invokeArgs['translator']) ? $invokeArgs['translator'] : $this->_getTranslator(); } diff --git a/app/code/core/Mage/Adminhtml/controllers/System/Config/System/StorageController.php b/app/code/core/Mage/Adminhtml/controllers/System/Config/System/StorageController.php index 8e31d4c9cb5f8e07f20d65b197fb31e9143f7502..f5efa23821b50d9002dd2649e3f28329f8c0433d 100644 --- a/app/code/core/Mage/Adminhtml/controllers/System/Config/System/StorageController.php +++ b/app/code/core/Mage/Adminhtml/controllers/System/Config/System/StorageController.php @@ -155,7 +155,7 @@ class Mage_Adminhtml_System_Config_System_StorageController extends Mage_Adminht $state = Mage_Core_Model_File_Storage_Flag::STATE_NOTIFIED; case Mage_Core_Model_File_Storage_Flag::STATE_NOTIFIED: - $block = Mage::getSingleton('Mage_Core_Model_Layout') + $block = Mage::app()->getLayout() ->createBlock('Mage_Adminhtml_Block_Notification_Toolbar') ->setTemplate('notification/toolbar.phtml'); $result['html'] = $block->toHtml(); diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml index fe724ee61925806d706d3e6adf729f7412b6303f..635895b0b112ce422d6c605efb2f8a436e74da7c 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog.xml @@ -44,6 +44,7 @@ <update handle="editor"/> <reference name="head"> <action method="addCss"><file>Mage_Adminhtml::css/ui-lightness/jquery-ui-1.8.21.custom.css</file></action> + <action method="addCss"><file>Mage_Adminhtml::css/ui-lightness/tabs.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/jquery.iframe-transport.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/jquery.fileupload.js</file></action> @@ -79,7 +80,6 @@ <adminhtml_catalog_product_edit> <update handle="editor"/> <reference name="head"> - <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/jquery.iframe-transport.js</file></action> <action method="addJs"><file>Mage_Adminhtml::jquery/fileUploader/jquery.fileupload.js</file></action> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit.js b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit.js index f7619910406b4628f2938f7694c08760f170d860..b37a56474ce6e34e52075e88dbdcf7b0b9be9f48 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit.js +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit.js @@ -80,8 +80,8 @@ function categorySubmit(url, useAjax) { var activeTab = $('active_tab_id'); if (activeTab) { - if (activeTab.tabsJsObject && activeTab.tabsJsObject.activeTab) { - activeTab.value = activeTab.tabsJsObject.activeTab.id; + if (activeTab.tabsJsObject && activeTab.tabsJsObject.tabs('activeAnchor')) { + activeTab.value = activeTab.tabsJsObject.tabs('activeAnchor').prop('id'); } } diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit/form.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit/form.phtml index fa391d79e0eee2eb6b54b89f95d271cdda0db249..d2102ac11916cd10f3c21f28059c338303bbea84 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit/form.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/edit/form.phtml @@ -123,11 +123,13 @@ <?php endif; ?> <?php if($this->isAjax() && ($block = $this->getLayout()->getBlock('tabs')) && ($_tabsJsObject=$block->getJsObjectName())): ?> - <?php echo $_tabsJsObject ?>.moveTabContentInDest(); - if (<?php echo $_tabsJsObject ?>.activeTab) { - $('active_tab_id').value = <?php echo $_tabsJsObject ?>.activeTab.id; + // Temporary solution, will be replaced after refactoring of manage category functionality + <?php $tabsBlock = $this->getLayout()->getBlock('tabs'); ?> + var activeAnchor = jQuery('#<?php echo $tabsBlock->getId() ?>').tabs('activeAnchor'); + if (activeAnchor.length) { + $('active_tab_id').value = activeAnchor.prop('id'); } - $('active_tab_id').tabsJsObject = <?php echo $_tabsJsObject ?>; + $('active_tab_id').tabsJsObject = jQuery('#<?php echo $tabsBlock->getId() ?>'); <?php endif; ?> //]]> </script> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/tree.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/tree.phtml index 1b79ba9e8cf158b87e56cbc9cf6c6f06c26efa4d..2bc2872bcb611a02c84c8ed742241f0d4562c3fb 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/tree.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/category/tree.phtml @@ -104,13 +104,18 @@ Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, { this.currentNodeId = parameters['category_id']; } this.selectCurrentNode(); + + // Temporary solution will be replaced after refactoring of tree functionality + jQuery('body').off('tabsactivate.tree').on('tabsactivate.tree', jQuery.proxy(function(e, ui){ + this.activeTab = jQuery(ui.newTab).find('a').prop('id'); + }, this)) }, request : function(url, params) { if (!params) { - if (category_info_tabsJsTabs.activeTab) { - var params = {active_tab_id:category_info_tabsJsTabs.activeTab.id}; + if (this.activeTab) { + var params = {active_tab_id:this.activeTab}; } else { var params = {}; @@ -180,8 +185,8 @@ Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, { setLocation(url); return; } - if (category_info_tabsJsTabs.activeTab) { - var params = {active_tab_id:category_info_tabsJsTabs.activeTab.id}; + if (this.activeTab) { + var params = {active_tab_id:this.activeTab}; } updateContent(url, params); } diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product.js b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product.js index 8c0ef79882e5749649b7783f38a6ddb32a5c05c6..d8bf8f5b82e822ce508389fbb1168d3a2b23b957 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product.js +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product.js @@ -53,10 +53,11 @@ Product.Gallery.prototype = { '(^|.|\\r|\\n)(__([a-zA-Z0-9_]+)__)', '')); this.fixParentTable(); this.updateImages(); - varienGlobalEvents.attachEventHandler('moveTab', this.onImageTabMove - .bind(this)); + jQuery('#' + this.containerId) + .closest('.ui-tabs-panel') + .on('move.tabs', jQuery.proxy(this.onImageTabMove, this)); }, - onImageTabMove : function(event) { + onImageTabMove : function(event, tab) { var imagesTab = false; this.container.ancestors().each( function(parentItem) { if (parentItem.tabObject) { @@ -65,7 +66,7 @@ Product.Gallery.prototype = { } }.bind(this)); - if (imagesTab && event.tab && event.tab.name && imagesTab.name == event.tab.name) { + if (imagesTab && tab && tab.name && imagesTab.name === tab.name) { this.container.select('input[type="radio"]').each(function(radio) { radio.observe('change', this.onChangeRadio); }.bind(this)); @@ -270,18 +271,10 @@ Product.AttributesBridge = { getAttributes : function(tabId) { return this.bindTabs2Attributes[tabId]; }, - setTabsObject : function(tabs) { - this.tabsObject = tabs; - }, - getTabsObject : function() { - return this.tabsObject; - }, addAttributeRow : function(data) { - $H(data).each( function(item) { - if (this.getTabsObject().activeTab.name != item.key) { - this.getTabsObject().showTabContent($(item.key)); - } - this.getAttributes(item.key).addRow(item.value); + $H(data).each(function(item) { + var element = this.getAttributes(item.key).addRow(item.value); + jQuery(element).trigger('focus'); }.bind(this)); } }; @@ -318,6 +311,7 @@ Product.Attributes.prototype = { window.scrollTo(0, Position.cumulativeOffset(element)[1] + element.offsetHeight); } + return element; } }; diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/change_attribute_set_widget.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/change_attribute_set_widget.phtml index ef078d80ba0a840707f49a305ca63fa494d6ab97..d573e98b62419d8d931999713e806428604b3750 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/change_attribute_set_widget.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/change_attribute_set_widget.phtml @@ -27,7 +27,6 @@ ?> <script type="text/javascript">//<[CDATA[ (function($) { - 'use strict'; $(function() { $('#product-edit-form').bind('product:changeAttributeSet', function(event, attributeSetId) { if ($('.tab-item-link.ajax.changed').length > 0 @@ -41,7 +40,6 @@ uri += 'set=' + window.encodeURIComponent(attributeSetId); $form.attr('action', uri).addClass('ignore-validate').submit(); }); - $('#attribute-set-info').dialog({ title: '<?php echo Mage::helper('Mage_Catalog_Helper_Data')->__('Select Attribute Set'); ?>', autoOpen: false, 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 0c62cf23e1cbc3511fd36fab9d4307967a66b5e8..09512e0f01c46c80954ed66a3604b43e99ce0973 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 @@ -92,17 +92,15 @@ } jQuery(function() { - var objName = '<?php echo $this->getSelectedTabId() ?>'; - if (objName) { - obj = $(objName); - //IE fix (bubbling event model) - product_info_tabsJsTabs.setSkipDisplayFirstTab(); - product_info_tabsJsTabs.showTabContent(obj); + <?php if ($this->getSelectedTabId()): ?> + if(jQuery('#<?php echo $this->getSelectedTabId() ?>').length) { + jQuery('#<?php echo $this->getSelectedTabId() ?>').trigger('click'); } - Product.AttributesBridge.setTabsObject(product_info_tabsJsTabs); - window.varienGlobalEvents.attachEventHandler('tabChangeBefore', function(data) { - jQuery('#config_super_product')[data.first ? 'show' : 'hide'](); - }); + <?php endif; ?> + jQuery(window).on('tabsbeforeactivate', function(e, ui){ + jQuery('#config_super_product')[ui.newTab.index() ? 'hide' : 'show'](); + }).triggerHandler('tabsbeforeactivate', [{newTab: jQuery('#<?php echo $this->getSelectedTabId() ?>').closest('li')}]); + (function ($) { var masks = <?php echo $this->helper('Mage_Core_Helper_Data')->jsonEncode($this->getFieldsAutogenerationMasks())?>; diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/js.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/js.phtml index 45ab1f98cf5ecc8ee0a206fb06ec95fdd41e3004..9b72f4032824b8457407a65e3a7d46f70e0959d8 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/js.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/catalog/product/js.phtml @@ -77,18 +77,25 @@ function recalculateTax() } // Bind tab changes -function bindActiveProductTab(event) { - if(event.tab && event.tab.name && $('store_switcher')){ - $('store_switcher').switchParams = 'active_tab/'+event.tab.name+'/'; +function bindActiveProductTab(event, ui) { + var anchor = jQuery(ui.newTab).find('a'); + if (anchor && anchor.name && $('store_switcher')) { + $('store_switcher').switchParams = 'active_tab/'+anchor.name+'/'; } } -varienGlobalEvents.attachEventHandler('showTab', bindActiveProductTab); +//varienGlobalEvents.attachEventHandler('showTab', bindActiveProductTab); +jQuery(document).on('tabsactivate', bindActiveProductTab); // bind active tab <?php if($tabsBlock = $this->getLayout()->getBlock('product_tabs')): ?> -if(<?php echo $tabsBlock->getJsObjectName() ?> && <?php echo $tabsBlock->getJsObjectName() ?>.activeTab && $('store_switcher')){ - $('store_switcher').switchParams = 'active_tab/'+<?php echo $tabsBlock->getJsObjectName() ?>.activeTab.name+'/'; -} +jQuery(document).ready(function(){ + if (jQuery('#<?php echo $tabsBlock->getId() ?>').length && jQuery('#<?php echo $tabsBlock->getId() ?>').is(':mage-tabs')) { + var activeAnchor = jQuery('#<?php echo $tabsBlock->getId() ?>').tabs('activeAnchor'); + if (activeAnchor && $('store_switcher')) { + $('store_switcher').switchParams = 'active_tab/' + activeAnchor.prop('name') + '/'; + } + } +}); <?php endif; ?> //]]> </script> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/css/ui-lightness/tabs.css b/app/code/core/Mage/Adminhtml/view/adminhtml/css/ui-lightness/tabs.css new file mode 100644 index 0000000000000000000000000000000000000000..80b9e5bc59285dfb7eb186fd4633640d4c424ab9 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/css/ui-lightness/tabs.css @@ -0,0 +1,109 @@ +/** + * 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 base_default + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +/* TABS +*******************************************************************************/ + +/* Vertical Tabs */ + +.ui-tabs.ui-corner-all, .tabs.ui-corner-all { + -moz-border-radius-topleft: 0px; + -webkit-border-top-left-radius: 0px; + -khtml-border-top-left-radius: 0px; + border-top-left-radius: 0px; +} + +.ui-tabs.ui-corner-all, .tabs.ui-corner-all { + -moz-border-radius-topright: 0px; + -webkit-border-top-right-radius: 0px; + -khtml-border-top-right-radius: 0px; + border-top-right-radius: 0px; +} + +.ui-tabs.ui-corner-all, .tabs.ui-corner-all { + -moz-border-radius-bottomleft: 0px; + -webkit-border-bottom-left-radius: 0px; + -khtml-border-bottom-left-radius: 0px; + border-bottom-left-radius: 0px; +} + +.ui-tabs.ui-corner-all, .tabs.ui-corner-all { + -moz-border-radius-bottomright: 0px; + -webkit-border-bottom-right-radius: 0px; + -khtml-border-bottom-right-radius: 0px; + border-bottom-right-radius: 0px; +} + +.tabs.ui-widget-header { + border: none !important; +} +.tabs li { + -moz-border-radius-topleft: 0px; + -webkit-border-top-left-radius: 0px; + -khtml-border-top-left-radius: 0px; + border-top-left-radius: 0px; + -moz-border-radius-topright: 0px; + -webkit-border-top-right-radius: 0px; + -khtml-border-top-right-radius: 0px; + border-top-right-radius: 0px; + border: none !important; +} +.ui-tabs.ui-widget-content { + border-left: none; + border-right: none; + border-bottom: none; +} +.ui-tabs { + padding: 0; +} + +.ui-tabs .ui-tabs-nav { + padding: 0; +} + +.ui-tabs .ui-tabs-nav li { + float: none; + top: 0; + margin: 0; +} + +.ui-tabs .ui-tabs-nav li a { + float: none; + padding: 0; +} + +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { + margin-bottom: 0; + padding-bottom: 0; +} + +.ui-tabs .ui-tabs-panel { + padding: 0; +} + +.ui-tabs { + border-top:1px solid #bebebe; + background-color:#e7efef; + padding: 0; +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/main.xml b/app/code/core/Mage/Adminhtml/view/adminhtml/main.xml index 7a3e785540b843ba587737c22d07b2a147906e85..2189410a47e2a163a2f56b7dc51e47124e660617 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/main.xml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/main.xml @@ -57,7 +57,7 @@ Supported layout update handles (special): <action method="setTitle" translate="title"><title>Magento Admin</title></action> <action method="addJs"><file>jquery/jquery-1.8.2.min.js</file></action> <action method="addJs"><file>mage/jquery-no-conflict.js</file></action> - <action method="addJs"><file>jquery/jquery-ui-1.9.1.custom.min.js</file></action> + <action method="addJs"><file>jquery/jquery-ui-1.9.2.custom.min.js</file></action> <action method="addJs"><file>jquery/jquery.tmpl.min.js</file></action> <action method="addJs"><file>jquery/jquery.validate.js</file></action> <action method="addJs"><file>mage/translate.js</file></action> @@ -82,9 +82,9 @@ Supported layout update handles (special): <action method="addJs"><file>mage/adminhtml/hash.js</file></action> <action method="addJs"><file>mage/adminhtml/events.js</file></action> - <action method="addJs"><file>mage/adminhtml/loader.js</file></action> + <action method="addJs"><file>mage/adminhtml/varienLoader.js</file></action> <action method="addJs"><file>mage/adminhtml/grid.js</file></action> - <action method="addJs"><file>mage/adminhtml/tabs.js</file></action> + <action method="addJs"><file>mage/backend/tabs.js</file></action> <action method="addJs"><file>mage/adminhtml/form.js</file></action> <action method="addJs"><file>mage/adminhtml/accordion.js</file></action> <action method="addJs"><file>mage/adminhtml/tools.js</file></action> @@ -110,14 +110,14 @@ Supported layout update handles (special): </block> <block type="Mage_Adminhtml_Block_Page_Notices" name="global_notices" as="global_notices" template="page/notices.phtml" /> - <block type="Mage_Adminhtml_Block_Page_Header" name="header" as="header"></block> + <block type="Mage_Adminhtml_Block_Page_Header" name="header" as="header"/> <container name="notifications" as="notifications" label="Notifications"> - <block type="Mage_Adminhtml_Block_Notification_Baseurl" name="notification_baseurl" as="notification_baseurl" template="notification/baseurl.phtml"></block> - <block type="Mage_Adminhtml_Block_Cache_Notifications" name="cache_notifications" template="system/cache/notifications.phtml"></block> + <block type="Mage_Adminhtml_Block_Notification_Baseurl" name="notification_baseurl" as="notification_baseurl" template="notification/baseurl.phtml"/> + <block type="Mage_Adminhtml_Block_Cache_Notifications" name="cache_notifications" template="system/cache/notifications.phtml"/> <block type="Mage_Adminhtml_Block_Notification_Survey" name="notification_survey" template="notification/survey.phtml"/> - <block type="Mage_Adminhtml_Block_Notification_Security" name="notification_security" as="notification_security" template="notification/security.phtml"></block> + <block type="Mage_Adminhtml_Block_Notification_Security" name="notification_security" as="notification_security" template="notification/security.phtml"/> </container> - <block type="Mage_Adminhtml_Block_Widget_Breadcrumbs" name="breadcrumbs" as="breadcrumbs"></block> + <block type="Mage_Adminhtml_Block_Widget_Breadcrumbs" name="breadcrumbs" as="breadcrumbs"/> <!--<update handle="formkey"/> this won't work, see the try/catch and a jammed exception in Mage_Core_Model_Layout::createBlock() --> <block type="Mage_Core_Block_Template" name="formkey" as="formkey" template="Mage_Adminhtml::admin/formkey.phtml"/> @@ -204,19 +204,19 @@ Supported layout update handles (special): <preview> <block type="Mage_Core_Block_Template" name="root" output="1" template="Mage_Adminhtml::newsletter/template/preview.phtml"> - <block type="Mage_Adminhtml_Block_Newsletter_Template_Preview" name="content" as="content"></block> + <block type="Mage_Adminhtml_Block_Newsletter_Template_Preview" name="content" as="content"/> </block> </preview> <newsletter_template_preview> <block type="Mage_Core_Block_Template" name="root" output="1" template="Mage_Adminhtml::newsletter/template/preview.phtml"> - <block type="Mage_Adminhtml_Block_Newsletter_Template_Preview" name="content" as="content"></block> + <block type="Mage_Adminhtml_Block_Newsletter_Template_Preview" name="content" as="content"/> </block> </newsletter_template_preview> <newsletter_queue_preview> <block type="Mage_Core_Block_Template" name="root" output="1" template="Mage_Adminhtml::newsletter/queue/preview.phtml"> - <block type="Mage_Adminhtml_Block_Newsletter_Queue_Preview" name="content" as="content"></block> + <block type="Mage_Adminhtml_Block_Newsletter_Queue_Preview" name="content" as="content"/> </block> </newsletter_queue_preview> @@ -226,7 +226,7 @@ Supported layout update handles (special): <systemPreview> <block type="Mage_Core_Block_Template" name="root" output="1" template="Mage_Adminhtml::system/email/template/preview.phtml"> - <block type="Mage_Adminhtml_Block_System_Email_Template_Preview" name="content" as="content"></block> + <block type="Mage_Adminhtml_Block_System_Email_Template_Preview" name="content" as="content"/> </block> </systemPreview> diff --git a/app/code/core/Mage/Adminhtml/view/adminhtml/widget/tabshoriz.phtml b/app/code/core/Mage/Adminhtml/view/adminhtml/widget/tabshoriz.phtml index f0b4294b4fcf967afebd4b2d124b6970673997d0..1f8b472f85c0ca6ad8cfe1f0c30ff26691cec0f8 100644 --- a/app/code/core/Mage/Adminhtml/view/adminhtml/widget/tabshoriz.phtml +++ b/app/code/core/Mage/Adminhtml/view/adminhtml/widget/tabshoriz.phtml @@ -28,18 +28,28 @@ <h3><?php echo $this->getTitle() ?></h3> <?php endif ?> --> <?php if(!empty($tabs)): ?> -<ul id="<?php echo $this->getId() ?>" class="tabs-horiz"> +<div id="<?php echo $this->getId() ?>"> +<ul class="tabs-horiz"> <?php foreach ($tabs as $_tab): ?> + <?php $_tabClass = 'tab-item-link ' . $this->getTabClass($_tab) . ' ' . (preg_match('/\s?ajax\s?/', $_tab->getClass()) ? 'notloaded' : '') ?> + <?php $_tabType = (!preg_match('/\s?ajax\s?/', $_tabClass) && $this->getTabUrl($_tab) != '#') ? 'link' : '' ?> + <?php $_tabHref = $this->getTabUrl($_tab) == '#' ? '#' . $this->getTabId($_tab) . '_content' : $this->getTabUrl($_tab) ?> <li> - <a href="<?php echo $this->getTabUrl($_tab)?>" id="<?php echo $this->getTabId($_tab) ?>" title="<?php echo $this->getTabTitle($_tab) ?>" class="tab-item-link <?php echo $this->getTabClass($_tab) ?><?php if (preg_match('/\s?ajax\s?/', $this->getTabClass($_tab))) {?> notloaded<?php }?>"> + <a href="<?php echo $_tabHref?>" id="<?php echo $this->getTabId($_tab) ?>" title="<?php echo $this->getTabTitle($_tab) ?>" class="<?php $_tabClass ?>" data-tab-type="<?php $_tabType ?>"> <span><span class="changed" title="<?php echo $this->__('The information in this tab has been changed.') ?>"></span><span class="error" title="<?php echo $this->__('This tab contains invalid data. Please solve the problem before saving.') ?>"></span><?php echo $this->getTabLabel($_tab) ?></span> </a> <div id="<?php echo $this->getTabId($_tab) ?>_content" style="display:none"><?php echo $this->getTabContent($_tab) ?></div> </li> <?php endforeach; ?> </ul> +</div> <script type="text/javascript"> - - <?php echo $this->getId() ?>JsTabs = new varienTabs('<?php echo $this->getId() ?>', '<?php echo $this->getDestElementId() ?>', '<?php echo $this->getActiveTabId() ?>', <?php echo $this->getAllShadowTabs()?>); + jQuery(function() { + jQuery('#<?php echo $this->getId() ?>').tabs({ + active: '<?php echo $this->getActiveTabId() ?>', + destination: '#<?php echo $this->getDestElementId() ?>', + shadowTabs: <?php echo $this->getAllShadowTabs()?> + }); + }); </script> <?php endif; ?> diff --git a/app/code/core/Mage/Backend/Block/Template.php b/app/code/core/Mage/Backend/Block/Template.php index 9b114fbc07531a749a551c7aa202f5587ad27c9f..c16ffc32a12b2f0a1a87e89651a8480cd9688dad 100644 --- a/app/code/core/Mage/Backend/Block/Template.php +++ b/app/code/core/Mage/Backend/Block/Template.php @@ -30,6 +30,9 @@ * @category Mage * @package Mage_Backend * @author Magento Core Team <core@magentocommerce.com> + * + * @SuppressWarnings(PHPMD.NumberOfChildren) + * @SuppressWarnings(PHPMD.numberOfChildren) */ class Mage_Backend_Block_Template extends Mage_Core_Block_Template { diff --git a/app/code/core/Mage/Backend/Controller/ActionAbstract.php b/app/code/core/Mage/Backend/Controller/ActionAbstract.php index 122fa0ed174e2bed8d35bdc01daec94daaedf4f1..ffbaa95370ce7c97daa2b9641f64ae1d8caa3278 100644 --- a/app/code/core/Mage/Backend/Controller/ActionAbstract.php +++ b/app/code/core/Mage/Backend/Controller/ActionAbstract.php @@ -54,35 +54,34 @@ abstract class Mage_Backend_Controller_ActionAbstract extends Mage_Core_Controll protected $_sessionNamespace = self::SESSION_NAMESPACE; /** - * Helper - * * @var Mage_Backend_Helper_Data */ protected $_helper; /** - * Session model - * * @var Mage_Backend_Model_Session */ protected $_session; /** - * Constructor - * - * @param Zend_Controller_Request_Abstract $request - * @param Zend_Controller_Response_Abstract $response + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Controller_Response_Http $response + * @param string $areaCode * @param Magento_ObjectManager $objectManager * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Layout_Factory $layoutFactory * @param array $invokeArgs */ - public function __construct(Zend_Controller_Request_Abstract $request, - Zend_Controller_Response_Abstract $response, + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Controller_Response_Http $response, + $areaCode = null, Magento_ObjectManager $objectManager, Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Layout_Factory $layoutFactory, array $invokeArgs = array() ) { - parent::__construct($request, $response, $objectManager, $frontController, $invokeArgs); + parent::__construct($request, $response, $areaCode, $objectManager, $frontController, $layoutFactory); $this->_helper = isset($invokeArgs['helper']) ? $invokeArgs['helper'] : diff --git a/app/code/core/Mage/Backend/Controller/Router/Default.php b/app/code/core/Mage/Backend/Controller/Router/Default.php index 43b53df357fdc6dff042dcd642c371c461a1c254..4ba7ef8eca4a82f4ab41b15e3fc401e56c5baa71 100644 --- a/app/code/core/Mage/Backend/Controller/Router/Default.php +++ b/app/code/core/Mage/Backend/Controller/Router/Default.php @@ -47,13 +47,20 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien protected $_areaFrontName; /** + * @param Mage_Core_Controller_Varien_Action_Factory $controllerFactory * @param Magento_ObjectManager $objectManager - * @param array $options + * @param string $areaCode + * @param string $baseController * @throws InvalidArgumentException */ - public function __construct(Magento_ObjectManager $objectManager, array $options = array()) - { - parent::__construct($objectManager, $options); + public function __construct( + Mage_Core_Controller_Varien_Action_Factory $controllerFactory, + Magento_ObjectManager $objectManager, + $areaCode, + $baseController + ) { + parent::__construct($controllerFactory, $objectManager, $areaCode, $baseController); + $this->_areaFrontName = Mage::helper('Mage_Backend_Helper_Data')->getAreaFrontName(); if (empty($this->_areaFrontName)) { throw new InvalidArgumentException('Area Front Name should be defined'); @@ -99,9 +106,9 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien } /** - * dummy call to pass through checking + * Dummy call to pass through checking * - * @return unknown + * @return boolean */ protected function _beforeModuleMatch() { @@ -207,7 +214,7 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien $parts = explode('_', $realModule); $realModule = implode('_', array_splice($parts, 0, 2)); $file = Mage::getModuleDir('controllers', $realModule); - return $file . DS . ucfirst($this->_area) . DS . uc_words($controller, DS) . 'Controller.php'; + return $file . DS . ucfirst($this->_areaCode) . DS . uc_words($controller, DS) . 'Controller.php'; } /** @@ -232,7 +239,7 @@ class Mage_Backend_Controller_Router_Default extends Mage_Core_Controller_Varien $parts = explode('_', $realModule); $realModule = implode('_', array_splice($parts, 0, 2)); - return $realModule . '_' . ucfirst($this->_area) . '_' . uc_words($controller) . 'Controller'; + return $realModule . '_' . ucfirst($this->_areaCode) . '_' . uc_words($controller) . 'Controller'; } /** diff --git a/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php b/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php index 707f39f5b2fef12efc6c5cc53b4285c4e7dc013b..89d590cd44630cfde72b1c3e570b5d62d76ad857 100644 --- a/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php +++ b/app/code/core/Mage/Backend/Controller/System/ConfigAbstract.php @@ -53,25 +53,34 @@ abstract class Mage_Backend_Controller_System_ConfigAbstract extends Mage_Backen protected $_authSession; /** - * @param Zend_Controller_Request_Abstract $request - * @param Zend_Controller_Response_Abstract $response + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Controller_Response_Http $response + * @param string $areaCode * @param Magento_ObjectManager $objectManager * @param Mage_Core_Controller_Varien_Front $frontController * @param Mage_Core_Model_Authorization $authorization * @param Mage_Backend_Model_Config_Structure $configStructure * @param Mage_Backend_Model_Auth_StorageInterface $authSession + * @param Mage_Core_Model_Layout_Factory $layoutFactory * @param array $invokeArgs + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ - public function __construct(Zend_Controller_Request_Abstract $request, - Zend_Controller_Response_Abstract $response, + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Controller_Response_Http $response, + $areaCode = null, Magento_ObjectManager $objectManager, Mage_Core_Controller_Varien_Front $frontController, Mage_Core_Model_Authorization $authorization, Mage_Backend_Model_Config_Structure $configStructure, Mage_Backend_Model_Auth_StorageInterface $authSession, + Mage_Core_Model_Layout_Factory $layoutFactory, array $invokeArgs = array() ) { - parent::__construct($request, $response, $objectManager, $frontController, $invokeArgs); + parent::__construct($request, $response, $areaCode, $objectManager, $frontController, $layoutFactory, + $invokeArgs + ); $this->_authorization = $authorization; $this->_configStructure = $configStructure; diff --git a/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php b/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php index 4e98bbd952c1e8304bc2e119dcd20cb84aa192ff..8033a590ed1bc35e45464f58eb7423564bdea88c 100644 --- a/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php +++ b/app/code/core/Mage/Backend/controllers/Adminhtml/System/Config/SaveController.php @@ -66,8 +66,9 @@ class Mage_Backend_Adminhtml_System_Config_SaveController extends Mage_Backend_C /** * Constructor * - * @param Zend_Controller_Request_Abstract $request - * @param Zend_Controller_Response_Abstract $response + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Controller_Response_Http $response + * @param string $areaCode * @param Magento_ObjectManager $objectManager * @param Mage_Core_Controller_Varien_Front $frontController * @param Mage_Core_Model_Authorization $authorization @@ -77,12 +78,15 @@ class Mage_Backend_Adminhtml_System_Config_SaveController extends Mage_Backend_C * @param Mage_Core_Model_Event_Manager $eventManager * @param Mage_Core_Model_App $app * @param Mage_Backend_Model_Auth_StorageInterface $authSession + * @param Mage_Core_Model_Layout_Factory $layoutFactory * @param array $invokeArgs * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ - public function __construct(Zend_Controller_Request_Abstract $request, - Zend_Controller_Response_Abstract $response, + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Controller_Response_Http $response, + $areaCode = null, Magento_ObjectManager $objectManager, Mage_Core_Controller_Varien_Front $frontController, Mage_Core_Model_Authorization $authorization, @@ -92,10 +96,11 @@ class Mage_Backend_Adminhtml_System_Config_SaveController extends Mage_Backend_C Mage_Core_Model_Event_Manager $eventManager, Mage_Core_Model_App $app, Mage_Backend_Model_Auth_StorageInterface $authSession, + Mage_Core_Model_Layout_Factory $layoutFactory, array $invokeArgs = array() ) { - parent::__construct($request, $response, $objectManager, $frontController, - $authorization, $configStructure, $authSession, $invokeArgs + parent::__construct($request, $response, $areaCode, $objectManager, $frontController, + $authorization, $configStructure, $authSession, $layoutFactory, $invokeArgs ); $this->_authorization = $authorization; diff --git a/app/code/core/Mage/Backend/view/adminhtml/admin/login.phtml b/app/code/core/Mage/Backend/view/adminhtml/admin/login.phtml index e38cc86b3d67635d77a1c9e7a67e4be8b2894afd..c39c07135936aff4fea1307f31007cb4d20f7fe3 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/admin/login.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/admin/login.phtml @@ -36,7 +36,7 @@ <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-1.8.2.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('mage/jquery-no-conflict.js') ?>"></script> - <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-ui-1.9.1.custom.min.js') ?>"></script> + <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-ui-1.9.2.custom.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery.tmpl.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery.validate.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('mage/validation.js') ?>"></script> diff --git a/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml b/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml index 9e6668669c792f97ecb6350882eb7ce8b204da3e..0164bf168b3fff1924e6bd9024a1deaf63d48378 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/system/config/js.phtml @@ -127,8 +127,12 @@ originModel.prototype = { var regionElement = $(countryElement.id.replace(/country_id/, 'region_id')); if (regionElement) { this.regionElement = regionElement; - var url = this.regionsUrl+'parent/'+countryElement.value; - this.loader.load(url, {}, this.refreshRegionField.bind(this)); + if (countryElement.value.length) { + var url = this.regionsUrl+'parent/'+countryElement.value; + this.loader.load(url, {}, this.refreshRegionField.bind(this)); + } else { + this.clearRegionField(this.regionElement.disabled); + } } } }, @@ -140,8 +144,12 @@ originModel.prototype = { var regionElement = $(countryElement.id.replace(/country_id/, 'region_id')); if (regionElement) { this.regionElement = regionElement; - var url = this.regionsUrl+'parent/'+countryElement.value; - this.loader.load(url, {}, this.refreshRegionField.bind(this)); + if (countryElement.value.length) { + var url = this.regionsUrl+'parent/'+countryElement.value; + this.loader.load(url, {}, this.refreshRegionField.bind(this)); + } else { + this.clearRegionField(this.regionElement.disabled); + } } } }, @@ -169,14 +177,16 @@ originModel.prototype = { parentNode.innerHTML = html; this.regionElement = $(regionElementId); } else if (this.reload) { - var html = '<input type="text" name="'+this.regionElement.name+'" id="'+this.regionElement.id+'" class="input-text" title="'+this.regionElement.title+'"'+(disabled?" disabled":"")+'>'; - var parentNode = this.regionElement.parentNode; - var regionElementId = this.regionElement.id; - parentNode.innerHTML = html; - this.regionElement = $(regionElementId); - //this.regionElement.replace(html); + this.clearRegionField(disabled); } } + }, + clearRegionField: function(disabled) { + var html = '<input type="text" name="' + this.regionElement.name + '" id="' + this.regionElement.id + '" class="input-text" title="' + this.regionElement.title + '"' + (disabled ? " disabled" : "") + '>'; + var parentNode = this.regionElement.parentNode; + var regionElementId = this.regionElement.id; + parentNode.innerHTML = html; + this.regionElement = $(regionElementId); } } diff --git a/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml b/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml index 4ffa372dd8a9dad416737f1a982f87cfe8db9c0a..8c27dce13f4ff300c19ebb3d9f9356185d67f354 100644 --- a/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml +++ b/app/code/core/Mage/Backend/view/adminhtml/widget/tabs.phtml @@ -24,22 +24,33 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php if ($this->getTitle()): ?> +<?php if($this->getTitle()): ?> <h3 <?php echo $this->getUiId('title') ?>><?php echo $this->getTitle() ?></h3> <?php endif ?> -<?php if (!empty($tabs)): ?> -<ul id="<?php echo $this->getId() ?>" <?php echo $this->getUiId('tab', $this->getId()) ?> class="tabs"> +<?php if(!empty($tabs)): ?> +<div id="<?php echo $this->getId() ?>"> +<ul <?php echo $this->getUiId('tab', $this->getId()) ?> class="<?php echo $this->getIsHoriz() ? 'tabs-horiz' : 'tabs' ?>"> <?php foreach ($tabs as $_tab): ?> <?php if (!$this->canShowTab($_tab)): continue; endif; ?> - <li <?php if ($this->getTabIsHidden($_tab)): ?> style="display:none"<?php endif; ?><?php echo $this->getUiId('tab', 'item', $_tab->getId()) ?>> - <a href="<?php echo $this->getTabUrl($_tab) ?>" id="<?php echo $this->getTabId($_tab) ?>" name="<?php echo $this->getTabId($_tab, false) ?>" title="<?php echo $this->getTabTitle($_tab) ?>" class="tab-item-link <?php echo $this->getTabClass($_tab) ?><?php if (preg_match('/\s?ajax\s?/', $_tab->getClass())) {?> notloaded<?php }?>"<?php echo $this->getUiId('tab', 'link', $_tab->getId()) ?>> + <?php $_tabClass = 'tab-item-link ' . $this->getTabClass($_tab) . ' ' . (preg_match('/\s?ajax\s?/', $_tab->getClass()) ? 'notloaded' : '') ?> + <?php $_tabType = (!preg_match('/\s?ajax\s?/', $_tabClass) && $this->getTabUrl($_tab) != '#') ? 'link' : '' ?> + <?php $_tabHref = $this->getTabUrl($_tab) == '#' ? '#' . $this->getTabId($_tab) . '_content' : $this->getTabUrl($_tab) ?> + <li <?php if($this->getTabIsHidden($_tab)): ?> style="display:none"<?php endif; ?><?php echo $this->getUiId('tab', 'item', $_tab->getId()) ?>> + <a href="<?php echo $_tabHref ?>" id="<?php echo $this->getTabId($_tab) ?>" name="<?php echo $this->getTabId($_tab, false) ?>" title="<?php echo $this->getTabTitle($_tab) ?>" class="<?php echo $_tabClass;?>" data-tab-type="<?php echo $_tabType;?>" <?php echo $this->getUiId('tab', 'link', $_tab->getId()) ?>> <span><span class="changed" title="<?php echo $this->__('The information in this tab has been changed.') ?>"></span><span class="error" title="<?php echo $this->__('This tab contains invalid data. Please solve the problem before saving.') ?>"></span><?php echo $this->getTabLabel($_tab); ?></span> </a> <div id="<?php echo $this->getTabId($_tab) ?>_content" style="display:none;"<?php echo $this->getUiId('tab', 'content', $_tab->getId()) ?>><?php echo $this->getTabContent($_tab) ?></div> </li> <?php endforeach; ?> </ul> +</div> <script type="text/javascript"> - var <?php echo $this->getJsObjectName() ?> = new varienTabs('<?php echo $this->getId() ?>', '<?php echo $this->getDestElementId() ?>', '<?php echo $this->getActiveTabId() ?>', <?php echo $this->getAllShadowTabs()?>); + jQuery(function() { + jQuery('#<?php echo $this->getId() ?>').tabs({ + active: '<?php echo $this->getActiveTabId() ?>', + destination: '#<?php echo $this->getDestElementId() ?>', + shadowTabs: <?php echo $this->getAllShadowTabs()?> + }); + }); </script> <?php endif; ?> diff --git a/app/code/core/Mage/Checkout/Block/Links.php b/app/code/core/Mage/Checkout/Block/Links.php index 5cb36a95de2975ea05c514e57e3a1ffe0e61e9a0..883458d891dd2939d14a0bea0806d36add222c8d 100644 --- a/app/code/core/Mage/Checkout/Block/Links.php +++ b/app/code/core/Mage/Checkout/Block/Links.php @@ -40,6 +40,7 @@ class Mage_Checkout_Block_Links extends Mage_Core_Block_Template */ public function addCartLink() { + /** @var $parentBlock Mage_Page_Block_Template_Links */ $parentBlock = $this->getParentBlock(); if ($parentBlock && Mage::helper('Mage_Core_Helper_Data')->isModuleOutputEnabled('Mage_Checkout')) { $count = $this->getSummaryQty() ? $this->getSummaryQty() @@ -69,12 +70,11 @@ class Mage_Checkout_Block_Links extends Mage_Core_Block_Template return $this; } + /** @var $parentBlock Mage_Page_Block_Template_Links */ $parentBlock = $this->getParentBlock(); if ($parentBlock && Mage::helper('Mage_Core_Helper_Data')->isModuleOutputEnabled('Mage_Checkout')) { $text = $this->__('Checkout'); - $parentBlock->addLink( - $text, 'checkout', $text, - true, array('_secure' => true), 60, null, + $parentBlock->addLink($text, 'checkout', $text, true, array('_secure' => true), 60, null, 'class="top-link-checkout"' ); } diff --git a/app/code/core/Mage/Cms/Controller/Router.php b/app/code/core/Mage/Cms/Controller/Router.php index 5d60442d391a7dadaa85e2d7a7b7f77f795b794d..0eaadafcde021cad93322288a132b7f1190dd184 100644 --- a/app/code/core/Mage/Cms/Controller/Router.php +++ b/app/code/core/Mage/Cms/Controller/Router.php @@ -35,19 +35,20 @@ class Mage_Cms_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract { /** - * Event manager - * * @var Mage_Core_Model_Event_Manager */ protected $_eventManager; /** - * Class constructor - * + * @param Mage_Core_Controller_Varien_Action_Factory $controllerFactory * @param Mage_Core_Model_Event_Manager $eventManager */ - public function __construct(Mage_Core_Model_Event_Manager $eventManager) - { + public function __construct( + Mage_Core_Controller_Varien_Action_Factory $controllerFactory, + Mage_Core_Model_Event_Manager $eventManager + ) { + parent::__construct($controllerFactory); + $this->_eventManager = $eventManager; } @@ -67,12 +68,12 @@ class Mage_Cms_Controller_Router extends Mage_Core_Controller_Varien_Router_Abst /** * Validate and Match Cms Page and modify request * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @return bool * * @SuppressWarnings(PHPMD.ExitExpression) */ - public function match(Zend_Controller_Request_Http $request) + public function match(Mage_Core_Controller_Request_Http $request) { if (!Mage::isInstalled()) { Mage::app()->getFrontController()->getResponse() @@ -98,9 +99,8 @@ class Mage_Cms_Controller_Router extends Mage_Core_Controller_Varien_Router_Abst ->setRedirect($condition->getRedirectUrl()) ->sendResponse(); $request->setDispatched(true); - return Mage::getControllerInstance('Mage_Core_Controller_Varien_Action_Redirect', - $request, - Mage::app()->getFrontController()->getResponse() + return $this->_controllerFactory->createController('Mage_Core_Controller_Varien_Action_Redirect', + array('request' => $request) ); } @@ -123,9 +123,8 @@ class Mage_Cms_Controller_Router extends Mage_Core_Controller_Varien_Router_Abst $identifier ); - return Mage::getControllerInstance('Mage_Core_Controller_Varien_Action_Forward', - $request, - Mage::app()->getFrontController()->getResponse() + return $this->_controllerFactory->createController('Mage_Core_Controller_Varien_Action_Forward', + array('request' => $request) ); } } diff --git a/app/code/core/Mage/Contacts/view/frontend/layout.xml b/app/code/core/Mage/Contacts/view/frontend/layout.xml index 7ab9309ff74a7a366aa335b41e34a617498c0155..d9aab2e831c8008cef5fdac0c147b22648b25571 100644 --- a/app/code/core/Mage/Contacts/view/frontend/layout.xml +++ b/app/code/core/Mage/Contacts/view/frontend/layout.xml @@ -28,7 +28,7 @@ <layout version="0.1.0"> <default> <reference name="footer_links"> - <action method="addLink" translate="label title" module="Mage_Contacts" ifconfig="contacts/contacts/enabled"><label>Contact Us</label><url>contacts</url><title>Contact Us</title><prepare>true</prepare></action> + <action method="addLink" translate="label title" module="Mage_Contacts" ifconfig="contacts/contacts/enabled"><label>Contact Us</label><url>contacts</url><title>Contact Us</title></action> </reference> </default> diff --git a/app/code/core/Mage/Core/Block/Abstract.php b/app/code/core/Mage/Core/Block/Abstract.php index 40754107bc3549f273a90e71f0777878dab5e93c..49b582e58fcac94673ac3563615cb6be1f01d29f 100644 --- a/app/code/core/Mage/Core/Block/Abstract.php +++ b/app/code/core/Mage/Core/Block/Abstract.php @@ -75,9 +75,7 @@ abstract class Mage_Core_Block_Abstract extends Varien_Object protected $_layout; /** - * Request object - * - * @var Zend_Controller_Request_Http + * @var Mage_Core_Controller_Request_Http */ protected $_request; @@ -152,17 +150,17 @@ abstract class Mage_Core_Block_Abstract extends Varien_Object Mage_Core_Model_Factory_Helper $helperFactory, array $data = array() ) { - $this->_request = $request; - $this->_layout = $layout; - $this->_eventManager = $eventManager; - $this->_urlBuilder = $urlBuilder; - $this->_translator = $translator; - $this->_cache = $cache; - $this->_designPackage = $designPackage; - $this->_session = $session; - $this->_storeConfig = $storeConfig; + $this->_request = $request; + $this->_layout = $layout; + $this->_eventManager = $eventManager; + $this->_urlBuilder = $urlBuilder; + $this->_translator = $translator; + $this->_cache = $cache; + $this->_designPackage = $designPackage; + $this->_session = $session; + $this->_storeConfig = $storeConfig; $this->_frontController = $frontController; - $this->_helperFactory = $helperFactory; + $this->_helperFactory = $helperFactory; parent::__construct($data); $this->_construct(); diff --git a/app/code/core/Mage/Core/Controller/Varien/Action.php b/app/code/core/Mage/Core/Controller/Varien/Action.php index 0939f54da1ee6116357addeabe242e16798d5a87..709305d603995644cee7413dd760fe91f2d9faa2 100755 --- a/app/code/core/Mage/Core/Controller/Varien/Action.php +++ b/app/code/core/Mage/Core/Controller/Varien/Action.php @@ -34,7 +34,7 @@ * @package Mage_Core * @author Magento Core Team <core@magentocommerce.com> */ -abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controller_Varien_DispatchableInterface +abstract class Mage_Core_Controller_Varien_Action extends Mage_Core_Controller_Varien_ActionAbstract { const FLAG_NO_CHECK_INSTALLATION = 'no-install-check'; const FLAG_NO_DISPATCH = 'no-dispatch'; @@ -53,16 +53,12 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle const XML_PAGE_TYPE_RENDER_INHERITED = 'global/dev/page_type/render_inherited'; /** - * Request object - * - * @var Zend_Controller_Request_Abstract + * @var Mage_Core_Controller_Request_Http */ protected $_request; /** - * Response object - * - * @var Zend_Controller_Response_Abstract + * @var Mage_Core_Controller_Response_Http */ protected $_response; @@ -138,32 +134,36 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle */ protected $_frontController = null; + /** + * @var Mage_Core_Model_Layout_Factory + */ + protected $_layoutFactory; + /** * Constructor * - * @param Zend_Controller_Request_Abstract $request - * @param Zend_Controller_Response_Abstract $response + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Controller_Response_Http $response + * @param string $areaCode * @param Magento_ObjectManager $objectManager * @param Mage_Core_Controller_Varien_Front $frontController - * @param array $invokeArgs + * @param Mage_Core_Model_Layout_Factory $layoutFactory */ public function __construct( - Zend_Controller_Request_Abstract $request, - Zend_Controller_Response_Abstract $response, + Mage_Core_Controller_Request_Http $request, + Mage_Core_Controller_Response_Http $response, + $areaCode = null, Magento_ObjectManager $objectManager, Mage_Core_Controller_Varien_Front $frontController, - array $invokeArgs = array() + Mage_Core_Model_Layout_Factory $layoutFactory ) { - $this->_request = $request; - $this->_response= $response; - $this->_objectManager = $objectManager; + parent::__construct($request, $response, $areaCode); + $this->_objectManager = $objectManager; $this->_frontController = $frontController; - + $this->_layoutFactory = $layoutFactory; $this->_frontController->setAction($this); - if (!$this->_currentArea) { - $this->_currentArea = isset($invokeArgs['areaCode']) ? $invokeArgs['areaCode'] : null; - } + $this->_construct(); } @@ -188,26 +188,6 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle return method_exists($this, $this->getActionMethodName($action)); } - /** - * Retrieve request object - * - * @return Mage_Core_Controller_Request_Http - */ - public function getRequest() - { - return $this->_request; - } - - /** - * Retrieve response object - * - * @return Mage_Core_Controller_Response_Http - */ - public function getResponse() - { - return $this->_response; - } - /** * Retrieve flag value * @@ -246,20 +226,6 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle return $this; } - /** - * Retrieve full bane of current action current controller and - * current module - * - * @param string $delimiter - * @return string - */ - public function getFullActionName($delimiter = '_') - { - return $this->getRequest()->getRequestedRouteName().$delimiter. - $this->getRequest()->getRequestedControllerName().$delimiter. - $this->getRequest()->getRequestedActionName(); - } - /** * Retrieve current layout object * @@ -267,7 +233,7 @@ abstract class Mage_Core_Controller_Varien_Action implements Mage_Core_Controlle */ public function getLayout() { - return Mage::getSingleton('Mage_Core_Model_Layout', array('area' => $this->_currentArea)); + return $this->_layoutFactory->createLayout(array('area' => $this->_currentArea)); } /** diff --git a/app/code/core/Mage/Core/Controller/Varien/Action/Factory.php b/app/code/core/Mage/Core/Controller/Varien/Action/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..c378b31a338b857e50dd451322dd16f3fd4df83b --- /dev/null +++ b/app/code/core/Mage/Core/Controller/Varien/Action/Factory.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_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Controller factory + * + * @category Mage + * @package Mage_Core + * @author Magento Core Team <core@magentocommerce.com> + */ +class Mage_Core_Controller_Varien_Action_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * @param string $controllerName + * @param array $arguments + * @return mixed + */ + public function createController($controllerName, array $arguments = array()) + { + return $this->_objectManager->create($controllerName, $arguments); + } +} diff --git a/app/code/core/Mage/Core/Controller/Varien/Action/Forward.php b/app/code/core/Mage/Core/Controller/Varien/Action/Forward.php index 7d6721104b9483b75c69629aaa1e26bcbef1f13c..89b93d7e038f0857275ef0652d82498f68df8b08 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Action/Forward.php +++ b/app/code/core/Mage/Core/Controller/Varien/Action/Forward.php @@ -24,7 +24,6 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** * Forward controller * @@ -32,13 +31,12 @@ * @package Mage_Core * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Core_Controller_Varien_Action_Forward extends Mage_Core_Controller_Varien_Action_RedirectAbstract +class Mage_Core_Controller_Varien_Action_Forward extends Mage_Core_Controller_Varien_ActionAbstract { /** * Dispatch controller action * * @param string $action action name - * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function dispatch($action) diff --git a/app/code/core/Mage/Core/Controller/Varien/Action/Redirect.php b/app/code/core/Mage/Core/Controller/Varien/Action/Redirect.php index dab1d172b232c8235f6dc64708f8702df95f40c2..556a2b03758847d7a98f9e55e1c6456ebf66f273 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Action/Redirect.php +++ b/app/code/core/Mage/Core/Controller/Varien/Action/Redirect.php @@ -24,7 +24,6 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - /** * Redirect controller * @@ -32,7 +31,7 @@ * @package Mage_Core * @author Magento Core Team <core@magentocommerce.com> */ -class Mage_Core_Controller_Varien_Action_Redirect extends Mage_Core_Controller_Varien_Action_RedirectAbstract +class Mage_Core_Controller_Varien_Action_Redirect extends Mage_Core_Controller_Varien_ActionAbstract { /** * Dispatch controller action diff --git a/app/code/core/Mage/Core/Controller/Varien/Action/RedirectAbstract.php b/app/code/core/Mage/Core/Controller/Varien/Action/RedirectAbstract.php deleted file mode 100644 index 59d1d40eec2dcb92fc4cf7caa9f0f6a08a68a148..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/Core/Controller/Varien/Action/RedirectAbstract.php +++ /dev/null @@ -1,73 +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_Core - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Abstract redirect/forward action class - * - * @category Mage - * @package Mage_Core - * @author Magento Core Team <core@magentocommerce.com> - */ -abstract class Mage_Core_Controller_Varien_Action_RedirectAbstract implements Mage_Core_Controller_Varien_DispatchableInterface -{ - /** - * Request object - * - * @var Zend_Controller_Request_Abstract - */ - protected $_request; - - /** - * Response object - * - * @var Zend_Controller_Response_Abstract - */ - protected $_response; - - /** - * Currently used area - * - * @var string - */ - protected $_currentArea; - - /** - * Constructor - * - * @param Zend_Controller_Request_Abstract $request - * @param Zend_Controller_Response_Abstract $response - * @param array $invokeArgs - */ - public function __construct(Zend_Controller_Request_Abstract $request, - Zend_Controller_Response_Abstract $response, array $invokeArgs = array() - ) { - $this->_request = $request; - $this->_response = $response; - if (false == isset($this->_currentArea)) { - $this->_currentArea = isset($invokeArgs['areaCode']) ? $invokeArgs['areaCode'] : null; - } - } -} diff --git a/app/code/core/Mage/Core/Controller/Varien/ActionAbstract.php b/app/code/core/Mage/Core/Controller/Varien/ActionAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..69c25862ca2727ffc53eeaacd6242a216a8a6827 --- /dev/null +++ b/app/code/core/Mage/Core/Controller/Varien/ActionAbstract.php @@ -0,0 +1,99 @@ +<?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_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Abstract redirect/forward action class + * + * @category Mage + * @package Mage_Core + * @author Magento Core Team <core@magentocommerce.com> + */ +abstract class Mage_Core_Controller_Varien_ActionAbstract implements Mage_Core_Controller_Varien_DispatchableInterface +{ + /** + * @var Mage_Core_Controller_Request_Http + */ + protected $_request; + + /** + * @var Mage_Core_Controller_Response_Http + */ + protected $_response; + + /** + * @var string + */ + protected $_currentArea; + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Controller_Response_Http $response + * @param string $areaCode + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Controller_Response_Http $response, + $areaCode = null + ) { + $this->_request = $request; + $this->_response = $response; + $this->_currentArea = $areaCode; + } + + /** + * Retrieve request object + * + * @return Mage_Core_Controller_Request_Http + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Retrieve response object + * + * @return Mage_Core_Controller_Response_Http + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Retrieve full bane of current action current controller and + * current module + * + * @param string $delimiter + * @return string + */ + public function getFullActionName($delimiter = '_') + { + return $this->getRequest()->getRequestedRouteName() . $delimiter . + $this->getRequest()->getRequestedControllerName() . $delimiter . + $this->getRequest()->getRequestedActionName(); + } +} diff --git a/app/code/core/Mage/Core/Controller/Varien/Front.php b/app/code/core/Mage/Core/Controller/Varien/Front.php index 7c0ea7f9b93877b554e932b469954c8261ea9de3..f295057e9c22cd4e4f8e200c2c14bd933813c080 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Front.php +++ b/app/code/core/Mage/Core/Controller/Varien/Front.php @@ -27,6 +27,21 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Core_Controller_FrontInterface { + const XML_STORE_ROUTERS_PATH = 'web/routers'; + + /** + * @var Mage_Core_Controller_Varien_Router_Factory + */ + protected $_routerFactory; + + /** + * @var Mage_Core_Model_Url_RewriteFactory + */ + protected $_rewriteFactory; + + /** + * @var array + */ protected $_defaults = array(); /** @@ -36,9 +51,16 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Co */ protected $_routers = array(); - protected $_urlCache = array(); + public function __construct( + Mage_Core_Controller_Varien_Router_Factory $routerFactory, + Mage_Core_Model_Url_RewriteFactory $rewriteFactory, + array $data = array() + ) { + parent::__construct($data); - const XML_STORE_ROUTERS_PATH = 'web/routers'; + $this->_routerFactory = $routerFactory; + $this->_rewriteFactory = $rewriteFactory; + } public function setDefault($key, $value=null) { @@ -73,7 +95,7 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Co /** * Retrieve response object * - * @return Zend_Controller_Response_Http + * @return Mage_Core_Controller_Response_Http */ public function getResponse() { @@ -138,7 +160,7 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Co continue; } if (isset($routerInfo['class'])) { - $router = Mage::getSingleton($routerInfo['class'], array('options' => $routerInfo)); + $router = $this->_routerFactory->createRouter($routerInfo['class'], $routerInfo); if (isset($routerInfo['area'])) { $router->collectRoutes($routerInfo['area'], $routerCode); } @@ -150,7 +172,7 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Co Mage::dispatchEvent('controller_front_init_routers', array('front'=>$this)); // Add default router at the last - $default = new Mage_Core_Controller_Varien_Router_Default(); + $default = $this->_routerFactory->createRouter('Mage_Core_Controller_Varien_Router_Default'); $this->addRouter('default', $default); return $this; @@ -171,32 +193,25 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Co Magento_Profiler::start('dispatch'); $request->setPathInfo()->setDispatched(false); - if (!$request->isStraight()) { - Magento_Profiler::start('db_url_rewrite'); - Mage::getModel('Mage_Core_Model_Url_Rewrite')->rewrite(); - Magento_Profiler::stop('db_url_rewrite'); - } - Magento_Profiler::start('config_url_rewrite'); - $this->rewrite(); - Magento_Profiler::stop('config_url_rewrite'); + $this->applyRewrites($request); Magento_Profiler::stop('dispatch'); Magento_Profiler::start('routers_match'); $routingCycleCounter = 0; - while (!$request->isDispatched() && $routingCycleCounter++<100) { + while (!$request->isDispatched() && $routingCycleCounter++ < 100) { + /** @var $router Mage_Core_Controller_Varien_Router_Abstract */ foreach ($this->_routers as $router) { /** @var $controllerInstance Mage_Core_Controller_Varien_Action */ $controllerInstance = $router->match($this->getRequest()); if ($controllerInstance) { - $controllerInstance->dispatch($request->getActionName()); break; } } } Magento_Profiler::stop('routers_match'); - if ($routingCycleCounter>100) { + if ($routingCycleCounter > 100) { Mage::throwException('Front controller reached 100 router match iterations'); } // This event gives possibility to launch something before sending output (allow cookie setting) @@ -208,6 +223,28 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Co return $this; } + /** + * Apply rewrites to current request + * + * @param Mage_Core_Controller_Request_Http $request + */ + public function applyRewrites(Mage_Core_Controller_Request_Http $request) + { + // URL rewrite + if (!$request->isStraight()) { + Magento_Profiler::start('db_url_rewrite'); + /** @var $urlRewrite Mage_Core_Model_Url_Rewrite */ + $urlRewrite = $this->_rewriteFactory->createFromArray(); + $urlRewrite->rewrite($request); + Magento_Profiler::stop('db_url_rewrite'); + } + + // config rewrite + Magento_Profiler::start('config_url_rewrite'); + $this->rewrite($request); + Magento_Profiler::stop('config_url_rewrite'); + } + public function getRouterByRoute($routeName) { // empty route supplied - return base url @@ -256,10 +293,15 @@ class Mage_Core_Controller_Varien_Front extends Varien_Object implements Mage_Co /** * Apply configuration rewrites to current url + * + * @param Mage_Core_Controller_Request_Http $request */ - public function rewrite() + public function rewrite(Mage_Core_Controller_Request_Http $request = null) { - $request = $this->getRequest(); + if (!$request) { + $request = $this->getRequest(); + } + $config = Mage::getConfig()->getNode('global/rewrite'); if (!$config) { return; diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Abstract.php b/app/code/core/Mage/Core/Controller/Varien/Router/Abstract.php index 4b64ec6cc0a57e5bb2c6911786f3b856e6f665ab..24037c407373531e595adb1aad6fac2e215d7df8 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Router/Abstract.php +++ b/app/code/core/Mage/Core/Controller/Varien/Router/Abstract.php @@ -34,6 +34,19 @@ abstract class Mage_Core_Controller_Varien_Router_Abstract */ protected $_front; + /** + * @var Mage_Core_Controller_Varien_Action_Factory + */ + protected $_controllerFactory; + + /** + * @param Mage_Core_Controller_Varien_Action_Factory $controllerFactory + */ + public function __construct(Mage_Core_Controller_Varien_Action_Factory $controllerFactory) + { + $this->_controllerFactory = $controllerFactory; + } + /** * Assign front controller instance * @@ -66,5 +79,5 @@ abstract class Mage_Core_Controller_Varien_Router_Abstract return $frontName; } - abstract public function match(Zend_Controller_Request_Http $request); + abstract public function match(Mage_Core_Controller_Request_Http $request); } diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Base.php b/app/code/core/Mage/Core/Controller/Varien/Router/Base.php index 89e0f1af4b541149636dd6c188961d1eb99b0a9e..9b981b03fb500f820019c4ea5357ad960be7936e 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Router/Base.php +++ b/app/code/core/Mage/Core/Controller/Varien/Router/Base.php @@ -46,14 +46,14 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie * * @var string */ - protected $_area; + protected $_areaCode; /** * Base controller that belongs to area * * @var string */ - protected $_baseController = null; + protected $_baseController; /** * @var Magento_ObjectManager @@ -61,17 +61,26 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie protected $_objectManager; /** + * @param Mage_Core_Controller_Varien_Action_Factory $controllerFactory * @param Magento_ObjectManager $objectManager - * @param array $options + * @param string $areaCode + * @param string $baseController + * @throws InvalidArgumentException */ - public function __construct(Magento_ObjectManager $objectManager, array $options = array()) - { - $this->_objectManager = $objectManager; - $this->_area = isset($options['area']) ? $options['area'] : null; - $this->_baseController = isset($options['base_controller']) ? $options['base_controller'] : null; + public function __construct( + Mage_Core_Controller_Varien_Action_Factory $controllerFactory, + Magento_ObjectManager $objectManager, + $areaCode, + $baseController + ) { + parent::__construct($controllerFactory); + + $this->_objectManager = $objectManager; + $this->_areaCode = $areaCode; + $this->_baseController = $baseController; - if (is_null($this->_area) || is_null($this->_baseController)) { - Mage::throwException("Not enough options to initialize router."); + if (is_null($this->_areaCode) || is_null($this->_baseController)) { + throw new InvalidArgumentException("Not enough options to initialize router."); } } @@ -117,9 +126,9 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie public function fetchDefault() { $this->getFront()->setDefault(array( - 'module' => 'core', + 'module' => 'core', 'controller' => 'index', - 'action' => 'index' + 'action' => 'index' )); } @@ -149,10 +158,10 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie /** * Match provided request and if matched - return corresponding controller * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @return Mage_Core_Controller_Front_Action|null */ - public function match(Zend_Controller_Request_Http $request) + public function match(Mage_Core_Controller_Request_Http $request) { //checking before even try to find out that current module //should use this router @@ -166,7 +175,7 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie return null; } - $this->_objectManager->loadAreaConfiguration($this->_area); + $this->_objectManager->loadAreaConfiguration($this->_areaCode); return $this->_matchController($request, $params); } @@ -185,10 +194,10 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie /** * Parse request URL params * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @return array */ - protected function _parseRequest(Zend_Controller_Request_Http $request) + protected function _parseRequest(Mage_Core_Controller_Request_Http $request) { $output = array(); @@ -208,11 +217,11 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie /** * Match module front name * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @param string $param * @return string|null */ - protected function _matchModuleFrontName(Zend_Controller_Request_Http $request, $param) + protected function _matchModuleFrontName(Mage_Core_Controller_Request_Http $request, $param) { // get module name if ($request->getModuleName()) { @@ -234,11 +243,11 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie /** * Match controller name * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @param string $param * @return string */ - protected function _matchControllerName(Zend_Controller_Request_Http $request, $param) + protected function _matchControllerName(Mage_Core_Controller_Request_Http $request, $param) { if ($request->getControllerName()) { $controller = $request->getControllerName(); @@ -259,11 +268,11 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie /** * Match controller name * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @param string $param * @return string */ - protected function _matchActionName(Zend_Controller_Request_Http $request, $param) + protected function _matchActionName(Mage_Core_Controller_Request_Http $request, $param) { if (empty($action)) { if ($request->getActionName()) { @@ -278,30 +287,14 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie return $action; } - /** - * Get new controller instance - * - * @param $controllerClassName - * @param Zend_Controller_Request_Http $request - * @return Mage_Core_Controller_Varien_Action - */ - protected function _getControllerInstance($controllerClassName, Zend_Controller_Request_Http $request) - { - return Mage::getControllerInstance($controllerClassName, - $request, - $this->getFront()->getResponse(), - array('areaCode' => $this->_area) - ); - } - /** * Get not found controller instance * * @param $currentModuleName - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @return Mage_Core_Controller_Varien_Action|null */ - protected function _getNotFoundControllerInstance($currentModuleName, Zend_Controller_Request_Http $request) + protected function _getNotFoundControllerInstance($currentModuleName, Mage_Core_Controller_Request_Http $request) { $controllerInstance = null; @@ -319,7 +312,9 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie } // instantiate controller class - $controllerInstance = $this->_getControllerInstance($controllerClassName, $request); + $controllerInstance = $this->_controllerFactory->createController($controllerClassName, + array('request' => $request, 'areaCode' => $this->_areaCode) + ); } else { return null; } @@ -342,11 +337,11 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie /** * Create matched controller instance * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @param array $params * @return Mage_Core_Controller_Front_Action|null */ - protected function _matchController(Zend_Controller_Request_Http $request, array $params) + protected function _matchController(Mage_Core_Controller_Request_Http $request, array $params) { $this->fetchDefault(); @@ -399,9 +394,11 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie continue; } - Mage::getConfig()->setCurrentAreaCode($this->_area); + Mage::getConfig()->setCurrentAreaCode($this->_areaCode); // instantiate controller class - $controllerInstance = $this->_getControllerInstance($controllerClassName, $request); + $controllerInstance = $this->_controllerFactory->createController($controllerClassName, + array('request' => $request, 'areaCode' => $this->_areaCode) + ); $found = true; break; @@ -602,11 +599,11 @@ class Mage_Core_Controller_Varien_Router_Base extends Mage_Core_Controller_Varie * Check that request uses https protocol if it should. * Function redirects user to correct URL if needed. * - * @param Mage_Core_Controller_Request_Http $request + * @param Zend_Controller_Request_Http $request * @param string $path * @return void */ - protected function _checkShouldBeSecure($request, $path = '') + protected function _checkShouldBeSecure(Zend_Controller_Request_Http $request, $path = '') { if (!Mage::isInstalled() || $request->getPost()) { return; diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Default.php b/app/code/core/Mage/Core/Controller/Varien/Router/Default.php index c603647f22004ded4d1d1cd5185417e019e5ddf1..6410f2b06c694ca4e289921b5d84565d26079cba 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Router/Default.php +++ b/app/code/core/Mage/Core/Controller/Varien/Router/Default.php @@ -31,10 +31,10 @@ class Mage_Core_Controller_Varien_Router_Default extends Mage_Core_Controller_Va * If store is admin and specified different admin front name, * change store to default (Possible when enabled Store Code in URL) * - * @param Zend_Controller_Request_Http $request + * @param Mage_Core_Controller_Request_Http $request * @return boolean */ - public function match(Zend_Controller_Request_Http $request) + public function match(Mage_Core_Controller_Request_Http $request) { $noRoute = explode('/', Mage::app()->getStore()->getConfig('web/default/no_route')); $moduleName = isset($noRoute[0]) ? $noRoute[0] : 'core'; @@ -55,9 +55,8 @@ class Mage_Core_Controller_Varien_Router_Default extends Mage_Core_Controller_Va ->setControllerName($controllerName) ->setActionName($actionName); - return Mage::getControllerInstance('Mage_Core_Controller_Varien_Action_Forward', - $request, - $this->getFront()->getResponse() + return $this->_controllerFactory->createController('Mage_Core_Controller_Varien_Action_Forward', + array('request' => $request) ); } } diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Factory.php b/app/code/core/Mage/Core/Controller/Varien/Router/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..a60bb5c30037dabf8e3d808bc1a1b11d20982084 --- /dev/null +++ b/app/code/core/Mage/Core/Controller/Varien/Router/Factory.php @@ -0,0 +1,62 @@ +<?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_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Core_Controller_Varien_Router_Factory +{ + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * @param string $className + * @param array $routerInfo + * @return Mage_Core_Controller_Varien_Router_Abstract + */ + public function createRouter($className, array $routerInfo = array()) + { + $arguments = array( + 'areaCode' => null, + 'baseController' => null, + ); + if (isset($routerInfo['area'])) { + $arguments['areaCode'] = $routerInfo['area']; + } + if (isset($routerInfo['base_controller'])) { + $arguments['baseController'] = $routerInfo['base_controller']; + } + + return $this->_objectManager->get($className, $arguments); + } +} diff --git a/app/code/core/Mage/Core/Model/App.php b/app/code/core/Mage/Core/Model/App.php index be2b550268d3fbeb26577f45c209c6145126189a..73e2e6ec76cdbfa6c6fb155cda6dbdf419a6d843 100644 --- a/app/code/core/Mage/Core/Model/App.php +++ b/app/code/core/Mage/Core/Model/App.php @@ -35,7 +35,6 @@ */ class Mage_Core_Model_App { - const XML_PATH_INSTALL_DATE = 'global/install/date'; const XML_PATH_SKIP_PROCESS_MODULES_UPDATES = 'global/skip_process_modules_updates'; @@ -67,7 +66,7 @@ class Mage_Core_Model_App * Default store code (for install) * */ - const DISTRO_STORE_CODE = 'default'; + const DISTRO_STORE_CODE = Mage_Core_Model_Store::DEFAULT_CODE; /** * Admin store Id @@ -117,13 +116,6 @@ class Mage_Core_Model_App */ protected $_design; - /** - * Application layout object - * - * @var Mage_Core_Model_Layout - */ - protected $_layout; - /** * Application configuration object * @@ -260,8 +252,11 @@ class Mage_Core_Model_App /** * Constructor */ - public function __construct(Magento_ObjectManager $objectManager) - { + public function __construct( + Mage_Core_Controller_Varien_Front $frontController, + Magento_ObjectManager $objectManager + ) { + $this->_frontController = $frontController; $this->_objectManager = $objectManager; } @@ -1123,14 +1118,7 @@ class Mage_Core_Model_App */ public function getLayout() { - if (!$this->_layout) { - if ($this->getFrontController()->getAction()) { - $this->_layout = $this->getFrontController()->getAction()->getLayout(); - } else { - $this->_layout = Mage::getSingleton('Mage_Core_Model_Layout'); - } - } - return $this->_layout; + return $this->_objectManager->get('Mage_Core_Model_Layout'); } /** diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index e8e3a6874ec73749fb127ef274fbf9b81472785c..eaa35a68cfe252ce7508f913beb50dd3637beed2 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -23,9 +23,30 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + + +/** + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.ExcessivePublicCount) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base { - const CACHE_TAG = 'CONFIG'; + /** + * Configuration cache tag + */ + const CACHE_TAG = 'CONFIG'; + + /** + * Stores configuration scope + */ + const SCOPE_STORES = 'stores'; + + /** + * Websites configuration scope + */ + const SCOPE_WEBSITES = 'websites'; /** * Flag which allow use cache logic @@ -39,7 +60,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * array( * $sectionName => $recursionLevel * ) - * Recursion level provide availability cache subnodes separatly + * Recursion level provide availability cache sub nodes separately * * @var array */ @@ -48,8 +69,8 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base 'adminhtml' => 0, 'crontab' => 0, 'install' => 0, - 'stores' => 1, - 'websites' => 0 + self::SCOPE_STORES => 1, + self::SCOPE_WEBSITES => 0 ); /** @@ -76,7 +97,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Storage for generated block class names * - * @var unknown_type + * @var array */ protected $_blockClassNameCache = array(); @@ -109,6 +130,13 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base */ protected $_resourceModel; + /** + * Configuration data model + * + * @var Mage_Core_Model_Config_Data + */ + protected $_configDataModel; + /** * Configuration for events by area * @@ -138,7 +166,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base protected $_cachePartsForSave = array(); /** - * Empty configuration object for loading and megring configuration parts + * Empty configuration object for loading and merging configuration parts * * @var Mage_Core_Model_Config_Base */ @@ -153,6 +181,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Active modules array per namespace + * * @var array */ private $_moduleNamespaces = null; @@ -179,7 +208,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base */ protected $_moduleDirs = array(); - /* + /** * Cache for declared modules to prevent loading modules' config twice * * @var array @@ -206,7 +235,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param Magento_ObjectManager $objectManager * @param mixed $sourceData */ - public function __construct(Magento_ObjectManager $objectManager, $sourceData=null) + public function __construct(Magento_ObjectManager $objectManager, $sourceData = null) { $this->_objectManager = $objectManager; $this->setCacheId('config_global'); @@ -233,6 +262,19 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base return $this->_resourceModel; } + /** + * Get configuration data model + * + * @return Mage_Core_Model_Config_Data + */ + public function getConfigDataModel() + { + if ($this->_configDataModel === null) { + $this->_configDataModel = Mage::getModel('Mage_Core_Model_Config_Data'); + } + return $this->_configDataModel; + } + /** * Get configuration options object * @@ -260,9 +302,10 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Initialization of core configuration * + * @param array $options * @return Mage_Core_Model_Config */ - public function init($options=array()) + public function init($options = array()) { $this->setCacheChecksum(null); $this->_cacheLoadedSections = array(); @@ -459,7 +502,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base */ protected function _getCacheLockId() { - return $this->getCacheId().'.lock'; + return $this->getCacheId() . '.lock'; } /** @@ -509,16 +552,17 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param string $sectionName * @param Varien_Simplexml_Element $source * @param int $recursionLevel + * @param array $tags * @return Mage_Core_Model_Config */ - protected function _saveSectionCache($idPrefix, $sectionName, $source, $recursionLevel=0, $tags=array()) + protected function _saveSectionCache($idPrefix, $sectionName, $source, $recursionLevel = 0, $tags = array()) { if ($source && $source->$sectionName) { $cacheId = $idPrefix . '_' . $sectionName; if ($recursionLevel > 0) { - foreach ($source->$sectionName->children() as $subSectionName => $node) { + foreach (array_keys((array)$source->$sectionName->children()) as $subSectionName) { $this->_saveSectionCache( - $cacheId, $subSectionName, $source->$sectionName, $recursionLevel-1, $tags + $cacheId, $subSectionName, $source->$sectionName, $recursionLevel - 1, $tags ); } } @@ -554,37 +598,37 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Load cached data by identifier * - * @param string $id + * @param string $cacheId * @return string */ - protected function _loadCache($id) + protected function _loadCache($cacheId) { - return Mage::app()->loadCache($id); + return Mage::app()->loadCache($cacheId); } /** * Save cache data * * @param string $data - * @param string $id + * @param string $cacheId * @param array $tags - * @param false|int $lifetime + * @param bool|int $lifetime * @return Mage_Core_Model_Config */ - protected function _saveCache($data, $id, $tags=array(), $lifetime=false) + protected function _saveCache($data, $cacheId, $tags = array(), $lifetime = false) { - return Mage::app()->saveCache($data, $id, $tags, $lifetime); + return Mage::app()->saveCache($data, $cacheId, $tags, $lifetime); } /** * Clear cache data by id * - * @param string $id + * @param string $cacheId * @return Mage_Core_Model_Config */ - protected function _removeCache($id) + protected function _removeCache($cacheId) { - return Mage::app()->removeCache($id); + return Mage::app()->removeCache($cacheId); } /** @@ -660,23 +704,9 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param string|int $scopeCode * @return Mage_Core_Model_Config_Element */ - public function getNode($path=null, $scope='', $scopeCode=null) + public function getNode($path = null, $scope = '', $scopeCode = null) { - if ($scope !== '') { - if (('store' === $scope) || ('website' === $scope)) { - $scope .= 's'; - } - if (('default' !== $scope) && is_int($scopeCode)) { - if ('stores' == $scope) { - $scopeCode = Mage::app()->getStore($scopeCode)->getCode(); - } elseif ('websites' == $scope) { - $scopeCode = Mage::app()->getWebsite($scopeCode)->getCode(); - } else { - Mage::throwException(Mage::helper('Mage_Core_Helper_Data')->__('Unknown scope "%s".', $scope)); - } - } - $path = $scope . ($scopeCode ? '/' . $scopeCode : '' ) . (empty($path) ? '' : '/' . $path); - } + $path = $this->_getPathInScope($path, $scope, $scopeCode); /** * Check path cache loading @@ -694,6 +724,49 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base return parent::getNode($path); } + /** + * Get path for scope + * + * @SuppressWarnings(PHPMD.NPathComplexity) + * @param null $path + * @param string $scope + * @param string|int $scopeCode + * @return null|string + */ + protected function _getPathInScope($path = null, $scope, $scopeCode) + { + if ($scope !== '') { + if (('store' === $scope) || ('website' === $scope)) { + $scope .= 's'; + } + if ((Mage_Core_Model_Store::DEFAULT_CODE !== $scope) && is_int($scopeCode)) { + $scopeCode = $this->_getScopeCode($scope, $scopeCode); + } + $path = $scope . ($scopeCode ? '/' . $scopeCode : '') . (empty($path) ? '' : '/' . $path); + } + return $path; + } + + /** + * Get scope code by id + * + * @param string $scope + * @param int $scopeId + * @return string + */ + protected function _getScopeCode($scope, $scopeId) + { + $scopeCode = ''; + if (self::SCOPE_STORES == $scope) { + $scopeCode = Mage::app()->getStore($scopeId)->getCode(); + } elseif (self::SCOPE_WEBSITES == $scope) { + $scopeCode = Mage::app()->getWebsite($scopeId)->getCode(); + } else { + Mage::throwException(Mage::helper('Mage_Core_Helper_Data')->__('Unknown scope "%s".', $scope)); + } + return $scopeCode; + } + /** * Create node by $path and set its value. * @@ -718,7 +791,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** - * Retrive Declared Module file list + * Retrieve declared module file list * * @return array */ @@ -765,7 +838,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Add module(s) to allowed list * - * @param strung|array $module + * @param string|array $module * @return Mage_Core_Model_Config */ public function addAllowedModules($module) @@ -849,16 +922,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base */ public function determineOmittedNamespace($name, $asFullModuleName = false) { - if (null === $this->_moduleNamespaces) { - $this->_moduleNamespaces = array(); - foreach ($this->_xml->xpath('modules/*') as $m) { - if ((string)$m->active == 'true') { - $moduleName = $m->getName(); - $module = strtolower($moduleName); - $this->_moduleNamespaces[substr($module, 0, strpos($module, '_'))][$module] = $moduleName; - } - } - } + $this->_initModulesPreNamespaces(); $name = explode('_', strtolower($name)); $partsNum = count($name); @@ -873,7 +937,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base } } // assume namespace is qualified - if(isset($name[1])) { + if (isset($name[1])) { $fullNS = $name[0] . '_' . $name[1]; if (2 <= $partsNum && isset($namespace[$fullNS])) { return $asFullModuleName ? $namespace[$fullNS] : $fullNS; @@ -883,42 +947,64 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base return ''; } + /** + * Init modules per namespaces + * + * @return Mage_Core_Model_Config + */ + protected function _initModulesPreNamespaces() + { + if (null === $this->_moduleNamespaces) { + $this->_moduleNamespaces = array(); + foreach ($this->_xml->xpath('modules/*') as $moduleNode) { + if ((string)$moduleNode->active == 'true') { + $moduleName = $moduleNode->getName(); + $module = strtolower($moduleName); + $this->_moduleNamespaces[substr($module, 0, strpos($module, '_'))][$module] = $moduleName; + } + } + } + return $this; + } + /** * Iterate all active modules "etc" folders and combine data from - * specidied xml file name to one object + * specified xml file name to one object * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) * @param string $fileName * @param null|Mage_Core_Model_Config_Base $mergeToObject + * @param null|Mage_Core_Model_Config_Base $mergeModel * @return Mage_Core_Model_Config_Base */ - public function loadModulesConfiguration($fileName, $mergeToObject = null, $mergeModel=null) + public function loadModulesConfiguration($fileName, $mergeToObject = null, $mergeModel = null) { if ($mergeToObject === null) { $mergeToObject = clone $this->_prototype; $mergeToObject->loadString('<config/>'); } - if ($mergeModel === null) { - $mergeModel = clone $this->_prototype; - } + + $mergeModel = $mergeModel === null ? clone $this->_prototype : $mergeModel; + $modules = $this->getNode('modules')->children(); - foreach ($modules as $modName=>$module) { - if ($module->is('active')) { - if (!is_array($fileName)) { - $fileName = array($fileName); - } - foreach ($fileName as $configFile) { - if ($configFile == 'config.xml' && isset($this->_modulesCache[$modName])) { - $mergeToObject->extend($this->_modulesCache[$modName], true); - //Prevent overriding <active> node of module if it was redefined in etc/modules - $mergeToObject->extend(new Mage_Core_Model_Config_Base( - "<config><modules><{$modName}><active>true</active></{$modName}></modules></config>"), - true - ); - } else { - $configFilePath = $this->getModuleDir('etc', $modName) . DS . $configFile; - if ($mergeModel->loadFile($configFilePath)) { - $mergeToObject->extend($mergeModel, true); - } + foreach ($modules as $modName => $module) { + if (!$module->is('active')) { + continue; + } + if (!is_array($fileName)) { + $fileName = array($fileName); + } + foreach ($fileName as $configFile) { + if ($configFile == 'config.xml' && isset($this->_modulesCache[$modName])) { + $mergeToObject->extend($this->_modulesCache[$modName], true); + //Prevent overriding <active> node of module if it was redefined in etc/modules + $mergeToObject->extend(new Mage_Core_Model_Config_Base( + "<config><modules><{$modName}><active>true</active></{$modName}></modules></config>"), true); + } else { + $configFilePath = $this->getModuleDir('etc', $modName) . DS . $configFile; + if ($mergeModel->loadFile($configFilePath)) { + $mergeToObject->extend($mergeModel, true); } } } @@ -961,6 +1047,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Get default server variables values * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @return array */ public function getDistroServerVars() @@ -969,17 +1056,18 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base if (isset($_SERVER['SCRIPT_NAME']) && isset($_SERVER['HTTP_HOST'])) { $secure = (!empty($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] != 'off')) - || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443'); + || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443'); $scheme = ($secure ? 'https' : 'http') . '://' ; $hostArr = explode(':', $_SERVER['HTTP_HOST']); $host = $hostArr[0]; - $port = isset( - $hostArr[1]) && (!$secure && $hostArr[1]!=80 || $secure && $hostArr[1]!=443 - ) ? ':'.$hostArr[1] : ''; + $port = ''; + if (isset($hostArr[1]) && (!$secure && $hostArr[1] != 80 || $secure && $hostArr[1] != 443)) { + $port = ':' . $hostArr[1]; + } $path = Mage::app()->getRequest()->getBasePath(); - $baseUrl = $scheme.$host.$port.rtrim($path, '/').'/'; + $baseUrl = $scheme . $host . $port . rtrim($path, '/') . '/'; } else { $baseUrl = 'http://localhost/'; } @@ -992,13 +1080,19 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base 'base_url' => $baseUrl, ); - foreach ($this->_distroServerVars as $k=>$v) { - $this->_substServerVars['{{'.$k.'}}'] = $v; + foreach ($this->_distroServerVars as $k => $v) { + $this->_substServerVars['{{' . $k . '}}'] = $v; } } return $this->_distroServerVars; } + /** + * Replace distro vars with values + * + * @param array $data + * @return string|array + */ public function substDistroServerVars($data) { $this->getDistroServerVars(); @@ -1015,10 +1109,10 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param string $moduleName * @return Varien_Simplexml_Object */ - function getModuleConfig($moduleName='') + public function getModuleConfig($moduleName = '') { $modules = $this->getNode('modules'); - if (''===$moduleName) { + if ('' === $moduleName) { return $modules; } else { return $modules->$moduleName; @@ -1033,10 +1127,10 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param string|Varien_Simplexml_Object $module * @return object */ - function getModuleSetup($module='') + public function getModuleSetup($module = '') { $className = 'Mage_Core_Setup'; - if (''!==$module) { + if ('' !== $module) { if (is_string($module)) { $module = $this->getModuleConfig($module); } @@ -1057,15 +1151,21 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param string $type * @return string */ - public function getVarDir($path=null, $type='var') + public function getVarDir($path = null, $type = 'var') { - $dir = Mage::getBaseDir($type).($path!==null ? DS.$path : ''); + $dir = Mage::getBaseDir($type) . ($path !== null ? DS . $path : ''); if (!$this->createDirIfNotExists($dir)) { return false; } return $dir; } + /** + * Create dir if not exists + * + * @param string $dir + * @return bool + */ public function createDirIfNotExists($dir) { return $this->getOptions()->createDirIfNotExists($dir); @@ -1158,7 +1258,9 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base } $args = (array)$observer->args; + // @codingStandardsIgnoreStart $observerClass = $observer->observer_class ? (string)$observer->observer_class : ''; + // @codingStandardsIgnoreEnd Mage::addObserver($eventName, $callback, $args, $observer->getName(), $observerClass); } } @@ -1170,10 +1272,9 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * * To be used in blocks, templates, etc. * - * @param array|string $args Module name if string * @return array */ - public function getPathVars($args=null) + public function getPathVars() { $path = array(); @@ -1247,7 +1348,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param array|object $constructArguments * @return Mage_Core_Model_Abstract|false */ - public function getModelInstance($modelClass='', $constructArguments=array()) + public function getModelInstance($modelClass = '', $constructArguments = array()) { $className = $this->getModelClassName($modelClass); if (class_exists($className)) { @@ -1267,7 +1368,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param array $constructArguments * @return object */ - public function getResourceModelInstance($modelClass='', $constructArguments=array()) + public function getResourceModelInstance($modelClass = '', $constructArguments = array()) { return $this->getModelInstance($modelClass, $constructArguments); } @@ -1321,10 +1422,11 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * * if empty $allowValues then retrieve all stores values * - * return array($storeId=>$pathValue) + * return array($storeId => $pathValue) * * @param string $path * @param array $allowValues + * @param string $useAsKey * @return array */ public function getStoresConfigByPath($path, $allowValues = array(), $useAsKey = 'id') @@ -1336,13 +1438,14 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base case 'id': $key = (int) $store->descend('system/store/id'); break; - case 'code': $key = $code; break; - case 'name': $key = (string) $store->descend('system/store/name'); + break; + default: + break; } if ($key === false) { continue; @@ -1405,7 +1508,6 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base */ public function getEventConfig($area, $eventName) { - //return $this->getNode($area)->events->{$eventName}; if (!isset($this->_eventAreas[$area])) { $this->_eventAreas[$area] = $this->getNode($area)->events; } @@ -1421,7 +1523,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param int $scopeId * @return Mage_Core_Store_Config */ - public function saveConfig($path, $value, $scope = 'default', $scopeId = 0) + public function saveConfig($path, $value, $scope = Mage_Core_Model_Store::DEFAULT_CODE, $scopeId = 0) { $resource = $this->getResourceModel(); $resource->saveConfig(rtrim($path, '/'), $value, $scope, $scopeId); @@ -1437,7 +1539,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * @param int $scopeId * @return Mage_Core_Model_Config */ - public function deleteConfig($path, $scope = 'default', $scopeId = 0) + public function deleteConfig($path, $scope = Mage_Core_Model_Store::DEFAULT_CODE, $scopeId = 0) { $resource = $this->getResourceModel(); $resource->deleteConfig(rtrim($path, '/'), $scope, $scopeId); @@ -1487,7 +1589,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * Get a resource model class name * * @param string $modelClass - * @return string|false + * @return string|bool */ public function getResourceModelClassName($modelClass) { @@ -1513,6 +1615,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base * * @param string|null $areaCode * @return array + * @throws InvalidArgumentException */ public function getAreaConfig($areaCode = null) { @@ -1527,6 +1630,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Load allowed areas from config * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @return Mage_Core_Model_Config */ protected function _loadAreas() @@ -1580,6 +1684,12 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base return $routers; } + /** + * Is module enabled + * + * @param string $moduleName + * @return bool + */ public function isModuleEnabled($moduleName) { if (!$this->getNode('modules/' . $moduleName)) { diff --git a/app/code/core/Mage/Core/Model/Design/Package.php b/app/code/core/Mage/Core/Model/Design/Package.php index 75a6c0d14a3e30a6e2dc29cdc213db715329cd3c..1862eb298cee88225b5738a7e426ba8e9d21e2eb 100644 --- a/app/code/core/Mage/Core/Model/Design/Package.php +++ b/app/code/core/Mage/Core/Model/Design/Package.php @@ -61,11 +61,6 @@ class Mage_Core_Model_Design_Package const CONTENT_TYPE_XML = 'xml'; /**#@-*/ - /** - * The name of the default theme in the context of a package - */ - const DEFAULT_THEME_NAME = 'default'; - /** * Published file cache storage tag */ diff --git a/app/code/core/Mage/Core/Model/Email/Template/Filter.php b/app/code/core/Mage/Core/Model/Email/Template/Filter.php index acc9379981b533eddedbb0c027e4cd388d40f5fc..bf297e5bff453308af1362f3cf452482bd07501a 100644 --- a/app/code/core/Mage/Core/Model/Email/Template/Filter.php +++ b/app/code/core/Mage/Core/Model/Email/Template/Filter.php @@ -209,7 +209,7 @@ class Mage_Core_Model_Email_Template_Filter extends Varien_Filter_Template $layout->generateXml(); $layout->generateElements(); - foreach ($layout->getAllBlocks() as $blockName => $block) { + foreach ($layout->getAllBlocks() as $block) { /* @var $block Mage_Core_Block_Abstract */ foreach ($params as $k => $v) { if (in_array($k, $skipParams)) { diff --git a/app/code/core/Mage/Core/Model/Event/Manager.php b/app/code/core/Mage/Core/Model/Event/Manager.php index 18aaecd685f99cac8956580766161b65c0ccfd18..bda7b0340d1557d9a3a1669747a77eeb0a4803b1 100644 --- a/app/code/core/Mage/Core/Model/Event/Manager.php +++ b/app/code/core/Mage/Core/Model/Event/Manager.php @@ -36,7 +36,7 @@ class Mage_Core_Model_Event_Manager * @param array $params * @return Mage_Core_Model_App */ - public function dispatch($eventName, $params) + public function dispatch($eventName, array $params = array()) { return Mage::dispatchEvent($eventName, $params); } diff --git a/app/code/core/Mage/Core/Model/Layout.php b/app/code/core/Mage/Core/Model/Layout.php index db1a8eab2aacd2cba4e58bb59a8b6e1523622b94..d283d7adaa7889febdafe93e5b39b505eed8b5b8 100644 --- a/app/code/core/Mage/Core/Model/Layout.php +++ b/app/code/core/Mage/Core/Model/Layout.php @@ -1201,7 +1201,7 @@ class Mage_Core_Model_Layout extends Varien_Simplexml_Config * Save block in blocks registry * * @param string $name - * @param Mage_Core_Block_abstract $block + * @param Mage_Core_Block_Abstract $block * @return Mage_Core_Model_Layout */ public function setBlock($name, $block) @@ -1334,7 +1334,7 @@ class Mage_Core_Model_Layout extends Varien_Simplexml_Config * @param array $attributes * @return Mage_Core_Block_Abstract */ - protected function _getBlockInstance($block, array $attributes=array()) + protected function _getBlockInstance($block, array $attributes = array()) { if ($block && is_string($block)) { $block = Mage::getConfig()->getBlockClassName($block); diff --git a/app/code/core/Mage/Core/Model/Layout/Factory.php b/app/code/core/Mage/Core/Model/Layout/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..1138fab5523b7a249778270407dedba421828a36 --- /dev/null +++ b/app/code/core/Mage/Core/Model/Layout/Factory.php @@ -0,0 +1,76 @@ +<?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_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Core_Model_Layout_Factory +{ + /** + * Default layout class name + */ + const CLASS_NAME = 'Mage_Core_Model_Layout'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * @param array $arguments + * @param string $className + * @return Mage_Core_Model_Layout + */ + public function createLayout(array $arguments = array(), $className = self::CLASS_NAME) + { + // because layout singleton was used everywhere in magento code, in observers, models, blocks, etc. + // the only way how we can replace default layout object with custom one is to save instance of custom layout + // to instance manager storage using default layout class name as alias + $createLayout = true; + if (isset($arguments['area'])) { + if ($this->_objectManager->hasSharedInstance(self::CLASS_NAME)) { + /** @var $layout Mage_Core_Model_Layout */ + $layout = $this->_objectManager->get(self::CLASS_NAME); + if ($arguments['area'] != $layout->getArea()) { + $this->_objectManager->removeSharedInstance(self::CLASS_NAME); + } else { + $createLayout = false; + } + } + } + if ($createLayout) { + $layout = $this->_objectManager->create($className, $arguments, false); + $this->_objectManager->addSharedInstance($layout, self::CLASS_NAME); + } + + return $this->_objectManager->get(self::CLASS_NAME); + } +} diff --git a/app/code/core/Mage/Core/Model/Resource/Config.php b/app/code/core/Mage/Core/Model/Resource/Config.php index 4000db0ebca193316abbf35800c22203c647eb94..917b5829f7f5c62ddb2e9a4c122cfb7a337f180e 100644 --- a/app/code/core/Mage/Core/Model/Resource/Config.php +++ b/app/code/core/Mage/Core/Model/Resource/Config.php @@ -62,8 +62,8 @@ class Mage_Core_Model_Resource_Config extends Mage_Core_Model_Resource_Db_Abstra ->from($this->getTable('core_website'), array('website_id', 'code', 'name')); $rowset = $read->fetchAssoc($select); foreach ($rowset as $w) { - $xmlConfig->setNode('websites/'.$w['code'].'/system/website/id', $w['website_id']); - $xmlConfig->setNode('websites/'.$w['code'].'/system/website/name', $w['name']); + $xmlConfig->setNode('websites/' . $w['code'] . '/system/website/id', $w['website_id']); + $xmlConfig->setNode('websites/' . $w['code'] . '/system/website/name', $w['name']); $websites[$w['website_id']] = array('code' => $w['code']); } @@ -76,12 +76,15 @@ class Mage_Core_Model_Resource_Config extends Mage_Core_Model_Resource_Db_Abstra if (!isset($websites[$s['website_id']])) { continue; } - $xmlConfig->setNode('stores/'.$s['code'].'/system/store/id', $s['store_id']); - $xmlConfig->setNode('stores/'.$s['code'].'/system/store/name', $s['name']); - $xmlConfig->setNode('stores/'.$s['code'].'/system/website/id', $s['website_id']); - $xmlConfig->setNode('websites/'.$websites[$s['website_id']]['code'].'/system/stores/'.$s['code'], $s['store_id']); + $xmlConfig->setNode('stores/' . $s['code'] . '/system/store/id', $s['store_id']); + $xmlConfig->setNode('stores/' . $s['code'] . '/system/store/name', $s['name']); + $xmlConfig->setNode('stores/' . $s['code'] . '/system/website/id', $s['website_id']); + $xmlConfig->setNode( + 'websites/' . $websites[$s['website_id']]['code'] . '/system/stores/' . $s['code'], + $s['store_id'] + ); $stores[$s['store_id']] = array('code'=>$s['code']); - $websites[$s['website_id']]['stores'][$s['store_id']] = $s['code']; + $websites[$s['website_id']][Mage_Core_Model_Config::SCOPE_STORES][$s['store_id']] = $s['code']; } $substFrom = array(); @@ -98,7 +101,7 @@ class Mage_Core_Model_Resource_Config extends Mage_Core_Model_Resource_Db_Abstra // set default config values from database foreach ($rowset as $r) { - if ($r['scope'] !== 'default') { + if ($r['scope'] !== Mage_Core_Model_Store::DEFAULT_CODE) { continue; } $value = str_replace($substFrom, $substTo, $r['value']); @@ -115,7 +118,7 @@ class Mage_Core_Model_Resource_Config extends Mage_Core_Model_Resource_Db_Abstra $deleteWebsites = array(); // set websites config values from database foreach ($rowset as $r) { - if ($r['scope'] !== 'websites') { + if ($r['scope'] !== Mage_Core_Model_Config::SCOPE_WEBSITES) { continue; } $value = str_replace($substFrom, $substTo, $r['value']); @@ -130,9 +133,9 @@ class Mage_Core_Model_Resource_Config extends Mage_Core_Model_Resource_Db_Abstra // extend website config values to all associated stores foreach ($websites as $website) { $extendSource = $xmlConfig->getNode('websites/' . $website['code']); - if (isset($website['stores'])) { - foreach ($website['stores'] as $sCode) { - $storeNode = $xmlConfig->getNode('stores/'.$sCode); + if (isset($website[Mage_Core_Model_Config::SCOPE_STORES])) { + foreach ($website[Mage_Core_Model_Config::SCOPE_STORES] as $sCode) { + $storeNode = $xmlConfig->getNode('stores/' . $sCode); /** * $extendSource DO NOT need overwrite source */ @@ -144,7 +147,7 @@ class Mage_Core_Model_Resource_Config extends Mage_Core_Model_Resource_Db_Abstra $deleteStores = array(); // set stores config values from database foreach ($rowset as $r) { - if ($r['scope'] !== 'stores') { + if ($r['scope'] !== Mage_Core_Model_Config::SCOPE_STORES) { continue; } $value = str_replace($substFrom, $substTo, $r['value']); @@ -158,14 +161,14 @@ class Mage_Core_Model_Resource_Config extends Mage_Core_Model_Resource_Db_Abstra if ($deleteWebsites) { $this->_getWriteAdapter()->delete($this->getMainTable(), array( - 'scope = ?' => 'websites', + 'scope = ?' => Mage_Core_Model_Config::SCOPE_WEBSITES, 'scope_id IN(?)' => $deleteWebsites, )); } if ($deleteStores) { $this->_getWriteAdapter()->delete($this->getMainTable(), array( - 'scope=?' => 'stores', + 'scope=?' => Mage_Core_Model_Config::SCOPE_STORES, 'scope_id IN(?)' => $deleteStores, )); } diff --git a/app/code/core/Mage/Core/Model/Resource/Setup.php b/app/code/core/Mage/Core/Model/Resource/Setup.php index 10b99379b1e9fcb1b7e761b2a12a83a95d76e3f8..d669117096debe904ef2b459f7e2f1daa2101844 100644 --- a/app/code/core/Mage/Core/Model/Resource/Setup.php +++ b/app/code/core/Mage/Core/Model/Resource/Setup.php @@ -274,7 +274,6 @@ class Mage_Core_Model_Resource_Setup /** * Apply data updates to the system after upgrading. * - * @param string $fromVersion * @return Mage_Core_Model_Resource_Setup */ public function applyDataUpdates() @@ -313,8 +312,8 @@ class Mage_Core_Model_Resource_Setup // Module is installed if ($dbVer !== false) { - $status = version_compare($configVer, $dbVer); - switch ($status) { + $status = version_compare($configVer, $dbVer); + switch ($status) { case self::VERSION_COMPARE_LOWER: $this->_rollbackResourceDb($configVer, $dbVer); break; @@ -324,7 +323,7 @@ class Mage_Core_Model_Resource_Setup default: return true; break; - } + } } elseif ($configVer) { $this->_installResourceDb($configVer); } @@ -579,7 +578,8 @@ class Mage_Core_Model_Resource_Setup case self::TYPE_DATA_UPGRADE: $this->_getResource()->setDataVersion($this->_resourceName, $version); break; - + default: + break; } return $this; @@ -592,7 +592,7 @@ class Mage_Core_Model_Resource_Setup * @param string $fromVersion * @param string $toVersion * @return string|false - * @throws Mage_Core_Exception + * @throws Magento_Exception */ protected function _modifyResourceDb($actionType, $fromVersion, $toVersion) @@ -710,6 +710,8 @@ class Mage_Core_Model_Resource_Setup case self::TYPE_DB_UNINSTALL: break; + default: + break; } return $arrRes; } @@ -728,7 +730,7 @@ class Mage_Core_Model_Resource_Setup * @param string|integer $parentId * @return mixed|boolean */ - public function getTableRow($table, $idField, $id, $field=null, $parentField=null, $parentId=0) + public function getTableRow($table, $idField, $id, $field = null, $parentField = null, $parentId = 0) { $table = $this->getTable($table); if (empty($this->_setupCache[$table][$parentId][$id])) { @@ -839,10 +841,9 @@ class Mage_Core_Model_Resource_Setup * @param string $value * @param int|string $scope * @param int $scopeId - * @param int $inherit * @return Mage_Core_Model_Resource_Setup */ - public function setConfigData($path, $value, $scope = 'default', $scopeId = 0, $inherit=0) + public function setConfigData($path, $value, $scope = Mage_Core_Model_Store::DEFAULT_CODE, $scopeId = 0) { $table = $this->getTable('core_config_data'); // this is a fix for mysql 4.1 diff --git a/app/code/core/Mage/Core/Model/Resource/Store.php b/app/code/core/Mage/Core/Model/Resource/Store.php index 00a0da47a9aaa8942cc1a7aab94801681d8c7d55..525a93176833f2643f07a7989e3c8d464c2b1966 100644 --- a/app/code/core/Mage/Core/Model/Resource/Store.php +++ b/app/code/core/Mage/Core/Model/Resource/Store.php @@ -97,7 +97,7 @@ class Mage_Core_Model_Resource_Store extends Mage_Core_Model_Resource_Db_Abstrac protected function _afterDelete(Mage_Core_Model_Abstract $model) { $where = array( - 'scope = ?' => 'stores', + 'scope = ?' => Mage_Core_Model_Config::SCOPE_STORES, 'scope_id = ?' => $model->getStoreId() ); diff --git a/app/code/core/Mage/Core/Model/Resource/Theme/Collection.php b/app/code/core/Mage/Core/Model/Resource/Theme/Collection.php index 10d106ca943ade6a37a7e221c1df68cccecf2ba9..f78b754f4f503b91d2671ac117e28de54b9696fe 100644 --- a/app/code/core/Mage/Core/Model/Resource/Theme/Collection.php +++ b/app/code/core/Mage/Core/Model/Resource/Theme/Collection.php @@ -29,6 +29,11 @@ */ class Mage_Core_Model_Resource_Theme_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract { + /** + * Default page size + */ + const DEFAULT_PAGE_SIZE = 4; + /** * Collection initialization */ @@ -58,7 +63,7 @@ class Mage_Core_Model_Resource_Theme_Collection extends Mage_Core_Model_Resource * @param string $area * @return Mage_Core_Model_Resource_Theme_Collection */ - public function addAreaFilter($area) + public function addAreaFilter($area = Mage_Core_Model_App_Area::AREA_FRONTEND) { $this->getSelect()->where('main_table.area=?', $area); return $this; @@ -133,4 +138,15 @@ class Mage_Core_Model_Resource_Theme_Collection extends Mage_Core_Model_Resource return $this->getFirstItem(); } + + /** + * Set page size + * + * @param int $size + * @return Mage_Core_Model_Resource_Theme_Collection + */ + public function setPageSize($size = self::DEFAULT_PAGE_SIZE) + { + return parent::setPageSize($size); + } } diff --git a/app/code/core/Mage/Core/Model/Resource/Website.php b/app/code/core/Mage/Core/Model/Resource/Website.php index 22436b0c100bc0334e2adb251c2cce9fdb1bd8c4..f3f7fac8c3d74e7bf1bfeb5aadfaf5ed4aea7c4a 100644 --- a/app/code/core/Mage/Core/Model/Resource/Website.php +++ b/app/code/core/Mage/Core/Model/Resource/Website.php @@ -97,7 +97,7 @@ class Mage_Core_Model_Resource_Website extends Mage_Core_Model_Resource_Db_Abstr protected function _afterDelete(Mage_Core_Model_Abstract $model) { $where = array( - 'scope = ?' => 'websites', + 'scope = ?' => Mage_Core_Model_Config::SCOPE_WEBSITES, 'scope_id = ?' => $model->getWebsiteId() ); @@ -110,7 +110,7 @@ class Mage_Core_Model_Resource_Website extends Mage_Core_Model_Resource_Db_Abstr /** * Retrieve default stores select object * Select fields website_id, store_id - * + * * @param boolean $withDefault include/exclude default admin website * @return Varien_Db_Select */ diff --git a/app/code/core/Mage/Core/Model/Session/Abstract.php b/app/code/core/Mage/Core/Model/Session/Abstract.php index 5cc1526bc64c14f3458e07acb7306bcb0d9eee7c..108d63efb67f2c61e86368ba7f1a9879f6831b39 100644 --- a/app/code/core/Mage/Core/Model/Session/Abstract.php +++ b/app/code/core/Mage/Core/Model/Session/Abstract.php @@ -78,6 +78,14 @@ class Mage_Core_Model_Session_Abstract extends Varien_Object */ protected $_skipSessionIdFlag = false; + /** + * This method needs to support sessions with APC enabled + */ + public function __destruct() + { + session_write_close(); + } + /** * Configure session handler and start session * diff --git a/app/code/core/Mage/Core/Model/Store/Group/Factory.php b/app/code/core/Mage/Core/Model/Store/Group/Factory.php index 8027acf611b5622e123741a496c6123280845a43..505221f74fb2f67ef9af4bf5ce79241567b00f47 100644 --- a/app/code/core/Mage/Core/Model/Store/Group/Factory.php +++ b/app/code/core/Mage/Core/Model/Store/Group/Factory.php @@ -27,8 +27,13 @@ /** * Store Group factory */ -class Mage_Core_Model_Store_Group_Factory +class Mage_Core_Model_Store_Group_Factory implements Magento_ObjectManager_Factory { + /** + * Store group model class name + */ + const CLASS_NAME = 'Mage_Core_Model_Store_Group'; + /** * Object Manager * @@ -36,17 +41,20 @@ class Mage_Core_Model_Store_Group_Factory */ protected $_objectManager; + /** + * @param Magento_ObjectManager $objectManager + */ public function __construct(Magento_ObjectManager $objectManager) { $this->_objectManager = $objectManager; } /** - * @param array $data - * @return Mage_Core_Model_Store_Group + * @param array $arguments + * @return mixed */ - public function create(array $data = array()) + public function createFromArray(array $arguments = array()) { - return $this->_objectManager->create('Mage_Core_Model_Store_Group', $data); + return $this->_objectManager->get(self::CLASS_NAME, $arguments); } } diff --git a/app/code/core/Mage/Core/Model/Theme.php b/app/code/core/Mage/Core/Model/Theme.php index 034c270240f1b1c0c1fbcdccc135eb93017d81cc..1efb5dbfc622baba2785cb8174a696d1f362884b 100644 --- a/app/code/core/Mage/Core/Model/Theme.php +++ b/app/code/core/Mage/Core/Model/Theme.php @@ -35,12 +35,16 @@ * @method string getPreviewImage() * @method string getThemeDirectory() * @method string getParentId() + * @method Mage_Core_Model_Theme setAssignedStores(array $stores) + * @method array getAssignedStores() * @method Mage_Core_Model_Theme addData(array $data) * @method Mage_Core_Model_Theme setParentId(int $id) * @method Mage_Core_Model_Theme setParentTheme($parentTheme) * @method Mage_Core_Model_Theme setPackageCode(string $packageCode) * @method Mage_Core_Model_Theme setThemeCode(string $themeCode) * @method Mage_Core_Model_Theme setPreviewImage(string $previewImage) + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract { @@ -91,6 +95,51 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract */ protected $_ioFile; + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @var Mage_Core_Model_Theme_Factory + */ + protected $_themeFactory; + + /** + * @var Mage_Core_Helper_Data + */ + protected $_helper; + + /** + * Initialize dependencies + * + * @param Mage_Core_Model_Event_Manager $eventDispatcher + * @param Mage_Core_Model_Cache $cacheManager + * @param Magento_ObjectManager $objectManager + * @param Mage_Core_Model_Theme_Factory $themeFactory + * @param Mage_Core_Helper_Data $helper + * @param Mage_Core_Model_Resource_Theme $resource + * @param Mage_Core_Model_Resource_Theme_Collection $resourceCollection + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Mage_Core_Model_Event_Manager $eventDispatcher, + Mage_Core_Model_Cache $cacheManager, + Magento_ObjectManager $objectManager, + Mage_Core_Model_Theme_Factory $themeFactory, + Mage_Core_Helper_Data $helper, + Mage_Core_Model_Resource_Theme $resource, + Mage_Core_Model_Resource_Theme_Collection $resourceCollection = null, + array $data = array() + ) { + parent::__construct($eventDispatcher, $cacheManager, $resource, $resourceCollection, $data); + $this->_objectManager = $objectManager; + $this->_themeFactory = $themeFactory; + $this->_helper = $helper; + } + /** * Theme model initialization */ @@ -119,20 +168,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract */ public function getCollectionFromFilesystem() { - return Mage::getSingleton('Mage_Core_Model_Theme_Collection'); - } - - /** - * Processing object after load data - * - * @return Mage_Core_Model_Theme - */ - protected function _afterLoad() - { - if ($this->getId()) { - $this->_updateDefaultParams(); - } - return parent::_afterLoad(); + return $this->_objectManager->get('Mage_Core_Model_Theme_Collection'); } /** @@ -144,7 +180,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract protected function _validate() { /** @var $validator Mage_Core_Model_Theme_Validator */ - $validator = Mage::getModel('Mage_Core_Model_Theme_Validator'); + $validator = $this->_objectManager->get('Mage_Core_Model_Theme_Validator'); if (!$validator->validate($this)) { $messages = $validator->getErrorMessages(); Mage::throwException(implode(PHP_EOL, reset($messages))); @@ -224,7 +260,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract protected function _beforeDelete() { if (!$this->isDeletable()) { - Mage::throwException(Mage::helper('Mage_Core_Helper_Data')->__('Current theme isn\'t deletable.')); + Mage::throwException($this->_helper->__('Current theme isn\'t deletable.')); } $this->removePreviewImage(); return parent::_beforeDelete(); @@ -254,7 +290,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract $theme = null; if ($this->getParentId()) { - $theme = Mage::getModel('Mage_Core_Model_Theme')->load($this->getParentId()); + $theme = $this->_themeFactory->create()->load($this->getParentId()); } $this->setParentTheme($theme); return $theme; @@ -292,7 +328,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract */ protected function _getPreviewImagePublishedRootDir() { - $dirPath = Mage::getBaseDir('media') . DS . self::THEME_DIR; + $dirPath = Mage::getBaseDir('media') . DIRECTORY_SEPARATOR . self::THEME_DIR; $this->_getIoFile()->checkAndCreateFolder($dirPath); return $dirPath; } @@ -304,7 +340,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract */ public function getImagePathOrigin() { - return $this->_getPreviewImagePublishedRootDir() . DS . self::IMAGE_DIR_ORIGIN; + return $this->_getPreviewImagePublishedRootDir() . DIRECTORY_SEPARATOR . self::IMAGE_DIR_ORIGIN; } /** @@ -314,7 +350,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract */ protected function _getImagePathPreview() { - return $this->_getPreviewImagePublishedRootDir() . DS . self::IMAGE_DIR_PREVIEW; + return $this->_getPreviewImagePublishedRootDir() . DIRECTORY_SEPARATOR . self::IMAGE_DIR_PREVIEW; } /** @@ -368,7 +404,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract return false; } if (!$adapter->isValid($scope)) { - Mage::throwException(Mage::helper('Mage_Core_Helper_Data')->__('Uploaded image is not valid')); + Mage::throwException($this->_helper->__('Uploaded image is not valid')); } $upload = new Varien_File_Uploader($scope); $upload->setAllowCreateFolders(true); @@ -377,7 +413,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract $upload->setFilesDispersion(false); if (!$upload->save($this->getImagePathOrigin())) { - Mage::throwException(Mage::helper('Mage_Core_Helper_Data')->__('Image can not be saved.')); + Mage::throwException($this->_helper->__('Image can not be saved.')); } $fileName = $this->getImagePathOrigin() . DS . $upload->getUploadedFileName(); @@ -394,7 +430,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract */ public function createPreviewImage($imagePath) { - $adapter = Mage::helper('Mage_Core_Helper_Data')->getImageAdapterType(); + $adapter = $this->_helper->getImageAdapterType(); $image = new Varien_Image($imagePath, $adapter); $image->keepTransparency(true); $image->constrainOnly(true); @@ -411,6 +447,23 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract return $imageName; } + /** + * Create preview image copy + * + * @return Mage_Core_Model_Theme + */ + public function createPreviewImageCopy() + { + $filePath = $this->_getImagePathPreview() . DIRECTORY_SEPARATOR . $this->getPreviewImage(); + $destinationFileName = Varien_File_Uploader::getNewFileName($filePath); + $this->_getIoFile()->cp( + $this->_getImagePathPreview() . DIRECTORY_SEPARATOR . $this->getPreviewImage(), + $this->_getImagePathPreview() . DIRECTORY_SEPARATOR . $destinationFileName + ); + $this->setPreviewImage($destinationFileName); + return $this; + } + /** * Delete preview image * @@ -421,7 +474,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract $previewImage = $this->getPreviewImage(); $this->setPreviewImage(''); if ($previewImage) { - $this->_getIoFile()->rm($this->_getImagePathPreview() . DS . $previewImage); + $this->_getIoFile()->rm($this->_getImagePathPreview() . DIRECTORY_SEPARATOR . $previewImage); } return $this; } @@ -476,18 +529,6 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract return $this->getArea() . '/' . $this->getThemePath(); } - /** - * Update default params (package_code and theme_code) - * - * @return Mage_Core_Model_Theme - */ - protected function _updateDefaultParams() - { - list($packageCode, $themeCode) = $this->getThemePath() ? explode('/', $this->getThemePath()) : null; - $this->setPackageCode($packageCode)->setThemeCode($themeCode); - return $this; - } - /** * Check if the theme is compatible with Magento version * @@ -514,9 +555,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract public function checkThemeCompatible() { if (!$this->isThemeCompatible()) { - $this->setThemeTitle( - Mage::helper('Mage_Core_Helper_Data')->__('%s (incompatible version)', $this->getThemeTitle()) - ); + $this->setThemeTitle($this->_helper->__('%s (incompatible version)', $this->getThemeTitle())); } return $this; } @@ -551,7 +590,7 @@ class Mage_Core_Model_Theme extends Mage_Core_Model_Abstract */ public function getLabelsCollectionForSystemConfiguration() { - return $this->getLabelsCollection(Mage::helper('Mage_Core_Helper_Data')->__('-- No Theme --')); + return $this->getLabelsCollection($this->_helper->__('-- No Theme --')); } /** diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php b/app/code/core/Mage/Core/Model/Theme/Factory.php similarity index 66% rename from app/code/core/Mage/Core/Controller/Varien/Router/Standard.php rename to app/code/core/Mage/Core/Model/Theme/Factory.php index a2572cc21bee04ae1e380ec90cc3d8c4785004ea..d108ce8e908db3cb21392d6f8216ac33999afdcd 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php +++ b/app/code/core/Mage/Core/Model/Theme/Factory.php @@ -25,28 +25,30 @@ */ /** - * @TODO This is temporary router. - * When required areas will be created this router should be removed or renamed and become a part of an area + * Theme factory */ -class Mage_Core_Controller_Varien_Router_Standard extends Mage_Core_Controller_Varien_Router_Base +class Mage_Core_Model_Theme_Factory { /** - * @param array $options + * Object Manager * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @var Magento_ObjectManager */ - public function __construct(Magento_ObjectManager $objectManager, array $options = array()) + protected $_objectManager; + + public function __construct(Magento_ObjectManager $objectManager) { $this->_objectManager = $objectManager; } /** - * @param $configArea - * @param $useRouterName + * Create new instance + * + * @param array $data + * @return Mage_Core_Model_Theme */ - public function collectRoutes($configArea, $useRouterName) + public function create(array $data = array()) { - $this->_area = $configArea; - parent::collectRoutes($configArea, $useRouterName); + return $this->_objectManager->create('Mage_Core_Model_Theme', $data); } } diff --git a/app/code/core/Mage/Core/Model/Theme/Registration.php b/app/code/core/Mage/Core/Model/Theme/Registration.php index a6d1f2e6bf7b3a826fd561206e0355f57e45bfeb..cebc813da5ac71db95ca464c24dffcb9b4854ada 100644 --- a/app/code/core/Mage/Core/Model/Theme/Registration.php +++ b/app/code/core/Mage/Core/Model/Theme/Registration.php @@ -83,11 +83,11 @@ class Mage_Core_Model_Theme_Registration public function register($baseDir = '', $pathPattern = '') { $this->_collection = $this->getThemeModel()->getCollectionFromFilesystem(); - - if (empty($baseDir) || empty($pathPattern)) { + $this->_collection->setBaseDir($baseDir); + if (empty($pathPattern)) { $this->_collection->addDefaultPattern('*'); } else { - $this->_collection->setBaseDir($baseDir)->addTargetPattern($pathPattern); + $this->_collection->addTargetPattern($pathPattern); } foreach ($this->_collection as $theme) { diff --git a/app/code/core/Mage/Core/Model/Theme/Service.php b/app/code/core/Mage/Core/Model/Theme/Service.php new file mode 100644 index 0000000000000000000000000000000000000000..b458d7a2a7e0ac65e0ae9bd63137471b67b8ee2d --- /dev/null +++ b/app/code/core/Mage/Core/Model/Theme/Service.php @@ -0,0 +1,303 @@ +<?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_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Theme Service model + */ +class Mage_Core_Model_Theme_Service +{ + /** + * @var Mage_Core_Model_Theme_Factory + */ + protected $_themeFactory; + + /** + * @var Mage_Core_Model_Design_Package + */ + protected $_design; + + /** + * @var Mage_Core_Model_App + */ + protected $_app; + + /** + * Flag that shows if theme customizations exist in Magento + * + * @var bool + */ + protected $_isCustomizationsExist; + + /** + * Theme customizations which are assigned to store views or as default + * + * @see self::_prepareThemeCustomizations() + * @var array + */ + protected $_assignedThemeCustomizations; + + /** + * Theme customizations which are not assigned to store views or as default + * + * @see self::_prepareThemeCustomizations() + * @var array + */ + protected $_unassignedThemeCustomizations; + + /** + * @var Mage_Core_Helper_Data + */ + protected $_helper; + + /** + * Initialize service model + * + * @param Mage_Core_Model_Theme_Factory $themeFactory + * @param Mage_Core_Model_Design_Package $design + * @param Mage_Core_Model_App $app + * @param Mage_Core_Helper_Data $helper + */ + public function __construct( + Mage_Core_Model_Theme_Factory $themeFactory, + Mage_Core_Model_Design_Package $design, + Mage_Core_Model_App $app, + Mage_Core_Helper_Data $helper + ) { + $this->_themeFactory = $themeFactory; + $this->_design = $design; + $this->_app = $app; + $this->_helper = $helper; + } + + /** + * Assign theme to the stores + * + * @param int $themeId + * @param array|null $stores + * @param string $scope + * @param string $area + * @return Mage_Core_Model_Theme_Service + * @throws UnexpectedValueException + */ + public function assignThemeToStores($themeId, $stores, $scope = Mage_Core_Model_Config::SCOPE_STORES, + $area = Mage_Core_Model_App_Area::AREA_FRONTEND + ) { + /** @var $theme Mage_Core_Model_Theme */ + $theme = $this->_themeFactory->create()->load($themeId); + if (!$theme->getId()) { + throw new UnexpectedValueException('Theme is not recognized. Requested id: ' . $themeId); + } + + $themeCustomization = $theme->isVirtual() ? $theme : $this->_createThemeCustomization($theme); + + $configPath = $this->_design->getConfigPathByArea($area); + + foreach ($this->_getAssignedScopesCollection($scope, $configPath) as $config) { + if ($config->getValue() == $themeId && !in_array($config->getScopeId(), $stores)) { + $this->_app->getConfig()->deleteConfig($configPath, $scope, $config->getScopeId()); + } + } + + foreach ($stores as $storeId) { + $this->_app->getConfig()->saveConfig($configPath, $themeCustomization->getId(), $scope, $storeId); + } + + if ($stores === null || count($stores) > 0) { + $this->_app->cleanCache(Mage_Core_Model_Config::CACHE_TAG); + } + + return $this; + } + + /** + * Create theme customization + * + * @param Mage_Core_Model_Theme $theme + * @return Mage_Core_Model_Theme + */ + protected function _createThemeCustomization($theme) + { + $themeCopyCount = $this->_getThemeCustomizations()->addFilter('parent_id', $theme->getId())->count(); + + $themeData = $theme->getData(); + $themeData['parent_id'] = $theme->getId(); + $themeData['theme_id'] = null; + $themeData['theme_path'] = null; + $themeData['theme_title'] = $theme->getThemeTitle() . ' - ' . $this->_helper->__('Copy') . ' #' + . ($themeCopyCount + 1); + + /** @var $themeCustomization Mage_Core_Model_Theme */ + $themeCustomization = $this->_themeFactory->create()->setData($themeData); + $themeCustomization->createPreviewImageCopy()->save(); + return $themeCustomization; + } + + /** + * Get assigned scopes collection of a theme + * + * @param string $scope + * @param string $configPath + * @return Mage_Core_Model_Resource_Config_Data_Collection + */ + protected function _getAssignedScopesCollection($scope, $configPath) + { + return $this->_app->getConfig()->getConfigDataModel()->getCollection() + ->addFieldToFilter('scope', $scope) + ->addFieldToFilter('path', $configPath); + } + + /** + * Check whether theme customizations exist in Magento + * + * @return bool + */ + public function isCustomizationsExist() + { + if ($this->_isCustomizationsExist === null) { + $this->_isCustomizationsExist = false; + /** @var $theme Mage_Core_Model_Theme */ + foreach ($this->_themeFactory->create()->getCollection() as $theme) { + if ($theme->isVirtual()) { + $this->_isCustomizationsExist = true; + break; + } + } + } + return $this->_isCustomizationsExist; + } + + /** + * Return frontend theme collection by page. Theme customizations are not included, only phisical themes. + * + * @param int $page + * @param int $pageSize + * @return Mage_Core_Model_Resource_Theme_Collection + */ + public function getThemes($page, $pageSize) + { + /** @var $collection Mage_Core_Model_Resource_Theme_Collection */ + $collection = $this->_themeFactory->create()->getCollection(); + $collection->addAreaFilter(Mage_Core_Model_App_Area::AREA_FRONTEND) + ->addFilter('theme_path', 'theme_path IS NOT NULL', 'string') + ->setPageSize($pageSize); + return $collection->setCurPage($page); + } + + /** + * Return theme customizations which are assigned to store views + * + * @see self::_prepareThemeCustomizations() + * @return array + */ + public function getAssignedThemeCustomizations() + { + if (is_null($this->_assignedThemeCustomizations)) { + $this->_prepareThemeCustomizations(); + } + return $this->_assignedThemeCustomizations; + } + + /** + * Return theme customizations which are not assigned to store views. + * + * @see self::_prepareThemeCustomizations() + * @return array + */ + public function getUnassignedThemeCustomizations() + { + if (is_null($this->_unassignedThemeCustomizations)) { + $this->_prepareThemeCustomizations(); + } + return $this->_unassignedThemeCustomizations; + } + + /** + * Fetch theme customization and sort them out to arrays: + * self::_assignedThemeCustomizations and self::_unassignedThemeCustomizations. + * + * NOTE: To get into "assigned" list theme customization not necessary should be assigned to store-view directly. + * It can be set to website or as default theme and be used by store-view via config fallback mechanism. + * + * @return Mage_Core_Model_Theme_Service + */ + protected function _prepareThemeCustomizations() + { + /** @var $themeCustomizations Mage_Core_Model_Resource_Theme_Collection */ + $themeCustomizations = $this->_getThemeCustomizations(); + $assignedThemes = $this->getStoresByThemes(); + + $this->_assignedThemeCustomizations = array(); + $this->_unassignedThemeCustomizations = array(); + /** @var $theme Mage_Core_Model_Theme */ + foreach ($themeCustomizations as $theme) { + if (isset($assignedThemes[$theme->getId()])) { + $theme->setAssignedStores($assignedThemes[$theme->getId()]); + $this->_assignedThemeCustomizations[] = $theme; + } else { + $this->_unassignedThemeCustomizations[] = $theme; + } + } + return $this; + } + + /** + * Return theme customizations collection + * + * @return Mage_Core_Model_Resource_Theme_Collection + */ + protected function _getThemeCustomizations() + { + /** @var $collection Mage_Core_Model_Resource_Theme_Collection */ + $collection = $this->_themeFactory->create()->getCollection(); + $collection->addAreaFilter(Mage_Core_Model_App_Area::AREA_FRONTEND) + ->addFilter('theme_path', 'theme_path IS NULL', 'string'); + return $collection; + } + + /** + * Return stores grouped by assigned themes + * + * @return array + */ + public function getStoresByThemes() + { + $storesByThemes = array(); + $stores = $this->_app->getStores(); + /** @var $store Mage_Core_Model_Store */ + foreach ($stores as $store) { + $themeId = $this->_design->getConfigurationDesignTheme( + Mage_Core_Model_App_Area::AREA_FRONTEND, + array('store' => $store) + ); + if (!isset($storesByThemes[$themeId])) { + $storesByThemes[$themeId] = array(); + } + $storesByThemes[$themeId][] = $store; + } + + return $storesByThemes; + } +} diff --git a/app/code/core/Mage/Core/Model/Url.php b/app/code/core/Mage/Core/Model/Url.php index 518f7e7dc87cc3a4debe1a2059ec01f4acf10253..c5ed7f7020a8d144509719740bf460d7a7338d0c 100644 --- a/app/code/core/Mage/Core/Model/Url.php +++ b/app/code/core/Mage/Core/Model/Url.php @@ -470,7 +470,7 @@ class Mage_Core_Model_Url extends Varien_Object /** * Retrieve route path * - * @param array $routParams + * @param array $routeParams * @return string */ public function getRoutePath($routeParams = array()) @@ -725,11 +725,14 @@ class Mage_Core_Model_Url extends Varien_Object * * @param string $routePath * @param array $routeParams - * * @return string */ public function getRouteUrl($routePath = null, $routeParams = null) { + if (filter_var($routePath, FILTER_VALIDATE_URL)) { + return $routePath; + } + $this->unsetData('route_params'); if (isset($routeParams['_direct'])) { @@ -948,6 +951,10 @@ class Mage_Core_Model_Url extends Varien_Object */ public function getUrl($routePath = null, $routeParams = null) { + if (filter_var($routePath, FILTER_VALIDATE_URL)) { + return $routePath; + } + $escapeQuery = false; /** @@ -1179,7 +1186,7 @@ class Mage_Core_Model_Url extends Varien_Object public function isOwnOriginUrl() { $storeDomains = array(); - $referer = parse_url(Mage::app()->getFrontController()->getRequest()->getServer('HTTP_REFERER'), PHP_URL_HOST); + $referer = parse_url(Mage::app()->getRequest()->getServer('HTTP_REFERER'), PHP_URL_HOST); foreach (Mage::app()->getStores() as $store) { $storeDomains[] = parse_url($store->getBaseUrl(), PHP_URL_HOST); $storeDomains[] = parse_url($store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, true), PHP_URL_HOST); diff --git a/app/code/core/Mage/Core/Model/Url/RewriteFactory.php b/app/code/core/Mage/Core/Model/Url/RewriteFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..046c070d01c785fc4e4d1d51e590927577f50413 --- /dev/null +++ b/app/code/core/Mage/Core/Model/Url/RewriteFactory.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_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Core_Model_Url_RewriteFactory implements Magento_ObjectManager_Factory +{ + /** + * Entity class name + */ + const CLASS_NAME = 'Mage_Core_Model_Url_Rewrite'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * @param array $arguments + * @return Mage_Core_Model_Url_Rewrite + */ + public function createFromArray(array $arguments = array()) + { + return $this->_objectManager->create(self::CLASS_NAME, $arguments, false); + } +} diff --git a/app/code/core/Mage/Core/Model/Website.php b/app/code/core/Mage/Core/Model/Website.php index de813b5159377be45c8c67336d8cd3dce33c6b87..bf9b2422841a20f8390802d22fa7c3559de2ac90 100644 --- a/app/code/core/Mage/Core/Model/Website.php +++ b/app/code/core/Mage/Core/Model/Website.php @@ -31,6 +31,10 @@ * @method Mage_Core_Model_Resource_Website getResource() * @method Mage_Core_Model_Website setCode(string $value) * @method string getName() + * @method string getGroupTitle() + * @method string getStoreTitle() + * @method string getStoreId() + * @method string getGroupId() * @method Mage_Core_Model_Website setName(string $value) * @method int getSortOrder() * @method Mage_Core_Model_Website setSortOrder(int $value) @@ -67,7 +71,7 @@ class Mage_Core_Model_Website extends Mage_Core_Model_Abstract protected $_configCache = array(); /** - * Website Group Coleection array + * Website Group Collection array * * @var array */ @@ -178,14 +182,14 @@ class Mage_Core_Model_Website extends Mage_Core_Model_Abstract return $this; } if (is_numeric($code)) { - foreach (Mage::getConfig()->getNode('websites')->children() as $websiteCode=>$website) { - if ((int)$website->system->website->id==$code) { + foreach (Mage::getConfig()->getNode('websites')->children() as $websiteCode => $website) { + if ((int)$website->system->website->id == $code) { $code = $websiteCode; break; } } } else { - $website = Mage::getConfig()->getNode('websites/'.$code); + $website = Mage::getConfig()->getNode('websites/' . $code); } if (!empty($website)) { $this->setCode($code); @@ -204,14 +208,13 @@ class Mage_Core_Model_Website extends Mage_Core_Model_Abstract public function getConfig($path) { if (!isset($this->_configCache[$path])) { - $config = Mage::getConfig()->getNode('websites/'.$this->getCode().'/'.$path); + $config = Mage::getConfig()->getNode('websites/' . $this->getCode() . '/' . $path); if (!$config) { return false; - #throw Mage::exception('Mage_Core', Mage::helper('Mage_Core_Helper_Data')->__('Invalid website\'s configuration path: %s', $path)); } if ($config->hasChildren()) { $value = array(); - foreach ($config->children() as $k=>$v) { + foreach ($config->children() as $k => $v) { $value[$k] = $v; } } else { @@ -244,6 +247,7 @@ class Mage_Core_Model_Website extends Mage_Core_Model_Abstract * Set website groups * * @param array $groups + * @return Mage_Core_Model_Website */ public function setGroups($groups) { @@ -255,7 +259,7 @@ class Mage_Core_Model_Website extends Mage_Core_Model_Abstract if ($this->getDefaultGroupId() == $group->getId()) { $this->_defaultGroup = $group; } - $this->_groupsCount ++; + $this->_groupsCount++; } return $this; } @@ -534,7 +538,7 @@ class Mage_Core_Model_Website extends Mage_Core_Model_Abstract * Retrieve default stores select object * Select fields website_id, store_id * - * @param $withDefault include/exclude default admin website + * @param bool $withDefault include/exclude default admin website * @return Varien_Db_Select */ public function getDefaultStoresSelect($withDefault = false) diff --git a/app/code/core/Mage/Core/etc/config.xml b/app/code/core/Mage/Core/etc/config.xml index fb35693a17d3ecf231d30cfd2ce0bb3fb86b8806..46d1e2fb4f541559f72bea62d39f063be9de6df3 100644 --- a/app/code/core/Mage/Core/etc/config.xml +++ b/app/code/core/Mage/Core/etc/config.xml @@ -277,7 +277,8 @@ <routers> <standard> <area>frontend</area> - <class>Mage_Core_Controller_Varien_Router_Standard</class> + <class>Mage_Core_Controller_Varien_Router_Base</class> + <base_controller>Mage_Core_Controller_Varien_Action</base_controller> </standard> </routers> <url> @@ -379,7 +380,8 @@ <routers> <standard> <area>frontend</area> - <class>Mage_Core_Controller_Varien_Router_Standard</class> + <class>Mage_Core_Controller_Varien_Router_Base</class> + <base_controller>Mage_Core_Controller_Varien_Action</base_controller> </standard> </routers> </web> diff --git a/app/code/core/Mage/Customer/Block/Account/Link.php b/app/code/core/Mage/Customer/Block/Account/Link.php index 19def49af590a5fb4b16898bda9ceb869fba6b4b..559384cbff176a0d640645117d89daf43bfb5c20 100644 --- a/app/code/core/Mage/Customer/Block/Account/Link.php +++ b/app/code/core/Mage/Customer/Block/Account/Link.php @@ -113,9 +113,10 @@ class Mage_Customer_Block_Account_Link extends Mage_Core_Block_Abstract */ protected function _addLink($target, $text, $url, $title, $position, $textBefore='', $textAfter='') { + /** @var $target Mage_Page_Block_Template_Links */ $target = $this->getLayout()->getBlock($target); if ($target && method_exists($target, 'addLink')) { - $target->addLink($text, $url, $title, false, array(), $position, null, null, $textBefore, $textAfter); + $target->addLink($text, $url, $title, true, array(), $position, null, null, $textBefore, $textAfter); } return $this; } diff --git a/app/code/core/Mage/Customer/sql/customer_setup/upgrade-1.6.2.0.1-1.6.2.0.3.php b/app/code/core/Mage/Customer/sql/customer_setup/upgrade-1.6.2.0.1-1.6.2.0.3.php index 5d3f96706ca8227d0c132e85ab86028025ec3932..4fe61063a004b26b6545d1a826819262de675745 100644 --- a/app/code/core/Mage/Customer/sql/customer_setup/upgrade-1.6.2.0.1-1.6.2.0.3.php +++ b/app/code/core/Mage/Customer/sql/customer_setup/upgrade-1.6.2.0.1-1.6.2.0.3.php @@ -27,4 +27,9 @@ /** @var $installer Mage_Customer_Model_Resource_Setup */ $installer = $this; -$installer->installEntities(); +$installer->cleanCache(); + +$entities = $installer->getDefaultEntities(); +foreach ($entities as $entityName => $entity) { + $installer->addEntityType($entityName, $entity); +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/List.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Container.php similarity index 50% rename from app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/List.php rename to app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Container.php index 2e586276cabfd277634bd270d0ef7d4a30994a6b..c36596357a85114d4fbbc2a3d8d5414fa74421f4 100644 --- a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/List.php +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Container.php @@ -25,16 +25,30 @@ */ /** - * Design editor theme list + * Editor toolbar */ -class Mage_DesignEditor_Block_Adminhtml_Theme_List extends Mage_Backend_Block_Widget_Container +class Mage_DesignEditor_Block_Adminhtml_Editor_Container extends Mage_Backend_Block_Widget_Container { /** - * So called "container controller" to specify group of blocks participating in some action + * Frame Url * * @var string */ - protected $_controller = 'vde'; + protected $_frameUrl; + + /** + * Add elements in layout + */ + protected function _prepareLayout() + { + $this->addButton('back_button', array( + 'label' => $this->_helperFactory->get('Mage_Catalog_Helper_Data')->__('Back'), + 'onclick' => 'setLocation(\'' . $this->getUrl('*/*') . '\')', + 'class' => 'back' + )); + + parent::_prepareLayout(); + } /** * Get header text @@ -43,34 +57,27 @@ class Mage_DesignEditor_Block_Adminhtml_Theme_List extends Mage_Backend_Block_Wi */ public function getHeaderText() { - return $this->__('Themes List'); + return $this->_helperFactory->get('Mage_DesignEditor_Helper_Data')->__('Visual Design Editor'); } /** - * Get list items of themes + * @param string $url * - * @param bool $isFeatured - * @return array + * @return Mage_DesignEditor_Block_Adminhtml_Editor_Container */ - public function getListItems($isFeatured = true) + public function setFrameUrl($url) { - /** @var $itemBlock Mage_DesignEditor_Block_Adminhtml_Theme_Item */ - $itemBlock = $this->getChildBlock('item'); - - /** @var $themeCollection Mage_Core_Model_Resource_Theme_Collection */ - $themeCollection = Mage::getResourceModel('Mage_Core_Model_Resource_Theme_Collection'); - $themeCollection->addAreaFilter(Mage_Core_Model_App_Area::AREA_FRONTEND); - - $items = array(); - /** @var $theme Mage_Core_Model_Theme */ - foreach ($themeCollection as $theme) { - if ($isFeatured != $theme->getIsFeatured()) { - continue; - } - $itemBlock->setTheme($theme); - $items[] = $this->getChildHtml('item', false); - } + $this->_frameUrl = $url; + return $this; + } - return $items; + /** + * Retrieve frame url + * + * @return string + */ + public function getFrameUrl() + { + return $this->_frameUrl; } } diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/BlockAbstract.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/BlockAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..842168f52bf2232e584f7ddfbe71eabb7e13f01c --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/BlockAbstract.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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Abstract toolbar block + */ +abstract class Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstract extends Mage_Backend_Block_Template +{ + /** + * Current VDE mode + * + * @var int + */ + protected $_mode; + + /** + * Get current VDE mode + * + * @return int + */ + public function getMode() + { + return $this->_mode; + } + + /** + * Get current VDE mode + * + * @param int $mode + * @return Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstract + */ + public function setMode($mode) + { + $this->_mode = $mode; + + return $this; + } + + /** + * Check if visual editor is in design mode + * + * @return bool + */ + public function isDesignMode() + { + return $this->getMode() == Mage_DesignEditor_Model_State::MODE_DESIGN; + } + + /** + * Check if visual editor is in navigation mode + * + * @return bool + */ + public function isNavigationMode() + { + return $this->getMode() == Mage_DesignEditor_Model_State::MODE_NAVIGATION; + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/Buttons.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/Buttons.php new file mode 100644 index 0000000000000000000000000000000000000000..373f7f481adb3cc31ad6cc7868d20fbd651e2c7c --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/Buttons.php @@ -0,0 +1,135 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * VDE buttons block + */ +class Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_Buttons + extends Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstract +{ + /** + * Current theme used for preview + * + * @var int + */ + protected $_themeId; + + /** + * Get current theme id + * + * @return int + */ + public function getThemeId() + { + return $this->_themeId; + } + + /** + * Get current theme id + * + * @param int $themeId + * @return Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_Buttons + */ + public function setThemeId($themeId) + { + $this->_themeId = $themeId; + + return $this; + } + + /** + * Get "View Layout" button URL + * + * @return string + */ + public function getViewLayoutUrl() + { + return $this->getUrl('*/*/getLayoutUpdate'); + } + + /** + * Get "Back" button URL + * + * @return string + */ + public function getBackUrl() + { + return $this->getUrl('*/*/'); + } + + /** + * Get "Navigation Mode" button URL + * + * @return string + */ + public function getNavigationModeUrl() + { + return $this->getUrl('*/*/launch', array( + 'mode' => Mage_DesignEditor_Model_State::MODE_NAVIGATION, + 'theme_id' => $this->getThemeId() + )); + } + + /** + * Get "Design Mode" button URL + * + * @return string + */ + public function getDesignModeUrl() + { + return $this->getUrl('*/*/launch', array( + 'mode' => Mage_DesignEditor_Model_State::MODE_DESIGN, + 'theme_id' => $this->getThemeId() + )); + } + + /** + * Get assign to storeview button + * + * @return string + */ + public function getAssignButtonHtml() + { + /** @var $assignButton Mage_Backend_Block_Widget_Button */ + $assignButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); + $assignButton->setData(array( + 'label' => $this->__('Assign this Theme'), + 'data_attr' => array( + 'widget-button' => array( + 'event' => 'assign', + 'related' => 'body', + 'eventData' => array( + 'theme_id' => $this->getThemeId() + ) + ), + ), + 'class' => 'save action-theme-assign', + 'target' => '_blank' + )); + + return $assignButton->toHtml(); + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Toolbar/HandlesHierarchy.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/HandlesHierarchy.php similarity index 51% rename from app/code/core/Mage/DesignEditor/Block/Toolbar/HandlesHierarchy.php rename to app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/HandlesHierarchy.php index 81fb97684a74d71945e227c5b4439d3254e24933..169dc3efb87192e9a7142c71d606f9cc5640544b 100644 --- a/app/code/core/Mage/DesignEditor/Block/Toolbar/HandlesHierarchy.php +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/HandlesHierarchy.php @@ -26,18 +26,70 @@ /** * Page handles navigation control + * + * @method array getHierarchy() getHierarchy() + * @method Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy setHierarchy() setHierarchy(array $data) + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Mage_DesignEditor_Block_Toolbar_HandlesHierarchy extends Mage_Core_Block_Template +class Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy + extends Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstract { /** * Page handle currently selected * - * @var string|bool + * @var string */ protected $_selectedHandle; /** - * Recursively render each level of the page handles hierarchy as an HTML list + * VDE url model + * + * @var Mage_DesignEditor_Model_Url_Handle + */ + protected $_vdeUrlBuilder; + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Model_Layout $layout + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Url $urlBuilder + * @param Mage_Core_Model_Translate $translator + * @param Mage_Core_Model_Cache $cache + * @param Mage_Core_Model_Design_Package $designPackage + * @param Mage_Core_Model_Session $session + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_DesignEditor_Model_Url_Handle $vdeUrlBuilder + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Model_Layout $layout, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Backend_Model_Url $urlBuilder, + Mage_Core_Model_Translate $translator, + Mage_Core_Model_Cache $cache, + Mage_Core_Model_Design_Package $designPackage, + Mage_Core_Model_Session $session, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_DesignEditor_Model_Url_Handle $vdeUrlBuilder, + array $data = array() + ) { + $this->_vdeUrlBuilder = $vdeUrlBuilder; + + parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, $designPackage, + $session, $storeConfig, $frontController, $helperFactory, $data + ); + } + + /** + * Recursively render each level of the page handles hierarchy * * @param array $hierarchy * @return string @@ -49,11 +101,12 @@ class Mage_DesignEditor_Block_Toolbar_HandlesHierarchy extends Mage_Core_Block_T } $result = '<ul>'; foreach ($hierarchy as $name => $info) { + $linkUrl = $this->_vdeUrlBuilder->getUrl('design/page/type', array('handle' => $name)); $class = $info['type'] == Mage_Core_Model_Layout_Merge::TYPE_FRAGMENT ? ' class="vde_option_fragment"' : ''; $result .= '<li rel="' . $name . '"' . $class . '>'; - $result .= '<a href="' . $this->getUrl('design/editor/page', array('handle' => $name)) . '">'; + $result .= '<a href="' . $linkUrl. '">'; $result .= $this->escapeHtml($info['label']); $result .= '</a>'; $result .= $this->_renderHierarchy($info['children']); @@ -70,29 +123,21 @@ class Mage_DesignEditor_Block_Toolbar_HandlesHierarchy extends Mage_Core_Block_T */ public function renderHierarchy() { - return $this->_renderHierarchy($this->getLayout()->getUpdate()->getPageHandlesHierarchy()); + return $this->_renderHierarchy($this->getHierarchy()); } /** * Retrieve the name of the currently selected page handle * - * @return string|false + * @return string|null */ public function getSelectedHandle() { if ($this->_selectedHandle === null) { - $this->_selectedHandle = false; - $layoutUpdate = $this->getLayout()->getUpdate(); - $pageHandles = $layoutUpdate->getPageHandles(); - if ($pageHandles) { - $this->_selectedHandle = end($pageHandles); - } else { - foreach (array_reverse($layoutUpdate->getHandles()) as $handle) { - if ($layoutUpdate->pageHandleExists($handle)) { - $this->_selectedHandle = $handle; - break; - } - } + $pageHandles = $this->getHierarchy(); + $defaultHandle = reset($pageHandles); + if ($defaultHandle !== false) { + $this->_selectedHandle = $defaultHandle['name']; } } return $this->_selectedHandle; @@ -101,7 +146,7 @@ class Mage_DesignEditor_Block_Toolbar_HandlesHierarchy extends Mage_Core_Block_T /** * Retrieve label for the currently selected page handle * - * @return string|false + * @return string|null */ public function getSelectedHandleLabel() { diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/ViewOptions.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/ViewOptions.php new file mode 100644 index 0000000000000000000000000000000000000000..5553b7e3a969cca85b16a7e8bc9263a8576d845d --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/ViewOptions.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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * View options control + */ +class Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_ViewOptions + extends Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstract +{ +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Launcher/Form.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Launcher/Form.php deleted file mode 100644 index 8965760a331c36ea43f50f9bcfb4e05550a5e9f5..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Launcher/Form.php +++ /dev/null @@ -1,64 +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_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Design editor launcher form - */ -class Mage_DesignEditor_Block_Adminhtml_Launcher_Form extends Mage_Adminhtml_Block_Widget_Form -{ - /** - * Create a form element with necessary controls - * - * @return Mage_Adminhtml_Block_Widget_Form - */ - protected function _prepareForm() - { - $form = new Varien_Data_Form(array( - 'id' => 'edit_form', - 'action' => $this->getUrl('adminhtml/system_design_editor/launch'), - 'target' => '_blank' - )); - - if (!Mage::app()->isSingleStoreMode()) { - $fieldset = $form->addFieldset( - 'base_fieldset', - array('legend' => Mage::helper('Mage_DesignEditor_Helper_Data')->__('Context Information')) - ); - $fieldset->addField('store_id', 'select', array( - 'name' => 'store_id', - 'label' => Mage::helper('Mage_DesignEditor_Helper_Data')->__('Store View'), - 'title' => Mage::helper('Mage_DesignEditor_Helper_Data')->__('Store View'), - 'required' => true, - 'values' => Mage::getSingleton('Mage_Core_Model_System_Store')->getStoreValuesForForm(), - )); - } - - $this->setForm($form); - $form->setUseContainer(true); - - return parent::_prepareForm(); - } -} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme.php new file mode 100644 index 0000000000000000000000000000000000000000..c380f6ce5657939c449e33605da27b3addb116f4 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme.php @@ -0,0 +1,94 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Design editor theme + * + * @method Mage_DesignEditor_Block_Adminhtml_Theme setTheme(Mage_Core_Model_Theme $theme) + * @method Mage_Core_Model_Theme getTheme() + */ +class Mage_DesignEditor_Block_Adminhtml_Theme extends Mage_Backend_Block_Template +{ + /** + * Buttons array + * + * @var array() + */ + protected $_buttons = array(); + + /** + * Add button + * + * @param Mage_Backend_Block_Widget_Button $button + * @return Mage_DesignEditor_Block_Adminhtml_Theme + */ + public function addButton($button) + { + $this->_buttons[] = $button; + return $this; + } + + /** + * Clear buttons + * + * @return Mage_DesignEditor_Block_Adminhtml_Theme + */ + public function clearButtons() + { + $this->_buttons = array(); + return $this; + } + + /** + * Get buttons html + * + * @return string + */ + public function getButtonsHtml() + { + $output = ''; + /** @var $button Mage_Backend_Block_Widget_Button */ + foreach ($this->_buttons as $button) { + $output .= $button->toHtml(); + } + return $output; + } + + /** + * Return array of assigned stores titles + * + * @return array + */ + public function getStoresTitles() + { + $storesTitles = array(); + /** @var $store Mage_Core_Model_Store */ + foreach ($this->getTheme()->getAssignedStores() as $store) { + $storesTitles[] = $store->getName(); + } + return $storesTitles; + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Item.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Item.php deleted file mode 100644 index 17de67400064af2e80c9eff09c80aea6f198dc1d..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Item.php +++ /dev/null @@ -1,75 +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_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Design editor theme - * - * @method Mage_DesignEditor_Block_Adminhtml_Theme_Item setTheme(Mage_Core_Model_Theme $theme) - * @method Mage_Core_Model_Theme getTheme() - */ -class Mage_DesignEditor_Block_Adminhtml_Theme_Item extends Mage_Backend_Block_Widget -{ - /** - * Get theme html - * - * @return string - */ - public function getThemeHtml() - { - $this->getChildBlock('theme')->setTheme($this->getTheme()); - return $this->getChildHtml('theme', false); - } - - /** - * Get launch button html - * - * @return string - */ - public function getLaunchButtonHtml() - { - $themeId = $this->getTheme()->getId(); - /** @var $previewButton Mage_Backend_Block_Widget_Button */ - $previewButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); - $previewButton->setData(array( - 'label' => $this->__('Launch'), - 'data_attr' => array( - 'widget-button' => array( - 'event' => 'save', - 'related' => '#edit_form', - 'eventData' => array( - 'action' => array('args' => array( - 'theme_id' => $themeId - )), - ) - ), - ), - 'class' => 'save', - 'target' => '_blank' - )); - - return $previewButton->toHtml(); - } -} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Abstract.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Abstract.php new file mode 100644 index 0000000000000000000000000000000000000000..0bbc766cc195166284d31915d2e7d6f98c144be9 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Abstract.php @@ -0,0 +1,191 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Abstract theme list + * + * @method Mage_Core_Model_Resource_Theme_Collection getCollection() + * @method Mage_Backend_Block_Abstract setCollection(Mage_Core_Model_Resource_Theme_Collection $collection) + */ +abstract class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract + extends Mage_Backend_Block_Abstract +{ + /** + * Get tab title + * + * @return string + */ + abstract public function getTabTitle(); + + /** + * Add theme buttons + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract + */ + protected function _addThemeButtons($themeBlock) + { + $themeBlock->clearButtons(); + return $this; + } + + /** + * Get list items of themes + * + * @return array + */ + public function getListItems() + { + /** @var $itemBlock Mage_DesignEditor_Block_Adminhtml_Theme */ + $itemBlock = $this->getChildBlock('theme'); + + $themeCollection = $this->getCollection(); + + $items = array(); + /** @var $theme Mage_Core_Model_Theme */ + foreach ($themeCollection as $theme) { + $itemBlock->setTheme($theme); + $this->_addThemeButtons($itemBlock); + $items[] = $this->getChildHtml('theme', false); + } + + return $items; + } + + /** + * Get assign to storeview button + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return string + */ + protected function _addAssignButtonHtml($themeBlock) + { + $themeId = $themeBlock->getTheme()->getId(); + /** @var $assignButton Mage_Backend_Block_Widget_Button */ + $assignButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); + $assignButton->setData(array( + 'label' => $this->__('Assign to a Storeview'), + 'data_attr' => array( + 'widget-button' => array( + 'event' => 'assign', + 'related' => 'body', + 'eventData' => array( + 'theme_id' => $themeId + ) + ), + ), + 'class' => 'save action-theme-assign', + 'target' => '_blank' + )); + + $themeBlock->addButton($assignButton); + return $this; + } + + /** + * Get preview button + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return string + */ + protected function _addPreviewButtonHtml($themeBlock) + { + /** @var $previewButton Mage_Backend_Block_Widget_Button */ + $previewButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); + $previewButton->setData(array( + 'label' => $this->__('Preview Theme'), + 'class' => 'preview-default', + 'data_attr' => array( + 'widget-button' => array( + 'event' => 'preview', + 'related' => 'body', + 'eventData' => array( + 'preview_url' => $this->_getPreviewUrl($themeBlock->getTheme()->getId()) + ) + ), + ) + )); + + $themeBlock->addButton($previewButton); + return $this; + } + + /** + * Get edit button + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return string + */ + protected function _addEditButtonHtml($themeBlock) + { + /** @var $previewButton Mage_Backend_Block_Widget_Button */ + $previewButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); + $previewButton->setData(array( + 'label' => $this->__('Edit Theme'), + 'class' => 'add edit-theme', + 'data_attr' => array( + 'widget-button' => array( + 'event' => 'preview', + 'related' => 'body', + 'eventData' => array( + 'preview_url' => $this->_getEditUrl($themeBlock->getTheme()->getId()) + ) + ), + ) + )); + + $themeBlock->addButton($previewButton); + return $this; + } + + /** + * Get preview url for selected theme + * + * @param int $themeId + * @return string + */ + protected function _getPreviewUrl($themeId) + { + return $this->getUrl('*/*/launch', array( + 'theme_id' => $themeId, + 'mode' => Mage_DesignEditor_Model_State::MODE_NAVIGATION + )); + } + + /** + * Get edit theme url for selected theme + * + * @param int $themeId + * @return string + */ + protected function _getEditUrl($themeId) + { + return $this->getUrl('*/*/launch', array( + 'theme_id' => $themeId, + 'mode' => Mage_DesignEditor_Model_State::MODE_DESIGN + )); + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Assigned.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Assigned.php new file mode 100644 index 0000000000000000000000000000000000000000..d1d7ca9dba2969efd0c7661fb1ce71a4312cab0a --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Assigned.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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Assigned theme list + */ +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Assigned + extends Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract +{ + /** + * Get list title + * + * @return string + */ + public function getTabTitle() + { + return $this->__('Themes Assigned to Storeviews'); + } + + /** + * Add theme buttons + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Assigned + */ + protected function _addThemeButtons($themeBlock) + { + parent::_addThemeButtons($themeBlock); + $this->_addPreviewButtonHtml($themeBlock)->_addAssignButtonHtml($themeBlock)->_addEditButtonHtml($themeBlock); + return $this; + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Available.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Available.php new file mode 100644 index 0000000000000000000000000000000000000000..55338a0b91f0c84b3248a729da4a2fee61468bfc --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Available.php @@ -0,0 +1,160 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Available theme list + * + * @method int getNextPage() + * @method Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available setNextPage(int $page) + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available + extends Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract +{ + /** + * @var Mage_Core_Model_Theme_Service + */ + protected $_serviceModel; + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Model_Layout $layout + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Url $urlBuilder + * @param Mage_Core_Model_Translate $translator + * @param Mage_Core_Model_Cache $cache + * @param Mage_Core_Model_Design_Package $designPackage + * @param Mage_Core_Model_Session $session + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_Theme_Service $serviceModel + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Model_Layout $layout, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Backend_Model_Url $urlBuilder, + Mage_Core_Model_Translate $translator, + Mage_Core_Model_Cache $cache, + Mage_Core_Model_Design_Package $designPackage, + Mage_Core_Model_Session $session, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_Theme_Service $serviceModel, + array $data = array() + ) { + $this->_serviceModel = $serviceModel; + + parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, $designPackage, + $session, $storeConfig, $frontController, $helperFactory, $data + ); + } + + /** + * Get service model + * + * @return Mage_Core_Model_Theme_Service + */ + protected function _getServiceModel() + { + return $this->_serviceModel; + } + + /** + * Get tab title + * + * @return string + */ + public function getTabTitle() + { + return $this->__('Available theme list'); + } + + /** + * Get next page url + * + * @return string + */ + public function getNextPageUrl() + { + return $this->getNextPage() <= $this->getCollection()->getLastPageNumber() + ? $this->getUrl('*/*/*', array('page' => $this->getNextPage())) + : ''; + } + + /** + * Get demo button + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available + */ + protected function _addDemoButtonHtml($themeBlock) + { + /** @var $demoButton Mage_Backend_Block_Widget_Button */ + $demoButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); + $demoButton->setData(array( + 'label' => $this->__('Theme Demo'), + 'class' => 'preview-demo', + 'data_attr' => array( + 'widget-button' => array( + 'event' => 'preview', + 'related' => 'body', + 'eventData' => array( + 'preview_url' => $this->_getPreviewUrl($themeBlock->getTheme()->getId()) + ) + ), + ) + )); + + $themeBlock->addButton($demoButton); + return $this; + } + + /** + * Add theme buttons + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract + */ + protected function _addThemeButtons($themeBlock) + { + parent::_addThemeButtons($themeBlock); + + $this->_addDemoButtonHtml($themeBlock)->_addAssignButtonHtml($themeBlock); + + if ($this->_getServiceModel()->isCustomizationsExist()) { + $this->_addEditButtonHtml($themeBlock); + } + + return $this; + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Unassigned.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Unassigned.php new file mode 100644 index 0000000000000000000000000000000000000000..a9ba65e88b620762afc6e2efecc5d9613304bbea --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/Unassigned.php @@ -0,0 +1,88 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Unassigned theme list + */ +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Unassigned + extends Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract +{ + /** + * Get list title + * + * @return string + */ + public function getTabTitle() + { + return $this->__('Unassigned Themes'); + } + + /** + * Get remove button + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return string + */ + protected function _addRemoveButtonHtml($themeBlock) + { + $themeId = $themeBlock->getTheme()->getId(); + /** @var $removeButton Mage_Backend_Block_Widget_Button */ + $removeButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); + + $removeButton->setData(array( + 'label' => $this->__('Remove Button'), + 'data_attr' => array( + 'widget-button' => array( + 'event' => 'delete', + 'related' => 'body', + 'eventData' => array( + 'url' => $this->getUrl('*/system_design_theme/delete/', array('id' => $themeId, 'back' => true)) + ) + ), + ), + 'class' => 'save delete-theme', + 'target' => '_blank' + )); + + $themeBlock->addButton($removeButton); + return $this; + } + + /** + * Add theme buttons + * + * @param Mage_DesignEditor_Block_Adminhtml_Theme $themeBlock + * @return Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract + */ + protected function _addThemeButtons($themeBlock) + { + parent::_addThemeButtons($themeBlock); + + $this->_addPreviewButtonHtml($themeBlock)->_addAssignButtonHtml($themeBlock)->_addEditButtonHtml($themeBlock) + ->_addRemoveButtonHtml($themeBlock); + return $this; + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/StoreView.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/StoreView.php new file mode 100644 index 0000000000000000000000000000000000000000..89e92002cd8574539d44d0d3c1284a4cda3c25bf --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/StoreView.php @@ -0,0 +1,232 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Theme selectors tabs container + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_StoreView extends Mage_Backend_Block_Template +{ + /** + * Website collection + * + * @var Mage_Core_Model_Resource_Website_Collection + */ + protected $_websiteCollection; + + /** + * @var Mage_Core_Model_Theme_Service + */ + protected $_serviceModel; + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Model_Layout $layout + * @param Mage_Core_Model_Event_Manager $eventManager + * @param Mage_Backend_Model_Url $urlBuilder + * @param Mage_Core_Model_Translate $translator + * @param Mage_Core_Model_Cache $cache + * @param Mage_Core_Model_Design_Package $designPackage + * @param Mage_Core_Model_Session $session + * @param Mage_Core_Model_Store_Config $storeConfig + * @param Mage_Core_Controller_Varien_Front $frontController + * @param Mage_Core_Model_Factory_Helper $helperFactory + * @param Mage_Core_Model_Resource_Website_Collection $websiteCollection + * @param Mage_Core_Model_Theme_Service $serviceModel + * @param array $data + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function __construct( + Mage_Core_Controller_Request_Http $request, + Mage_Core_Model_Layout $layout, + Mage_Core_Model_Event_Manager $eventManager, + Mage_Backend_Model_Url $urlBuilder, + Mage_Core_Model_Translate $translator, + Mage_Core_Model_Cache $cache, + Mage_Core_Model_Design_Package $designPackage, + Mage_Core_Model_Session $session, + Mage_Core_Model_Store_Config $storeConfig, + Mage_Core_Controller_Varien_Front $frontController, + Mage_Core_Model_Factory_Helper $helperFactory, + Mage_Core_Model_Resource_Website_Collection $websiteCollection, + Mage_Core_Model_Theme_Service $serviceModel, + array $data = array() + ) { + $this->_websiteCollection = $websiteCollection; + $this->_serviceModel = $serviceModel; + + parent::__construct($request, $layout, $eventManager, $urlBuilder, $translator, $cache, $designPackage, + $session, $storeConfig, $frontController, $helperFactory, $data + ); + } + + /** + * Get website collection with stores and store-views joined + * + * @return Mage_Core_Model_Resource_Website_Collection + */ + public function getCollection() + { + return $this->_websiteCollection->joinGroupAndStore(); + } + + /** + * Get website, stores and store-views + * + * @return Mage_Core_Model_Resource_Website_Collection + */ + public function getWebsiteStructure() + { + $structure = array(); + $website = null; + $store = null; + $storeView = null; + /** @var $row Mage_Core_Model_Website */ + foreach ($this->getCollection() as $row) { + $website = $row->getName(); + $store = $row->getGroupTitle(); + $storeView = $row->getStoreTitle(); + if (!isset($structure[$website])) { + $structure[$website] = array(); + } + if (!isset($structure[$website][$store])) { + $structure[$website][$store] = array(); + } + $structure[$website][$store][$storeView] = (int)$row->getStoreId(); + } + + return $structure; + } + + /** + * Get assign to multiple storeview button + * + * @return string + */ + public function getAssignSaveButtonHtml() + { + /** @var $assignSaveButton Mage_Backend_Block_Widget_Button */ + $assignSaveButton = $this->getLayout()->createBlock('Mage_Backend_Block_Widget_Button'); + $assignSaveButton->setData(array( + 'label' => $this->__('Done'), + 'class' => 'store-assign-done save', + 'data_attr' => array( + 'widget-button' => array( + 'event' => 'assign-save', + 'related' => 'body', + 'eventData' => array() + ), + ) + )); + + return $assignSaveButton->toHtml(); + } + + /** + * Get an array of stores grouped by theme customization it uses. + * + * The structure is the following: + * array( + * theme_id => array(store_id) + * ) + * + * @return array + */ + protected function _getStoresByThemes() + { + $assignedThemeIds = array_map( + function ($theme) { + return $theme->getId(); + }, + $this->_serviceModel->getAssignedThemeCustomizations() + ); + + $storesByThemes = array(); + foreach ($this->_serviceModel->getStoresByThemes() as $themeId => $stores) { + /* NOTE + We filter out themes not included to $assignedThemeIds array so we only get actually "assigned" + themes. So if theme is assigned to store or website and used by store-view only via config fall-back + mechanism it will not get to the resulting $storesByThemes array. + */ + if (!in_array($themeId, $assignedThemeIds)) { + continue; + } + + $storesByThemes[$themeId] = array(); + /** @var $store Mage_Core_Model_Store */ + foreach ($stores as $store) { + $storesByThemes[$themeId][] = (int)$store->getId(); + } + } + + return $storesByThemes; + } + + /** + * Get the flag if there are multiple store-views in Magento + * + * @return bool + */ + protected function _isMultipleStoreViewMode() + { + $isMultipleMode = false; + $tmpStore = null; + foreach ($this->_serviceModel->getStoresByThemes() as $stores) { + /** @var $store Mage_Core_Model_Store */ + foreach ($stores as $store) { + if ($tmpStore === null) { + $tmpStore = $store->getId(); + } elseif ($tmpStore != $store->getId()) { + $isMultipleMode = true; + break(2); + } + } + } + + return $isMultipleMode; + } + + /** + * Get options for JS widget vde.themeSelector + * + * @return string + */ + public function getOptionsJson() + { + $options = array(); + $options['storesByThemes'] = $this->_getStoresByThemes(); + $options['assignSaveUrl'] = $this->getUrl('*/*/assignThemeToStore'); + $options['afterAssignSaveUrl'] = $this->getUrl('*/*/launch'); + $options['isMultipleStoreViewMode'] = $this->_isMultipleStoreViewMode(); + + /** @var $helper Mage_Core_Helper_Data */ + $helper = $this->helper('Mage_Core_Helper_Data'); + + return $helper->jsonEncode($options); + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tab/Available.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tab/Available.php new file mode 100644 index 0000000000000000000000000000000000000000..72fbe5dc6219b84704d334539103a72c4eef9f1a --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tab/Available.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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Theme selector tab for available themes + */ +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_Tab_Available + extends Mage_Backend_Block_Template + implements Mage_Backend_Block_Widget_Tab_Interface +{ + /** + * Return tab content, available theme list + * + * @return string + */ + protected function _toHtml() + { + $this->getChildBlock('available.theme.list')->setTabId($this->getId()); + return $this->getChildHtml('available.theme.list'); + } + + /** + * Return Tab title + * + * @return string + */ + public function getTabTitle() + { + return $this->__('Available Themes'); + } + + /** + * Return Tab label + * + * @return string + */ + public function getTabLabel() + { + return $this->getTabTitle(); + } + + /** + * Can show tab in tabs + * + * @return boolean + */ + public function canShowTab() + { + return true; + } + + /** + * Tab is hidden + * + * @return boolean + */ + public function isHidden() + { + return false; + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Toolbar/Theme.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tab/Customizations.php similarity index 58% rename from app/code/core/Mage/DesignEditor/Block/Toolbar/Theme.php rename to app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tab/Customizations.php index 38cdc3244fa5a68ba2d338706e8bf07801d82147..c72861ba1bc8d26cba8dcc657b4dab893112ca21 100644 --- a/app/code/core/Mage/DesignEditor/Block/Toolbar/Theme.php +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tab/Customizations.php @@ -25,44 +25,58 @@ */ /** - * A theme selector for design editor frontend toolbar panel + * Theme selector tab for customized themes */ -class Mage_DesignEditor_Block_Toolbar_Theme extends Mage_Core_Block_Template +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_Tab_Customizations + extends Mage_Backend_Block_Template + implements Mage_Backend_Block_Widget_Tab_Interface { /** - * Html id of the theme select control + * Initialize tab block */ - const VDE_HTML_THEME_ID = 'visual_design_editor_theme'; + protected function _construct() + { + parent::_construct(); + $this->setActive(true); + } /** - * Get current theme + * Return Tab title * - * @return Mage_Core_Model_Theme + * @return string */ - public function getTheme() + public function getTabTitle() { - return Mage::registry('vde_theme'); + return $this->__('My Customizations'); } /** - * Returns whether theme selected in current store design + * Return Tab label * - * @param int|string $theme - * @return bool + * @return string */ - public function isThemeSelected($theme) + public function getTabLabel() { - $currentTheme = Mage::getDesign()->getDesignTheme()->getId(); - return $currentTheme == $theme; + return $this->getTabTitle(); } /** - * Returns html id of the theme select control + * Can show tab in tabs * - * @return string + * @return boolean + */ + public function canShowTab() + { + return true; + } + + /** + * Tab is hidden + * + * @return boolean */ - public function getSelectHtmlId() + public function isHidden() { - return self::VDE_HTML_THEME_ID; + return false; } } diff --git a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Launcher/Form/Container.php b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tabs.php similarity index 62% rename from app/code/core/Mage/DesignEditor/Block/Adminhtml/Launcher/Form/Container.php rename to app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tabs.php index ec75e5eecb1448fc034e14190678a6978cbe9cf0..9d794b8face509e40918e0b5ad4ad0377754e9da 100644 --- a/app/code/core/Mage/DesignEditor/Block/Adminhtml/Launcher/Form/Container.php +++ b/app/code/core/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/Tabs.php @@ -25,36 +25,29 @@ */ /** - * Design editor launcher form container + * Theme selectors tabs container */ -class Mage_DesignEditor_Block_Adminhtml_Launcher_Form_Container extends Mage_Adminhtml_Block_Widget_Form_Container +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_Tabs extends Mage_Backend_Block_Widget_Tabs { /** - * Prevent dynamic form block creation, use the layout declaration instead - * - * @var string - */ - protected $_mode = ''; - - /** - * Customize inherited buttons + * Initialize tab */ protected function _construct() { parent::_construct(); - $this->_removeButton('back'); - $this->_removeButton('reset'); - $this->_removeButton('delete'); - $this->_removeButton('save'); + $this->setId('theme_selector_tabs'); + $this->setDestElementId('theme_selector'); + $this->setTitle($this->__('Design & Theme Gallery')); + $this->setIsHoriz(true); } /** - * Retrieve appropriate text for the header element + * Add content container to template * * @return string */ - public function getHeaderText() + protected function _toHtml() { - return Mage::helper('Mage_DesignEditor_Helper_Data')->__('Visual Design Editor'); + return parent::_toHtml() . '<div id="' . $this->getDestElementId() . '"><div>'; } } diff --git a/app/code/core/Mage/DesignEditor/Block/Page/Html/Head.php b/app/code/core/Mage/DesignEditor/Block/Page/Html/Head.php new file mode 100644 index 0000000000000000000000000000000000000000..b824fd8f6013d9d28d0bb18dd0f23ba573d78a6a --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Block/Page/Html/Head.php @@ -0,0 +1,63 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Substitution for regular head block + */ +class Mage_DesignEditor_Block_Page_Html_Head extends Mage_Page_Block_Html_Head +{ + /** + * Block template + * + * @var string + */ + protected $_template = 'Mage_Page::html/head.phtml'; + + /** + * Render HTML for the added head items + * + * @return string + */ + public function getCssJsHtml() + { + /** @var $block Mage_DesignEditor_Block_Page_Html_Head_Vde */ + $block = $this->getLayout()->getBlock('vde_head'); + if ($block) { + // remove all current JS files + foreach (array_keys($this->_data['items']) as $itemKey) { + if (strpos($itemKey, 'js/') === 0) { + unset($this->_data['items'][$itemKey]); + } + } + + // add data from VDE head + $vdeItems = $block->getData('items'); + $this->_data['items'] = array_merge($this->_data['items'], $vdeItems); + } + + return parent::getCssJsHtml(); + } +} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_breadcrumbs_simple_product.php b/app/code/core/Mage/DesignEditor/Block/Page/Html/Head/Vde.php similarity index 59% rename from dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_breadcrumbs_simple_product.php rename to app/code/core/Mage/DesignEditor/Block/Page/Html/Head/Vde.php index 81bce301293f0f916f7a790f25316df82e52f3e5..eb1257944faf21fa6c556631d69270ef8d3dc7ec 100644 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_breadcrumbs_simple_product.php +++ b/app/code/core/Mage/DesignEditor/Block/Page/Html/Head/Vde.php @@ -18,29 +18,21 @@ * 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 + * @category Mage * @package Mage_DesignEditor - * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -?> -<?php -return array( - array( - 'label' => 'All Pages', - 'url' => 'http://localhost/index.php/design/editor/page/handle/default/', - ), - array( - 'label' => 'Catalog Category (Non-Anchor)', - 'url' => 'http://localhost/index.php/design/editor/page/handle/catalog_category_default/', - ), - array( - 'label' => 'Catalog Product View (Any)', - 'url' => 'http://localhost/index.php/design/editor/page/handle/catalog_product_view/', - ), - array( - 'label' => 'Catalog Product View (Simple)', - 'url' => '', - ), -); + +/** + * Invisible block to collect VDE header information + */ +class Mage_DesignEditor_Block_Page_Html_Head_Vde extends Mage_Page_Block_Html_Head +{ + /** + * No need to render output + * + * @var string + */ + protected $_template = null; +} diff --git a/app/code/core/Mage/DesignEditor/Block/Template.php b/app/code/core/Mage/DesignEditor/Block/Template.php index ded9a0d8cd38183a5a98f6db8cc220eb89fb8b43..3ae79e146dc7425116d7aaae8454612b8600ecc2 100644 --- a/app/code/core/Mage/DesignEditor/Block/Template.php +++ b/app/code/core/Mage/DesignEditor/Block/Template.php @@ -37,14 +37,11 @@ class Mage_DesignEditor_Block_Template extends Mage_Core_Block_Template { /** - * Check whether highlighting of elements is disabled or not + * Path to template file in theme. * - * @return bool + * @var string */ - public function isHighlightingDisabled() - { - return Mage::getSingleton('Mage_DesignEditor_Model_Session')->isHighlightingDisabled(); - } + protected $_template = 'wrapping.phtml'; /** * Get remove button for block/container wrapper diff --git a/app/code/core/Mage/DesignEditor/Block/Toolbar.php b/app/code/core/Mage/DesignEditor/Block/Toolbar.php deleted file mode 100644 index dac9b99bb74b27c51a4455fd5e3709aefb992f57..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/Block/Toolbar.php +++ /dev/null @@ -1,84 +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_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Frontend toolbar panel for the design editor controls - */ -class Mage_DesignEditor_Block_Toolbar extends Mage_Core_Block_Template -{ - /** - * Prevent rendering if the design editor is inactive - * - * @return string - */ - protected function _toHtml() - { - /** @var $session Mage_DesignEditor_Model_Session */ - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - if (!$session->isDesignEditorActive()) { - return ''; - } - return parent::_toHtml(); - } - - /** - * Returns messages for Visual Design Editor, clears list of session messages - * - * @return array - */ - public function getMessages() - { - return Mage::getSingleton('Mage_DesignEditor_Model_Session') - ->getMessages(true) - ->getItems(); - } - - /** - * Get configuration options for Visual Design Editor as JSON - * - * @return string - */ - public function getOptionsJson() - { - $options = array( - 'cookieHighlightingName' => Mage_DesignEditor_Model_Session::COOKIE_HIGHLIGHTING, - ); - /** @var $toolbarRowBlock Mage_DesignEditor_Block_Template */ - $toolbarRowBlock = $this->getChildBlock('design_editor_toolbar_row'); - - if ($toolbarRowBlock) { - /** @var $buttonsBlock Mage_DesignEditor_Block_Toolbar_Buttons */ - $buttonsBlock = $toolbarRowBlock->getChildBlock('design_editor_toolbar_buttons'); - if ($buttonsBlock) { - $options['compactLogUrl'] = $buttonsBlock->getCompactLogUrl(); - $options['viewLayoutUrl'] = $buttonsBlock->getViewLayoutUrl(); - $options['baseUrl'] = Mage::getBaseUrl(); - } - } - - return Mage::helper('Mage_Core_Helper_Data')->jsonEncode($options); - } -} diff --git a/app/code/core/Mage/DesignEditor/Block/Toolbar/Breadcrumbs.php b/app/code/core/Mage/DesignEditor/Block/Toolbar/Breadcrumbs.php deleted file mode 100644 index 7e6471a699124c41144f830ebacde18e7dc87274..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/Block/Toolbar/Breadcrumbs.php +++ /dev/null @@ -1,93 +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_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Breadcrumbs navigation for the current page - */ -class Mage_DesignEditor_Block_Toolbar_Breadcrumbs extends Mage_Core_Block_Template -{ - /** - * Retrieve breadcrumbs for the current page location - * - * Result format: - * array( - * array( - * 'label' => 'Some Page Handle', - * 'url' => http://localhost/index.php/design/editor/page/page_type/some_page_type/', - * ), - * // ... - * ) - * - * @return array - */ - public function getBreadcrumbs() - { - $layoutUpdate = $this->getLayout()->getUpdate(); - $result = array(); - $pageHandles = $this->_getPageHandlesPath(); - foreach ($pageHandles as $pageHandle) { - $result[] = array( - 'label' => $this->escapeHtml($layoutUpdate->getPageHandleLabel($pageHandle)), - 'url' => $this->getUrl('design/editor/page', array('handle' => $pageHandle)) - ); - } - /** @var $blockHead Mage_Page_Block_Html_Head */ - $blockHead = $this->getLayout()->getBlock('head'); - if ($blockHead && !$this->getOmitCurrentPage()) { - $result[] = array( - 'label' => $blockHead->getTitle(), - 'url' => '', - ); - } else if ($result) { - $result[count($result) - 1]['url'] = ''; - } - return $result; - } - - /** - * Return breadcrumbs path leading to the page handle selected - * - * @return array - */ - protected function _getPageHandlesPath() - { - $layoutUpdate = $this->getLayout()->getUpdate(); - $pageHandles = $layoutUpdate->getPageHandles(); - if (!$pageHandles) { - /** @var $controllerAction Mage_Core_Controller_Varien_Action */ - $controllerAction = Mage::app()->getFrontController()->getAction(); - if ($controllerAction) { - $pageHandles = array($controllerAction->getDefaultLayoutHandle()); - } - } - if (count($pageHandles) == 1) { - $pageHandle = reset($pageHandles); - $pageHandles = $layoutUpdate->getPageHandleParents($pageHandle, false); - $pageHandles[] = $pageHandle; - } - return $pageHandles; - } -} diff --git a/app/code/core/Mage/DesignEditor/Controller/Varien/Router/Standard.php b/app/code/core/Mage/DesignEditor/Controller/Varien/Router/Standard.php new file mode 100644 index 0000000000000000000000000000000000000000..b38bba36efab515736cb96614c81bbf9ab3c6531 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Controller/Varien/Router/Standard.php @@ -0,0 +1,185 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Controller_Varien_Router_Standard extends Mage_Core_Controller_Varien_Router_Base +{ + /** + * @var Mage_Backend_Model_Auth_Session + */ + protected $_backendSession; + + /** + * @var Mage_DesignEditor_Helper_Data + */ + protected $_helper; + + /** + * Routers that must not been matched + * + * @var array + */ + protected $_excludedRouters = array('admin', 'vde'); + + /** + * Layout factory + * + * @var Mage_DesignEditor_Model_State + */ + protected $_editorState; + + /** + * Configuration model + * + * @var Mage_Core_Model_Config + */ + protected $_configuration; + + /** + * @param Mage_Core_Controller_Varien_Action_Factory $controllerFactory + * @param Magento_ObjectManager $objectManager + * @param string $areaCode + * @param string $baseController + * @param Mage_Backend_Model_Auth_Session $backendSession + * @param Mage_DesignEditor_Helper_Data $helper + * @param Mage_DesignEditor_Model_State $editorState + * @param Mage_Core_Model_Config $configuration + */ + public function __construct( + Mage_Core_Controller_Varien_Action_Factory $controllerFactory, + Magento_ObjectManager $objectManager, + $areaCode, + $baseController, + Mage_Backend_Model_Auth_Session $backendSession, + Mage_DesignEditor_Helper_Data $helper, + Mage_DesignEditor_Model_State $editorState, + Mage_Core_Model_Config $configuration + ) { + parent::__construct($controllerFactory, $objectManager, $areaCode, $baseController); + + $this->_backendSession = $backendSession; + $this->_helper = $helper; + $this->_editorState = $editorState; + $this->_configuration = $configuration; + } + + /** + * Match provided request and if matched - return corresponding controller + * + * @param Mage_Core_Controller_Request_Http $request + * @return Mage_Core_Controller_Front_Action|null + */ + public function match(Mage_Core_Controller_Request_Http $request) + { + // if URL has VDE prefix + if (!$this->_isVdeRequest($request)) { + return null; + } + + // user must be logged in admin area + if (!$this->_backendSession->isLoggedIn()) { + return null; + } + + // override VDE configuration + $this->_overrideConfiguration(); + + // prepare request to imitate + $this->_prepareVdeRequest($request); + + // apply rewrites + $this->getFront()->applyRewrites($request); + + // match routers + $controller = null; + $routers = $this->_getMatchedRouters(); + /** @var $router Mage_Core_Controller_Varien_Router_Abstract */ + foreach ($routers as $router) { + /** @var $controller Mage_Core_Controller_Varien_ActionAbstract */ + $controller = $router->match($request); + if ($controller) { + $this->_editorState->update($this->_areaCode, $request, $controller); + break; + } + } + + return $controller; + } + + /** + * Check if URL has vde prefix + * + * @param Mage_Core_Controller_Request_Http $request + * @return bool + */ + protected function _isVdeRequest(Mage_Core_Controller_Request_Http $request) + { + $url = trim($request->getOriginalPathInfo(), '/'); + $vdeFrontName = $this->_helper->getFrontName(); + return $url == $vdeFrontName || strpos($url, $vdeFrontName . '/') === 0; + } + + /** + * Modify request path to imitate basic request + * + * @param Mage_Core_Controller_Request_Http $request + * @return Mage_DesignEditor_Controller_Varien_Router_Standard + */ + protected function _prepareVdeRequest(Mage_Core_Controller_Request_Http $request) + { + $vdeFrontName = $this->_helper->getFrontName(); + $noVdePath = substr($request->getPathInfo(), strlen($vdeFrontName) + 1) ?: '/'; + $request->setPathInfo($noVdePath); + return $this; + } + + /** + * Returns list of routers that must been tried to match + * + * @return array + */ + protected function _getMatchedRouters() + { + $routers = $this->getFront()->getRouters(); + foreach (array_keys($routers) as $name) { + if (in_array($name, $this->_excludedRouters)) { + unset($routers[$name]); + } + } + return $routers; + } + + /** + * Override frontend configuration with VDE area data + */ + protected function _overrideConfiguration() + { + $vdeNode = $this->_configuration->getNode(Mage_DesignEditor_Model_Area::AREA_VDE); + if ($vdeNode) { + $this->_configuration->getNode(Mage_Core_Model_App_Area::AREA_FRONTEND) + ->extend($vdeNode, true); + } + } +} diff --git a/app/code/core/Mage/DesignEditor/Helper/Data.php b/app/code/core/Mage/DesignEditor/Helper/Data.php index df1abfb354158ac2e6ccecd2577fc74f6805b142..e0e4ebc28245c89392728f8d879f729bbff4ad4b 100644 --- a/app/code/core/Mage/DesignEditor/Helper/Data.php +++ b/app/code/core/Mage/DesignEditor/Helper/Data.php @@ -29,4 +29,102 @@ */ class Mage_DesignEditor_Helper_Data extends Mage_Core_Helper_Abstract { + /**#@+ + * XML paths to VDE settings + */ + const XML_PATH_FRONT_NAME = 'vde/design_editor/frontName'; + const XML_PATH_DISABLED_CACHE_TYPES = 'vde/design_editor/disabledCacheTypes'; + const XML_PATH_BLOCK_WHITE_LIST = 'vde/design_editor/block/white_list'; + const XML_PATH_BLOCK_BLACK_LIST = 'vde/design_editor/block/black_list'; + const XML_PATH_CONTAINER_WHITE_LIST = 'vde/design_editor/container/white_list'; + /**#@-*/ + + /** + * @var Mage_Core_Model_Config + */ + protected $_configuration; + + /** + * @param Mage_Core_Model_Config $configuration + */ + public function __construct(Mage_Core_Model_Config $configuration) + { + $this->_configuration = $configuration; + } + + /** + * Get VDE front name prefix + * + * @return string + */ + public function getFrontName() + { + return (string)$this->_configuration->getNode(self::XML_PATH_FRONT_NAME); + } + + /** + * Get disabled cache types in VDE mode + * + * @return array + */ + public function getDisabledCacheTypes() + { + $cacheTypes = explode(',', $this->_configuration->getNode(self::XML_PATH_DISABLED_CACHE_TYPES)); + $resultCacheTypes = array(); + foreach ($cacheTypes as $cacheType) { + $resultCacheTypes[] = trim($cacheType); + } + + return $resultCacheTypes; + } + + /** + * Get list of configuration element values + * + * @param string $xmlPath + * @return array + */ + protected function _getElementsList($xmlPath) + { + $elements = array(); + $node = $this->_configuration->getNode($xmlPath); + if ($node) { + $data = $node->asArray(); + if (is_array($data)) { + $elements = array_values($data); + } + } + return $elements; + } + + /** + * Get list of allowed blocks + * + * @return array + */ + public function getBlockWhiteList() + { + return $this->_getElementsList(self::XML_PATH_BLOCK_WHITE_LIST); + } + + /** + * Get list of not allowed blocks + * + * @return array + */ + public function getBlockBlackList() + { + return $this->_getElementsList(self::XML_PATH_BLOCK_BLACK_LIST); + } + + /** + * Get list of allowed blocks + * + * @return array + */ + public function getContainerWhiteList() + { + return $this->_getElementsList(self::XML_PATH_CONTAINER_WHITE_LIST); + } + } diff --git a/app/code/core/Mage/DesignEditor/Exception.php b/app/code/core/Mage/DesignEditor/Model/Area.php similarity index 86% rename from app/code/core/Mage/DesignEditor/Exception.php rename to app/code/core/Mage/DesignEditor/Model/Area.php index a04e87bfb6289de9e85b86274ba078c7bd2ff0b2..64bbcb29c9f157fb0d162431c51feafb93927828 100644 --- a/app/code/core/Mage/DesignEditor/Exception.php +++ b/app/code/core/Mage/DesignEditor/Model/Area.php @@ -25,11 +25,12 @@ */ /** - * Magento Design Editor Exception - * - * @category Mage - * @package Mage_DesignEditor + * VDE area model */ -class Mage_DesignEditor_Exception extends Mage_Core_Exception +class Mage_DesignEditor_Model_Area { + /** + * VDE configuration area name + */ + const AREA_VDE = 'vde'; } diff --git a/app/code/core/Mage/DesignEditor/Model/Layout.php b/app/code/core/Mage/DesignEditor/Model/Layout.php index 7e2a68abba49c78e63d675a1b05e519e4f82fa4f..5d89dbc2af59bb939c74157b975f91fe3627b2e3 100644 --- a/app/code/core/Mage/DesignEditor/Model/Layout.php +++ b/app/code/core/Mage/DesignEditor/Model/Layout.php @@ -27,53 +27,145 @@ /** * Model for manipulating layout for purpose of design editor */ -class Mage_DesignEditor_Model_Layout +class Mage_DesignEditor_Model_Layout extends Mage_Core_Model_Layout { + /** + * Flag that keeps true in case when we need to sanitize layout blocks + * + * @var bool + */ + protected $_sanitationEnabled = false; + + /** + * Is block wrapping enabled flag + * + * @var bool + */ + protected $_wrappingEnabled = false; + /** * List of block types considered as "safe" * * "Safe" means that they will work with any template (if applicable) * - * @var array + * @var array|null */ - protected static $_blockWhiteList = array( - 'Mage_Core_Block_Template', - 'Mage_Page_Block_', - 'Mage_DesignEditor_Block_', - 'Mage_Checkout_Block_Onepage_', - 'Mage_Customer_Block_Account_Navigation', - 'Mage_Paypal_Block_Express_Review_Details', - 'Mage_Poll_Block_ActivePoll', - 'Mage_Sales_Block_Guest_Links', - 'Mage_Catalog_Block_Product_Compare_Sidebar', - 'Mage_Checkout_Block_Cart_Sidebar', - 'Mage_Wishlist_Block_Customer_Sidebar', - 'Mage_Reports_Block_Product_Viewed', - 'Mage_Reports_Block_Product_Compared', - 'Mage_Sales_Block_Reorder_Sidebar', - 'Mage_Paypal_Block_Express_Shortcut', - 'Mage_PaypalUk_Block_Express_Shortcut', - ); + protected $_blockWhiteList = null; /** * List of block types considered as "not safe" * - * @var array + * @var array|null */ - protected static $_blockBlackList = array( - 'Mage_Page_Block_Html_Pager', - ); + protected $_blockBlackList = null; /** * List of layout containers that potentially have "safe" blocks * + * @var array|null + */ + protected $_containerWhiteList = null; + + /** + * Block that wrap page elements when wrapping enabled + * + * @var Mage_DesignEditor_Block_Template + */ + protected $_wrapperBlock; + + /** + * @var Mage_DesignEditor_Helper_Data + */ + protected $_helper; + + /** + * List of JS events not allowed in VDE mode + * * @var array */ - protected static $_containerWhiteList = array( - 'root', 'head', 'after_body_start', 'header', 'footer', 'before_body_end', - 'top.links', 'top.menu', + protected $_jsEvents = array( + 'onclick', + 'onblur', + 'ondblclick', + 'onfocus', + 'onkeydown', + 'onkeypress', + 'onkeyup', + 'onmousedown', + 'onmousemove', + 'onmouseout', + 'onmouseover', + 'onmouseup' ); + /** + * @param Mage_Core_Model_BlockFactory $blockFactory + * @param Magento_Data_Structure $structure + * @param Mage_Core_Model_Layout_Argument_Processor $argumentProcessor + * @param Mage_Core_Model_Layout_Translator $translator + * @param Mage_Core_Model_Layout_ScheduledStructure $scheduledStructure + * @param Mage_DesignEditor_Block_Template $wrapperBlock + * @param Mage_DesignEditor_Helper_Data $helper + * @param string $area + */ + public function __construct( + Mage_Core_Model_BlockFactory $blockFactory, + Magento_Data_Structure $structure, + Mage_Core_Model_Layout_Argument_Processor $argumentProcessor, + Mage_Core_Model_Layout_Translator $translator, + Mage_Core_Model_Layout_ScheduledStructure $scheduledStructure, + Mage_DesignEditor_Block_Template $wrapperBlock, + Mage_DesignEditor_Helper_Data $helper, + $area = Mage_Core_Model_Design_Package::DEFAULT_AREA + ) { + $this->_wrapperBlock = $wrapperBlock; + $this->_helper = $helper; + parent::__construct($blockFactory, $structure, $argumentProcessor, $translator, $scheduledStructure, $area); + } + + /** + * Set sanitizing flag + * + * @param bool $flag + */ + public function setSanitizing($flag) + { + $this->_sanitationEnabled = $flag; + } + + /** + * Set wrapping flag + * + * @param bool $flag + */ + public function setWrapping($flag) + { + $this->_wrappingEnabled = $flag; + } + + /** + * Replace all inline JavaScript + * + * @return string + */ + public function getOutput() + { + $output = parent::getOutput(); + if (preg_match('/<body\s*[^>]*>.*<\/body>/is', $output, $body)) { + $oldBody = $body[0]; + // Replace script tags + $newBody = preg_replace('/<script\s*[^>]*>.*?<\/script>/is', '', $oldBody); + // Replace JS events + foreach ($this->_jsEvents as $event) { + $newBody = preg_replace("/(<[^>]+){$event}\\s*=\\s*(['\"])/is", "$1{$event}-vde=$2", $newBody); + } + // Replace href JS + $newBody = preg_replace('/(<[^>]+)href\s*=\s*([\'"])javascript:/is', '$1href-vde=$2', $newBody); + $output = str_replace($oldBody, $newBody, $output); + } + return $output; + } + /** * Replace all potentially dangerous blocks in layout into stubs * @@ -82,10 +174,10 @@ class Mage_DesignEditor_Model_Layout * * @param Varien_Simplexml_Element $node */ - public static function sanitizeLayout(Varien_Simplexml_Element $node) + public function sanitizeLayout(Varien_Simplexml_Element $node) { - self::_sanitizeLayout($node, 'reference'); // it is important to sanitize references first - self::_sanitizeLayout($node, 'block'); + $this->_sanitizeLayout($node, 'reference'); // it is important to sanitize references first + $this->_sanitizeLayout($node, 'block'); } /** @@ -96,20 +188,20 @@ class Mage_DesignEditor_Model_Layout * @param Varien_Simplexml_Element $node * @param string $nodeName */ - protected static function _sanitizeLayout(Varien_Simplexml_Element $node, $nodeName) + protected function _sanitizeLayout(Varien_Simplexml_Element $node, $nodeName) { if ($node->getName() == $nodeName) { switch ($nodeName) { case 'block': - self::_sanitizeBlock($node); + $this->_sanitizeBlock($node); break; case 'reference': - self::_sanitizeReference($node); + $this->_sanitizeReference($node); break; } } foreach ($node->children() as $child) { - self::_sanitizeLayout($child, $nodeName); + $this->_sanitizeLayout($child, $nodeName); } } @@ -120,18 +212,31 @@ class Mage_DesignEditor_Model_Layout * * @param Varien_Simplexml_Element $node */ - protected static function _sanitizeBlock(Varien_Simplexml_Element $node) + protected function _sanitizeBlock(Varien_Simplexml_Element $node) { $type = $node->getAttribute('type'); if (!$type) { return; // we encountered a node with name "block", however it doesn't actually define any block... } - if (self::_isParentSafe($node) || self::_isTypeSafe($type)) { + if ($this->_isParentSafe($node) || $this->_isTypeSafe($type)) { return; } - self::_overrideAttribute($node, 'template', 'Mage_DesignEditor::stub.phtml'); - self::_overrideAttribute($node, 'type', 'Mage_Core_Block_Template'); - self::_deleteNodes($node, 'action'); + $this->_overrideAttribute($node, 'template', 'Mage_DesignEditor::stub.phtml'); + $this->_overrideAttribute($node, 'type', 'Mage_Core_Block_Template'); + $this->_deleteNodes($node, 'action'); + } + + /** + * Get list of allowed containers + * + * @return array + */ + protected function _getContainerWhiteList() + { + if ($this->_containerWhiteList === null) { + $this->_containerWhiteList = $this->_helper->getContainerWhiteList(); + } + return $this->_containerWhiteList; } /** @@ -140,29 +245,55 @@ class Mage_DesignEditor_Model_Layout * @param Varien_Simplexml_Element $node * @return bool */ - protected static function _isParentSafe(Varien_Simplexml_Element $node) + protected function _isParentSafe(Varien_Simplexml_Element $node) { $parentAttributes = $node->getParent()->attributes(); if (isset($parentAttributes['name'])) { - if (!in_array($parentAttributes['name'], self::$_containerWhiteList)) { + if (!in_array($parentAttributes['name'], $this->_getContainerWhiteList())) { return false; } } return true; } + /** + * Get list of allowed blocks + * + * @return array + */ + protected function _getBlockWhiteList() + { + if ($this->_blockWhiteList === null) { + $this->_blockWhiteList = $this->_helper->getBlockWhiteList(); + } + return $this->_blockWhiteList; + } + + /** + * Get list of not allowed blocks + * + * @return array + */ + protected function _getBlockBlackList() + { + if ($this->_blockBlackList === null) { + $this->_blockBlackList = $this->_helper->getBlockBlackList(); + } + return $this->_blockBlackList; + } + /** * Check whether the specified type of block can be safely used in layout without required context * * @param string $type * @return bool */ - protected static function _isTypeSafe($type) + protected function _isTypeSafe($type) { - if (in_array($type, self::$_blockBlackList)) { + if (in_array($type, $this->_getBlockBlackList())) { return false; } - foreach (self::$_blockWhiteList as $safeType) { + foreach ($this->_getBlockWhiteList() as $safeType) { if ('_' !== substr($safeType, -1, 1)) { if ($type === $safeType) { return true; @@ -181,7 +312,7 @@ class Mage_DesignEditor_Model_Layout * @param string $name * @param string $value */ - protected static function _overrideAttribute(Varien_Simplexml_Element $node, $name, $value) + protected function _overrideAttribute(Varien_Simplexml_Element $node, $name, $value) { $attributes = $node->attributes(); if (isset($attributes[$name])) { @@ -197,7 +328,7 @@ class Mage_DesignEditor_Model_Layout * @param Varien_Simplexml_Element $node * @param string $name */ - protected static function _deleteNodes(Varien_Simplexml_Element $node, $name) + protected function _deleteNodes(Varien_Simplexml_Element $node, $name) { $count = count($node->{$name}); for ($i = $count; $i >= 0; $i--) { @@ -212,17 +343,91 @@ class Mage_DesignEditor_Model_Layout * * @param Varien_Simplexml_Element $node */ - protected static function _sanitizeReference(Varien_Simplexml_Element $node) + protected function _sanitizeReference(Varien_Simplexml_Element $node) { $attributes = $node->attributes(); $name = $attributes['name']; $result = $node->xpath("//block[@name='{$name}']") ?: array(); + /** @var $block Varien_Simplexml_Element */ foreach ($result as $block) { - $isTypeSafe = self::_isTypeSafe($block->getAttribute('type')); - if (!$isTypeSafe || !self::_isParentSafe($block)) { - self::_deleteNodes($node, 'action'); + $isTypeSafe = $this->_isTypeSafe($block->getAttribute('type')); + if (!$isTypeSafe || !$this->_isParentSafe($block)) { + $this->_deleteNodes($node, 'action'); } break; } } + + /** + * Create structure of elements from the loaded XML configuration + */ + public function generateElements() + { + if ($this->_sanitationEnabled) { + $this->sanitizeLayout($this->getNode()); + } + + parent::generateElements(); + } + + /** + * Gets HTML of block element + * + * @param string $name + * @return string + * @throws Magento_Exception + */ + protected function _renderBlock($name) + { + $result = parent::_renderBlock($name); + + if ($this->_wrappingEnabled) { + $block = $this->getBlock($name); + if (strpos(get_class($block), 'Mage_DesignEditor_Block_') !== 0 && $this->isManipulationAllowed($name)) { + $result = $this->_wrapElement($result, $name, false, true); + } + } + + return $result; + } + + /** + * Gets HTML of container element + * + * @param string $name + * @return string + */ + protected function _renderContainer($name) + { + $result = parent::_renderContainer($name); + + if ($this->_wrappingEnabled && $this->hasElement($name)) { + $result = $this->_wrapElement($result, $name, true); + } + + return $result; + } + + /** + * Wrap layout element + * + * @param string $elementContent + * @param string $elementName + * @param bool $isContainer + * @param bool $canManipulate + * @return string + */ + protected function _wrapElement($elementContent, $elementName, $isContainer = false, $canManipulate = false) + { + $elementId = 'vde_element_' . rtrim(strtr(base64_encode($elementName), '+/', '-_'), '='); + $this->_wrapperBlock->setData(array( + 'element_id' => $elementId, + 'element_title' => $this->getElementProperty($elementName, 'label') ?: $elementName, + 'element_html' => $elementContent, + 'is_manipulation_allowed' => $canManipulate, + 'is_container' => $isContainer, + 'element_name' => $elementName, + )); + return $this->_wrapperBlock->toHtml(); + } } diff --git a/app/code/core/Mage/DesignEditor/Model/Observer.php b/app/code/core/Mage/DesignEditor/Model/Observer.php index 7785f69632ba6b97741c8209b08a55b997600cde..6c60c15accf375893866a223bcba2c2f5bdb77dc 100644 --- a/app/code/core/Mage/DesignEditor/Model/Observer.php +++ b/app/code/core/Mage/DesignEditor/Model/Observer.php @@ -29,168 +29,36 @@ */ class Mage_DesignEditor_Model_Observer { - /**#@+ - * VDE specific layout update handles - */ - const HANDLE_PAGE = 'design_editor_page'; - const HANDLE_TOOLBAR = 'design_editor_toolbar'; - /**#@-*/ - - /** - * Renderer for wrapping html to be shown at frontend - * - * @var Mage_Core_Block_Template - */ - protected $_wrappingRenderer = null; - - /** - * Handler for 'controller_action_predispatch' event - */ - public function preDispatch() - { - /* Deactivate the design editor, if the admin session has been already expired */ - if (!$this->_getSession()->isLoggedIn()) { - $this->_getSession()->deactivateDesignEditor(); - } - - /* Deactivate the design editor, if the theme cannot be loaded */ - if ($this->_getSession()->isDesignEditorActive()) { - /** @var $theme Mage_Core_Model_Theme */ - $theme = Mage::getModel('Mage_Core_Model_Theme'); - try { - $theme->load($this->_getSession()->getThemeId()); - if (!$theme->getId()) { - Mage::throwException(Mage::helper('Mage_DesignEditor_Helper_Data')->__('The theme was not found.')); - } - Mage::register('vde_theme', $theme); - } catch (Exception $e) { - $this->_getSession()->deactivateDesignEditor(); - Mage::logException($e); - } - } - - /* Apply custom design to the current page */ - if ($this->_getSession()->isDesignEditorActive() && $theme->getThemePath()) { - Mage::getDesign()->setDesignTheme($theme->getThemePath()); - } - } - - /** - * Add the design editor toolbar to the current page - * - * @param Varien_Event_Observer $observer - */ - public function addToolbar(Varien_Event_Observer $observer) - { - if (!$this->_getSession()->isDesignEditorActive()) { - return; - } - - /** @var $update Mage_Core_Model_Layout_Merge */ - $update = $observer->getEvent()->getLayout()->getUpdate(); - $handles = $update->getHandles(); - $handle = reset($handles); - if ($handle && $update->getPageHandleType($handle) == Mage_Core_Model_Layout_Merge::TYPE_FRAGMENT) { - $update->addHandle(self::HANDLE_PAGE); - } - $update->addHandle(self::HANDLE_TOOLBAR); - } - /** - * Disable blocks HTML output caching + * @var Mage_Backend_Model_Session */ - public function disableBlocksOutputCaching() - { - if (!$this->_getSession()->isDesignEditorActive()) { - return; - } - Mage::app()->getCacheInstance()->banUse(Mage_Core_Block_Abstract::CACHE_GROUP); - } + protected $_backendSession; /** - * Set design_editor_active flag, which allows to load DesignEditor's CSS or JS scripts - * - * @param Varien_Event_Observer $observer + * @var Mage_Core_Model_Design_Package */ - public function setDesignEditorFlag(Varien_Event_Observer $observer) - { - if (!$this->_getSession()->isDesignEditorActive()) { - return; - } - /** @var $block Mage_Page_Block_Html_Head */ - $block = $observer->getEvent()->getLayout()->getBlock('head'); - if ($block) { - $block->setDesignEditorActive(true); - } - } + protected $_design; /** - * Retrieve session instance for the design editor - * - * @return Mage_DesignEditor_Model_Session + * @param Mage_Backend_Model_Session $backendSession + * @param Mage_Core_Model_Design_Package $design */ - protected function _getSession() - { - return Mage::getSingleton('Mage_DesignEditor_Model_Session'); + public function __construct( + Mage_Backend_Model_Session $backendSession, + Mage_Core_Model_Design_Package $design + ) { + $this->_backendSession = $backendSession; + $this->_design = $design; } /** - * Wrap each element of a page that is being rendered, with a block-level HTML-element to highlight it in VDE - * - * Subscriber to event 'core_layout_render_element' - * - * @param Varien_Event_Observer $observer + * Set specified design theme */ - public function wrapPageElement(Varien_Event_Observer $observer) + public function setTheme() { - if (!$this->_getSession()->isDesignEditorActive()) { - return; - } - - if (!$this->_wrappingRenderer) { - $this->_wrappingRenderer = Mage::getModel('Mage_DesignEditor_Block_Template', array('data' => array( - 'template' => 'wrapping.phtml' - ))); + $themeId = $this->_backendSession->getData('theme_id'); + if ($themeId !== null) { + $this->_design->setDesignTheme($themeId); } - - $event = $observer->getEvent(); - /** @var $layout Mage_Core_Model_Layout */ - $layout = $event->getData('layout'); - $elementName = $event->getData('element_name'); - /** @var $transport Varien_Object */ - $transport = $event->getData('transport'); - - $block = $layout->getBlock($elementName); - $isVde = ($block && 0 === strpos(get_class($block), 'Mage_DesignEditor_Block_')); - $manipulationAllowed = $layout->isManipulationAllowed($elementName) && !$isVde; - $isContainer = $layout->isContainer($elementName); - - if ($manipulationAllowed || $isContainer) { - $elementId = 'vde_element_' . rtrim(strtr(base64_encode($elementName), '+/', '-_'), '='); - $this->_wrappingRenderer->setData(array( - 'element_id' => $elementId, - 'element_title' => $layout->getElementProperty($elementName, 'label') ?: $elementName, - 'element_html' => $transport->getData('output'), - 'is_manipulation_allowed' => $manipulationAllowed, - 'is_container' => $isContainer, - 'element_name' => $elementName, - )); - $transport->setData('output', $this->_wrappingRenderer->toHtml()); - } - - /* Inject toolbar at the very beginning of the page */ - if ($elementName == 'after_body_start') { - $elementHtml = $transport->getData('output'); - $toolbarHtml = $layout->renderElement('design_editor_toolbar'); - $transport->setData('output', $toolbarHtml . $elementHtml); - } - } - - /** - * Deactivate the design editor - */ - public function adminSessionUserLogout() - { - $this->_getSession()->deactivateDesignEditor(); } } diff --git a/app/code/core/Mage/DesignEditor/Model/Session.php b/app/code/core/Mage/DesignEditor/Model/Session.php deleted file mode 100644 index 34bdea5dd62b47ad23fe1d78d552e35f126a3c80..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/Model/Session.php +++ /dev/null @@ -1,90 +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_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Design editor session model - * - * @method int getThemeId() - */ -class Mage_DesignEditor_Model_Session extends Mage_Backend_Model_Auth_Session -{ - /** - * Session key that indicates whether the design editor is active - */ - const SESSION_DESIGN_EDITOR_ACTIVE = 'DESIGN_EDITOR_ACTIVE'; - - /** - * Cookie name, which indicates whether highlighting of elements is enabled or not - */ - const COOKIE_HIGHLIGHTING = 'vde_highlighting'; - - /** - * Check whether the design editor is active for the current session or not - * - * @return bool - */ - public function isDesignEditorActive() - { - return $this->getData(self::SESSION_DESIGN_EDITOR_ACTIVE) && $this->isLoggedIn(); - } - - /** - * Activate the design editor for the current session - */ - public function activateDesignEditor() - { - if (!$this->getData(self::SESSION_DESIGN_EDITOR_ACTIVE) && $this->isLoggedIn()) { - $this->setData(self::SESSION_DESIGN_EDITOR_ACTIVE, 1); - Mage::dispatchEvent('design_editor_session_activate'); - } - } - - /** - * Deactivate the design editor for the current session - */ - public function deactivateDesignEditor() - { - /* - * isLoggedIn() is intentionally not taken into account to be able to trigger event when admin session expires - */ - if ($this->getData(self::SESSION_DESIGN_EDITOR_ACTIVE)) { - $this->unsetData(self::SESSION_DESIGN_EDITOR_ACTIVE); - Mage::getSingleton('Mage_Core_Model_Cookie')->delete(self::COOKIE_HIGHLIGHTING); - Mage::dispatchEvent('design_editor_session_deactivate'); - } - } - - /** - * Check whether highlighting of elements is disabled or not - * - * @return bool - */ - public function isHighlightingDisabled() - { - $highlighting = Mage::getSingleton('Mage_Core_Model_Cookie')->get(self::COOKIE_HIGHLIGHTING); - return 'off' == $highlighting; - } -} diff --git a/app/code/core/Mage/DesignEditor/Model/State.php b/app/code/core/Mage/DesignEditor/Model/State.php new file mode 100644 index 0000000000000000000000000000000000000000..595e2dc35b36d410e1d7aeec5e5122f2904459cc --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Model/State.php @@ -0,0 +1,169 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Design editor state model + */ +class Mage_DesignEditor_Model_State +{ + /**#@+ + * Name of layout classes that will be used as main layout + */ + const LAYOUT_DESIGN_CLASS_NAME = 'Mage_DesignEditor_Model_Layout'; + const LAYOUT_NAVIGATION_CLASS_NAME = 'Mage_Core_Model_Layout'; + /**#@-*/ + + /**#@+ + * Url model classes that will be used instead of Mage_Core_Model_Url in different vde modes + */ + const URL_MODEL_NAVIGATION_MODE_CLASS_NAME = 'Mage_DesignEditor_Model_Url_NavigationMode'; + const URL_MODEL_DESIGN_MODE_CLASS_NAME = 'Mage_DesignEditor_Model_Url_DesignMode'; + /**#@-*/ + + /**#@+ + * Import behaviors + */ + const MODE_DESIGN = 'design'; + const MODE_NAVIGATION = 'navigation'; + /**#@-*/ + + /** + * @var Mage_Backend_Model_Session + */ + protected $_backendSession; + + /** + * @var Mage_Core_Model_Layout_Factory + */ + protected $_layoutFactory; + + /** + * @var Mage_DesignEditor_Model_Url_Factory + */ + protected $_urlModelFactory; + + /** + * Application Cache Manager + * + * @var Mage_Core_Model_Cache + */ + protected $_cacheManager; + + /** + * @var Mage_DesignEditor_Helper_Data + */ + protected $_dataHelper; + + /** + * @param Mage_Backend_Model_Session $backendSession + * @param Mage_Core_Model_Layout_Factory $layoutFactory + * @param Mage_DesignEditor_Model_Url_Factory $urlModelFactory + * @param Mage_Core_Model_Cache $cacheManager + * @param Mage_DesignEditor_Helper_Data $dataHelper + */ + public function __construct( + Mage_Backend_Model_Session $backendSession, + Mage_Core_Model_Layout_Factory $layoutFactory, + Mage_DesignEditor_Model_Url_Factory $urlModelFactory, + Mage_Core_Model_Cache $cacheManager, + Mage_DesignEditor_Helper_Data $dataHelper + ) { + $this->_backendSession = $backendSession; + $this->_layoutFactory = $layoutFactory; + $this->_urlModelFactory = $urlModelFactory; + $this->_cacheManager = $cacheManager; + $this->_dataHelper = $dataHelper; + } + + public function update( + $areaCode, + Mage_Core_Controller_Request_Http $request, + Mage_Core_Controller_Varien_ActionAbstract $controller + ) { + $handle = $request->getParam('handle', ''); + if (empty($handle)) { + $mode = self::MODE_NAVIGATION; + + if (!$request->isAjax()) { + $this->_backendSession->setData('vde_current_handle', $controller->getFullActionName()); + $this->_backendSession->setData('vde_current_url', $request->getPathInfo()); + } + } else { + $mode = self::MODE_DESIGN; + } + + $this->_backendSession->setData('vde_current_mode', $mode); + $this->_injectUrlModel($mode); + $this->_injectLayout($mode, $areaCode); + $this->_disableCache(); + } + + /** + * Create layout instance that will be used as main layout for whole system + * + * @param string $mode + * @param string $areaCode + */ + protected function _injectLayout($mode, $areaCode) + { + switch ($mode) { + case self::MODE_DESIGN: + $this->_layoutFactory->createLayout(array('area' => $areaCode), self::LAYOUT_DESIGN_CLASS_NAME); + break; + case self::MODE_NAVIGATION: + default: + $this->_layoutFactory->createLayout(array('area' => $areaCode), self::LAYOUT_NAVIGATION_CLASS_NAME); + break; + } + } + + /** + * Create url model instance that will be used instead of Mage_Core_Model_Url in navigation mode + */ + protected function _injectUrlModel($mode) + { + switch ($mode) { + case self::MODE_DESIGN: + $this->_urlModelFactory->replaceClassName(self::URL_MODEL_DESIGN_MODE_CLASS_NAME); + break; + case self::MODE_NAVIGATION: + default: + $this->_urlModelFactory->replaceClassName(self::URL_MODEL_NAVIGATION_MODE_CLASS_NAME); + break; + } + } + + /** + * Disable some cache types in VDE mode + */ + protected function _disableCache() + { + foreach ($this->_dataHelper->getDisabledCacheTypes() as $cacheCode) { + $this->_cacheManager->banUse($cacheCode); + $this->_cacheManager->cleanType($cacheCode); + } + } +} diff --git a/app/code/core/Mage/DesignEditor/Model/Url/DesignMode.php b/app/code/core/Mage/DesignEditor/Model/Url/DesignMode.php new file mode 100644 index 0000000000000000000000000000000000000000..6d17e0af32ff2db57714844579a274393180686d --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Model/Url/DesignMode.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 Mage + * @package Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Design mode design editor url model + */ +class Mage_DesignEditor_Model_Url_DesignMode extends Mage_Core_Model_Url +{ + /** + * Retrieve route path + * + * @param array $routeParams + * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function getRoutePath($routeParams = array()) + { + return '#'; + } + + /** + * Retrieve route URL + * + * @param string $routePath + * @param array $routeParams + * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function getRouteUrl($routePath = null, $routeParams = null) + { + return '#'; + } + + /** + * Build url by requested path and parameters + * + * @param string|null $routePath + * @param array|null $routeParams + * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function getUrl($routePath = null, $routeParams = null) + { + return '#'; + } +} diff --git a/app/code/core/Mage/DesignEditor/Model/Url/Factory.php b/app/code/core/Mage/DesignEditor/Model/Url/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..68481873331fc24734c837a7949598cc548e02aa --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Model/Url/Factory.php @@ -0,0 +1,70 @@ +<?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_Core + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Model_Url_Factory implements Magento_ObjectManager_Factory +{ + /** + * Default url model class name + */ + const CLASS_NAME = 'Mage_Core_Model_Url'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * @param Magento_ObjectManager $objectManager + */ + public function __construct(Magento_ObjectManager $objectManager) + { + $this->_objectManager = $objectManager; + } + + /** + * Replace name of url model + * + * @param string $className + * @return Mage_DesignEditor_Model_Url_Factory + */ + public function replaceClassName($className) + { + $this->_objectManager->addAlias(self::CLASS_NAME, $className); + + return $this; + } + + /** + * Create url model new instance + * + * @param array $arguments + * @return Mage_Core_Model_Url + */ + public function createFromArray(array $arguments = array()) + { + return $this->_objectManager->create(self::CLASS_NAME, $arguments, false); + } +} diff --git a/app/code/core/Mage/DesignEditor/Model/Url/Handle.php b/app/code/core/Mage/DesignEditor/Model/Url/Handle.php new file mode 100644 index 0000000000000000000000000000000000000000..2c77262e9ae2011bef67f2584434f75d0677d3e6 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/Model/Url/Handle.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 Mage + * @package Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Design editor url model for navigation by page types (handles) + */ +class Mage_DesignEditor_Model_Url_Handle extends Mage_Core_Model_Url +{ + /** + * VDE helper + * + * @var Mage_DesignEditor_Helper_Data + */ + protected $_helper; + + /** + * Constructor + * + * @param Mage_DesignEditor_Helper_Data $helper + * @param array $data + */ + public function __construct(Mage_DesignEditor_Helper_Data $helper, array $data = array()) + { + $this->_helper = $helper; + parent::__construct($data); + } + + /** + * Retrieve route path + * + * @param array $routeParams + * @return string + */ + public function getRoutePath($routeParams = array()) + { + return $this->_helper->getFrontName() . '/' . parent::getRoutePath($routeParams); + } +} diff --git a/app/code/core/Mage/DesignEditor/Block/Toolbar/Buttons.php b/app/code/core/Mage/DesignEditor/Model/Url/NavigationMode.php similarity index 62% rename from app/code/core/Mage/DesignEditor/Block/Toolbar/Buttons.php rename to app/code/core/Mage/DesignEditor/Model/Url/NavigationMode.php index 79a3a0ac866b20822c555092d79441d96b00a9ee..247b66e41dff9f004a8b61d9941d72c653bfab6c 100644 --- a/app/code/core/Mage/DesignEditor/Block/Toolbar/Buttons.php +++ b/app/code/core/Mage/DesignEditor/Model/Url/NavigationMode.php @@ -25,37 +25,37 @@ */ /** - * Exit button control block + * Navigation mode design editor url model */ -class Mage_DesignEditor_Block_Toolbar_Buttons extends Mage_Core_Block_Template +class Mage_DesignEditor_Model_Url_NavigationMode extends Mage_Core_Model_Url { /** - * Get exit editor URL + * VDE helper * - * @return string + * @var Mage_DesignEditor_Helper_Data */ - public function getExitUrl() - { - return Mage::getSingleton('Mage_Backend_Model_Url')->getUrl('adminhtml/system_design_editor/exit'); - } + protected $_helper; /** - * Get "View Layout" button URL + * Constructor * - * @return string + * @param Mage_DesignEditor_Helper_Data $helper + * @param array $data */ - public function getViewLayoutUrl() + public function __construct(Mage_DesignEditor_Helper_Data $helper, array $data = array()) { - return $this->getUrl('design/editor/getLayoutUpdate'); + $this->_helper = $helper; + parent::__construct($data); } /** - * Get "Compact Log" button URL + * Retrieve route path * + * @param array $routeParams * @return string */ - public function getCompactLogUrl() + public function getRoutePath($routeParams = array()) { - return $this->getUrl('design/editor/compactHistory'); + return $this->_helper->getFrontName() . '/' . parent::getRoutePath($routeParams); } } diff --git a/app/code/core/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorController.php b/app/code/core/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorController.php index 7bddbeddffe86f646cdf02a415759a42e50728c5..fc7bcc425fede6856bb9c7aa517bf30765fc388b 100644 --- a/app/code/core/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorController.php +++ b/app/code/core/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorController.php @@ -34,15 +34,88 @@ class Mage_DesignEditor_Adminhtml_System_Design_EditorController extends Mage_Ad */ public function indexAction() { + $this->_doSelectionTheme('firstEntrance'); + } + + /** + * Display available theme list. Only when no customized themes + */ + public function firstEntranceAction() + { + $this->_doSelectionTheme('index'); + } + + /** + * Check whether is customized themes in database + * + * @return bool + */ + protected function _isFirstEntrance() + { + /** @var $themeService Mage_Core_Model_Theme_Service */ + $themeService = $this->_objectManager->get('Mage_Core_Model_Theme_Service'); + return !$themeService->isCustomizationsExist(); + } + + /** + * Load layout + * + * @param string $forwardAction + */ + protected function _doSelectionTheme($forwardAction) + { + if ($forwardAction == 'index' xor $this->_isFirstEntrance()) { + $this->_forward($forwardAction); + return; + } + try { $this->_title($this->__('System'))->_title($this->__('Design'))->_title($this->__('Editor')); $this->loadLayout(); $this->_setActiveMenu('Mage_DesignEditor::system_design_editor'); + if (!$this->_isFirstEntrance()) { + /** @var $themeService Mage_Core_Model_Theme_Service */ + $themeService = $this->_objectManager->get('Mage_Core_Model_Theme_Service'); + $this->getLayout()->getBlock('assigned.theme.list')->setCollection( + $themeService->getAssignedThemeCustomizations() + ); + $this->getLayout()->getBlock('unassigned.theme.list')->setCollection( + $themeService->getUnassignedThemeCustomizations() + ); + } $this->renderLayout(); } catch (Exception $e) { $this->_getSession()->addError($this->__('Cannot load list of themes.')); $this->_redirectUrl($this->_getRefererUrl()); - Mage::logException($e); + $this->_objectManager->get('Mage_Core_Model_Logger')->logException($e); + } + } + + /** + * Ajax loading available themes + */ + public function loadThemeListAction() + { + $page = $this->getRequest()->getParam('page', 1); + $pageSize = $this->getRequest() + ->getParam('page_size', Mage_Core_Model_Resource_Theme_Collection::DEFAULT_PAGE_SIZE); + + try { + $this->loadLayout(); + /** @var $service Mage_Core_Model_Theme_Service */ + $service = $this->_objectManager->get('Mage_Core_Model_Theme_Service'); + + /** @var $collection Mage_Core_Model_Resource_Theme_Collection */ + $collection = $service->getThemes($page, $pageSize); + $this->getLayout()->getBlock('available.theme.list')->setCollection($collection)->setNextPage(++$page); + $this->getResponse()->setBody($this->_objectManager->get('Mage_Core_Helper_Data')->jsonEncode( + array('content' => $this->getLayout()->getOutput()) + )); + } catch (Exception $e) { + $this->_objectManager->get('Mage_Core_Model_Logger')->logException($e); + $this->getResponse()->setBody($this->_objectManager->get('Mage_Core_Helper_Data')->jsonEncode( + array('error' => $this->_helper->__('Theme list can not be loaded'))) + ); } } @@ -51,54 +124,148 @@ class Mage_DesignEditor_Adminhtml_System_Design_EditorController extends Mage_Ad */ public function launchAction() { - /** @var $session Mage_DesignEditor_Model_Session */ - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - - $themeId = (int)$this->getRequest()->getParam('theme_id'); + $themeId = (int)$this->getRequest()->getParam('theme_id', $this->_getSession()->getData('theme_id')); + $mode = (string)$this->getRequest()->getParam('mode', Mage_DesignEditor_Model_State::MODE_DESIGN); /** @var $theme Mage_Core_Model_Theme */ - $theme = Mage::getModel('Mage_Core_Model_Theme'); + $theme = $this->_objectManager->create('Mage_Core_Model_Theme'); + try { $theme->load($themeId); if (!$theme->getId()) { - Mage::throwException($this->__('The theme was not found.')); + throw new InvalidArgumentException($this->__('The theme was not found.')); + } + + $this->_getSession()->setData('theme_id', $theme->getId()); + + /** @var $eventDispatcher Mage_Core_Model_Event_Manager */ + $eventDispatcher = $this->_objectManager->get('Mage_Core_Model_Event_Manager'); + $eventDispatcher->dispatch('design_editor_activate'); + + $customLayoutParams = array('area' => Mage_Core_Model_App_Area::AREA_FRONTEND); + + /** @var $customFrontLayout Mage_Core_Model_Layout_Merge */ + $customFrontLayout = $this->_objectManager->create('Mage_Core_Model_Layout_Merge', + array('arguments' => $customLayoutParams) + ); + $pageTypes = $customFrontLayout->getPageHandlesHierarchy(); + + $this->_title($this->__('System'))->_title($this->__('Design'))->_title($this->__('Editor')); + $this->loadLayout(); + + /** @var $toolbarBlock Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_Buttons */ + $toolbarBlock = $this->getLayout()->getBlock('design_editor_toolbar_buttons'); + $toolbarBlock->setThemeId($themeId) + ->setMode($mode); + + /** @var $hierarchyBlock Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy */ + $hierarchyBlock = $this->getLayout()->getBlock('design_editor_toolbar_handles_hierarchy'); + if ($hierarchyBlock) { + $hierarchyBlock->setHierarchy($pageTypes) + ->setMode($mode); + } + + /** @var $viewOptionsBlock Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_ViewOptions */ + $viewOptionsBlock = $this->getLayout()->getBlock('design_editor_toolbar_view_options'); + if ($viewOptionsBlock) { + $viewOptionsBlock->setMode($mode); } - $session->activateDesignEditor(); - $session->setThemeId($theme->getId()); + + /** @var $editorBlock Mage_DesignEditor_Block_Adminhtml_Editor_Container */ + $editorBlock = $this->getLayout()->getBlock('design_editor'); + if ($mode == Mage_DesignEditor_Model_State::MODE_NAVIGATION) { + $currentUrl = $this->_getCurrentUrl(); + } else { + $currentUrl = $this->_getCurrentHandleUrl(); + } + $editorBlock->setFrameUrl($currentUrl); + + $this->renderLayout(); } catch (Mage_Core_Exception $e) { - $this->_getSession()->addError($e->getMessage()); + $this->_getSession()->addException($e, $e->getMessage()); $this->_redirect('*/*/'); return; } catch (Exception $e) { - $this->_getSession()->addError($this->__('The theme was not found.')); - Mage::logException($e); + $this->_getSession()->addException($e, $this->__('The theme was not found.')); $this->_redirect('*/*/'); return; } + } - /* Redirect to the frontend */ - $query = array(Mage_Core_Model_Session_Abstract::SESSION_ID_QUERY_PARAM => urlencode($session->getSessionId())); - $storeId = (int)$this->getRequest()->getParam('store_id'); - if (!Mage::app()->isSingleStoreMode() && $storeId) { - $storeId = (int)$this->getRequest()->getParam('store_id'); - $params = array('_store' => $storeId); - $store = Mage::app()->getStore($storeId); - $query['___store'] = urlencode($store->getCode()); + /** + * Get current handle + * + * @return string + */ + protected function _getCurrentHandleUrl() + { + /** @var $vdeUrlModel Mage_DesignEditor_Model_Url_Handle */ + $vdeUrlModel = $this->_objectManager->get('Mage_DesignEditor_Model_Url_Handle'); + $handle = $this->_getSession()->getData('vde_current_handle'); + if (empty($handle)) { + $handle = 'default'; } - $params['_nosid'] = true; - $params['_query'] = $query; - $this->_redirectUrl(Mage::getUrl('/', $params)); + + return $vdeUrlModel->getUrl('design/page/type', array('handle' => $handle)); } /** - * Exit design editor + * Get current url + * + * @return string */ - public function exitAction() + protected function _getCurrentUrl() { - /** @var $session Mage_DesignEditor_Model_Session */ - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - $session->deactivateDesignEditor(); - $this->loadLayout(); - $this->renderLayout(); + /** @var $vdeUrlModel Mage_DesignEditor_Model_Url_NavigationMode */ + $vdeUrlModel = $this->_objectManager->get('Mage_DesignEditor_Model_Url_NavigationMode'); + $url = $this->_getSession()->getData('vde_current_url'); + if (empty($url)) { + $url = ''; + } + + return $vdeUrlModel->getUrl(ltrim($url, '/')); + } + + /** + * Assign theme to list of store views + */ + public function assignThemeToStoreAction() + { + $themeId = (int)$this->_getSession()->getData('theme_id'); + $stores = $this->getRequest()->getParam('stores'); + + /** @var $coreHelper Mage_Core_Helper_Data */ + $coreHelper = $this->_objectManager->get('Mage_Core_Helper_Data'); + + try { + if (!is_numeric($themeId)) { + throw new InvalidArgumentException('Theme id is not valid'); + } + + //TODO used until we find a way to convert array to JSON on JS side + $defaultStore = -1; + $emptyStores = -2; + if ($stores == $defaultStore) { + $ids = array_keys(Mage::app()->getStores()); + $stores = array(array_shift($ids)); + } elseif ($stores == $emptyStores) { + $stores = array(); + } + + if (!is_array($stores)) { + throw new InvalidArgumentException('Param "stores" is not valid'); + } + + /** @var $themeService Mage_Core_Model_Theme_Service */ + $themeService = $this->_objectManager->get('Mage_Core_Model_Theme_Service'); + $themeService->assignThemeToStores($themeId, $stores); + $message = $coreHelper->__('Theme successfully assigned'); + $this->getResponse()->setBody($coreHelper->jsonEncode(array('success' => $message))); + } catch (Exception $e) { + $this->_objectManager->get('Mage_Core_Model_Logger')->logException($e); + $this->getResponse()->setBody($coreHelper->jsonEncode( + array('error' => $this->_helper->__('Theme is not assigned'))) + ); + } } /** @@ -108,6 +275,52 @@ class Mage_DesignEditor_Adminhtml_System_Design_EditorController extends Mage_Ad */ protected function _isAllowed() { - return Mage::getSingleton('Mage_Core_Model_Authorization')->isAllowed('Mage_DesignEditor::editor'); + return $this->_objectManager->get('Mage_Core_Model_Authorization')->isAllowed('Mage_DesignEditor::editor'); + } + + /** + * Compact history + * + * @param array $historyData + * @return Mage_DesignEditor_Model_History + */ + protected function _compactHistory($historyData) + { + /** @var $historyModel Mage_DesignEditor_Model_History */ + $historyModel = Mage::getModel('Mage_DesignEditor_Model_History'); + /** @var $historyCompactModel Mage_DesignEditor_Model_History_Compact */ + $historyCompactModel = Mage::getModel('Mage_DesignEditor_Model_History_Compact'); + /** @var $collection Mage_DesignEditor_Model_Change_Collection */ + $collection = $historyModel->setChanges($historyData)->getChanges(); + $historyCompactModel->compact($collection); + return $historyModel; + } + + /** + * Get layout xml + */ + public function getLayoutUpdateAction() + { + $historyData = Mage::app()->getRequest()->getPost('historyData'); + if (!$historyData) { + $this->getResponse()->setBody(Mage::helper('Mage_Core_Helper_Data')->jsonEncode( + array(Mage_Core_Model_Message::ERROR => array($this->__('Invalid post data'))) + )); + return; + } + + try { + $historyModel = $this->_compactHistory($historyData); + /** @var $layoutRenderer Mage_DesignEditor_Model_History_Renderer_LayoutUpdate */ + $layoutRenderer = Mage::getModel('Mage_DesignEditor_Model_History_Renderer_LayoutUpdate'); + $layoutUpdate = $historyModel->output($layoutRenderer); + $this->getResponse()->setBody(Mage::helper('Mage_Core_Helper_Data')->jsonEncode(array( + Mage_Core_Model_Message::SUCCESS => array($layoutUpdate) + ))); + } catch (Mage_Core_Exception $e) { + $this->getResponse()->setBody(Mage::helper('Mage_Core_Helper_Data')->jsonEncode( + array(Mage_Core_Model_Message::ERROR => array($e->getMessage())) + )); + } } } diff --git a/app/code/core/Mage/DesignEditor/controllers/EditorController.php b/app/code/core/Mage/DesignEditor/controllers/EditorController.php deleted file mode 100644 index 21593685112ab9f70e9596c123847f1d50da3c8b..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/controllers/EditorController.php +++ /dev/null @@ -1,218 +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_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Controller that allows to display arbitrary page in design editor mode - */ -class Mage_DesignEditor_EditorController extends Mage_Core_Controller_Front_Action -{ - /** - * @var Mage_DesignEditor_Model_Session - */ - protected $_session; - - /** - * Variable to store full action name - * - * @var string - */ - protected $_fullActionName = ''; - - /** - * Enforce admin session with the active design editor mode - * - * @return Mage_DesignEditor_EditorController - */ - public function preDispatch() - { - parent::preDispatch(); - - $this->_session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - if (!$this->_session->isDesignEditorActive()) { - Mage::getSingleton('Mage_Core_Model_Session')->addError( - $this->__('Design editor is not initialized by administrator.') - ); - $this->norouteAction(); - $this->setFlag('', self::FLAG_NO_DISPATCH, true); - } - - return $this; - } - - /** - * Display an arbitrary page by specified page type - */ - public function pageAction() - { - try { - $handle = $this->getRequest()->getParam('handle'); - - // page type format - if (!$handle || !preg_match('/^[a-z][a-z\d]*(_[a-z][a-z\d]*)*$/i', $handle)) { - Mage::throwException($this->__('Invalid page handle specified.')); - } - - // whether such page type exists - if (!$this->getLayout()->getUpdate()->pageHandleExists($handle)) { - Mage::throwException( - $this->__("Specified page type or page fragment type doesn't exist: '{$handle}'.") - ); - } - - $this->_fullActionName = $handle; - $this->addPageLayoutHandles(); - $this->loadLayoutUpdates(); - $this->generateLayoutXml(); - Mage::getModel('Mage_DesignEditor_Model_Layout')->sanitizeLayout($this->getLayout()->getNode()); - $this->generateLayoutBlocks(); - - $blockHierarchy = $this->getLayout()->getBlock('design_editor_toolbar_handles_hierarchy'); - if ($blockHierarchy) { - $blockHierarchy->setSelectedHandle($handle); - } - $blockBreadcrumbs = $this->getLayout()->getBlock('design_editor_toolbar_breadcrumbs'); - if ($blockBreadcrumbs) { - $blockBreadcrumbs->setOmitCurrentPage(true); - } - - $this->renderLayout(); - } catch (Mage_Core_Exception $e) { - $this->getResponse()->setBody($e->getMessage()); - $this->getResponse()->setHeader('Content-Type', 'text/plain; charset=UTF-8')->setHttpResponseCode(503); - } - } - - /** - * Hack the "full action name" in order to render emulated layout - * - * @param string $delimiter - * @return string - */ - public function getFullActionName($delimiter = '_') - { - if ($this->_fullActionName) { - return $this->_fullActionName; - } - return parent::getFullActionName($delimiter); - } - - /** - * Sets new theme for viewed store and returns customer back to the previous address - */ - public function themeAction() - { - $backUrl = $this->_getRefererUrl(); - $themeId = $this->getRequest()->get('theme_id'); - /** @var $theme Mage_Core_Model_Theme */ - $theme = Mage::getModel('Mage_Core_Model_Theme'); - try { - $theme->load($themeId); - if (!$theme->getId()) { - Mage::throwException($this->__('The theme was not found.')); - } - $this->_session->setThemeId($themeId); - } catch (Mage_Core_Exception $e) { - $this->_session->addError($e->getMessage()); - } - $this->getResponse()->setRedirect($backUrl); - } - - /** - * Compact history - */ - public function compactHistoryAction() - { - $historyData = Mage::app()->getRequest()->getPost(); - - /** @var $helper Mage_Core_Helper_Data */ - $helper = Mage::helper('Mage_Core_Helper_Data'); - - if (!$historyData) { - $this->getResponse()->setBody($helper->jsonEncode( - array(Mage_Core_Model_Message::ERROR => array($this->__('Invalid post data'))) - )); - return; - } - - try { - $historyModel = $this->_compactHistory($historyData); - $response = array(Mage_Core_Model_Message::SUCCESS => array($historyModel->getChanges()->toArray())); - } catch (Mage_Core_Exception $e) { - $response = array( - Mage_Core_Model_Message::ERROR => array($e->getMessage()) - ); - } - - $this->getResponse()->setBody($helper->jsonEncode($response)); - } - - /** - * Compact history - * - * @param array $historyData - * @return Mage_DesignEditor_Model_History - */ - protected function _compactHistory($historyData) - { - /** @var $historyModel Mage_DesignEditor_Model_History */ - $historyModel = Mage::getModel('Mage_DesignEditor_Model_History'); - /** @var $historyCompactModel Mage_DesignEditor_Model_History_Compact */ - $historyCompactModel = Mage::getModel('Mage_DesignEditor_Model_History_Compact'); - /** @var $collection Mage_DesignEditor_Model_Change_Collection */ - $collection = $historyModel->setChanges($historyData)->getChanges(); - $historyCompactModel->compact($collection); - return $historyModel; - } - - /** - * Get layout xml - */ - public function getLayoutUpdateAction() - { - $historyData = Mage::app()->getRequest()->getPost(); - - if (!$historyData) { - $this->getResponse()->setBody(Mage::helper('Mage_Core_Helper_Data')->jsonEncode( - array(Mage_Core_Model_Message::ERROR => array($this->__('Invalid post data'))) - )); - return; - } - - try { - $historyModel = $this->_compactHistory($historyData); - /** @var $layoutRenderer Mage_DesignEditor_Model_History_Renderer_LayoutUpdate */ - $layoutRenderer = Mage::getModel('Mage_DesignEditor_Model_History_Renderer_LayoutUpdate'); - $layoutUpdate = $historyModel->output($layoutRenderer); - $this->getResponse()->setBody(Mage::helper('Mage_Core_Helper_Data')->jsonEncode(array( - Mage_Core_Model_Message::SUCCESS => array($layoutUpdate) - ))); - } catch (Mage_Core_Exception $e) { - $this->getResponse()->setBody(Mage::helper('Mage_Core_Helper_Data')->jsonEncode( - array(Mage_Core_Model_Message::ERROR => array($e->getMessage())) - )); - } - } -} diff --git a/app/code/core/Mage/DesignEditor/controllers/PageController.php b/app/code/core/Mage/DesignEditor/controllers/PageController.php new file mode 100644 index 0000000000000000000000000000000000000000..d74ab6158a2614cc5bd523af400386c66bf45849 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/controllers/PageController.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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Design Editor controller which performs page actions + */ +class Mage_DesignEditor_PageController extends Mage_Core_Controller_Front_Action +{ + /** + * Variable to store full action name + * + * @var string + */ + protected $_fullActionName = ''; + + /** + * Check backend session + */ + public function preDispatch() + { + parent::preDispatch(); + + // user must be logged in admin area + /** @var $backendSession Mage_Backend_Model_Auth_Session */ + $backendSession = $this->_objectManager->get('Mage_Backend_Model_Auth_Session'); + if (!$backendSession->isLoggedIn()) { + if ($this->getRequest()->getActionName() != 'noroute') { + $this->_forward('noroute'); + } + } + } + + /** + * Render specified page type layout handle + * + * @throws InvalidArgumentException + */ + public function typeAction() + { + try { + $handle = $this->getRequest()->getParam('handle'); + + // check page type format + if (!$handle || !preg_match('/^[a-z][a-z\d]*(_[a-z][a-z\d]*)*$/i', $handle)) { + throw new InvalidArgumentException($this->__('Invalid page handle specified.')); + } + + /** @var $layout Mage_DesignEditor_Model_Layout */ + $layout = $this->getLayout(); + $layoutClassName = Mage_DesignEditor_Model_State::LAYOUT_DESIGN_CLASS_NAME; + if (!($layout instanceof $layoutClassName)) { + throw new InvalidArgumentException($this->__('Incorrect Design Editor layout.')); + } + + // whether such page type exists + if (!$this->getLayout()->getUpdate()->pageHandleExists($handle)) { + throw new InvalidArgumentException( + $this->__('Specified page type or page fragment type doesn\'t exist: "%s".', $handle) + ); + } + + // required layout handle + $this->_fullActionName = $handle; + + // set sanitize and wrapping flags + $layout->setSanitizing(true); + $layout->setWrapping(true); + + $this->loadLayout(array( + 'default', + parent::getFullActionName() // current action layout handle + )); + $this->renderLayout(); + } catch (Exception $e) { + $this->getResponse()->setBody($e->getMessage()); + $this->getResponse()->setHeader('Content-Type', 'text/plain; charset=UTF-8')->setHttpResponseCode(503); + } + } + + /** + * Replace full action name to render emulated layout + * + * @param string $delimiter + * @return string + */ + public function getFullActionName($delimiter = '_') + { + if ($this->_fullActionName) { + return $this->_fullActionName; + } + return parent::getFullActionName($delimiter); + } +} diff --git a/app/code/core/Mage/DesignEditor/etc/config.xml b/app/code/core/Mage/DesignEditor/etc/config.xml index 2efcf43d56464b368dc72be55f62cd8ee68e5e4a..40c8b10c110a6898f24d6c2ab4917a27872fdc73 100644 --- a/app/code/core/Mage/DesignEditor/etc/config.xml +++ b/app/code/core/Mage/DesignEditor/etc/config.xml @@ -37,6 +37,17 @@ </depends> </Mage_DesignEditor> </modules> + <default> + <web> + <routers> + <vde> + <area>frontend</area> + <class>Mage_DesignEditor_Controller_Varien_Router_Standard</class> + <base_controller>Mage_Core_Controller_Varien_Action</base_controller> + </vde> + </routers> + </web> + </default> <frontend> <layout> <updates> @@ -54,49 +65,6 @@ </args> </designeditor> </routers> - <events> - <controller_action_predispatch> - <observers> - <designeditor> - <class>Mage_DesignEditor_Model_Observer</class> - <method>preDispatch</method> - </designeditor> - </observers> - </controller_action_predispatch> - <controller_action_layout_generate_blocks_before> - <observers> - <designeditor> - <class>Mage_DesignEditor_Model_Observer</class> - <method>disableBlocksOutputCaching</method> - </designeditor> - </observers> - </controller_action_layout_generate_blocks_before> - <controller_action_layout_load_before> - <observers> - <designeditor> - <class>Mage_DesignEditor_Model_Observer</class> - <method>addToolbar</method> - </designeditor> - </observers> - </controller_action_layout_load_before> - <controller_action_layout_generate_blocks_after> - <observers> - <designeditor> - <class>Mage_DesignEditor_Model_Observer</class> - <method>setDesignEditorFlag</method> - </designeditor> - </observers> - </controller_action_layout_generate_blocks_after> - <core_layout_render_element> - <observers> - <designeditor> - <type>singleton</type> - <class>Mage_DesignEditor_Model_Observer</class> - <method>wrapPageElement</method> - </designeditor> - </observers> - </core_layout_render_element> - </events> </frontend> <adminhtml> <layout> @@ -106,17 +74,58 @@ </designeditor> </updates> </layout> + </adminhtml> + <vde> + <design_editor> + <frontName>vde</frontName> + <disabledCacheTypes>BLOCK_HTML,LAYOUT_GENERAL_CACHE_TAG,FPC</disabledCacheTypes> + <block> + <white_list> + <mage_core_block_template>Mage_Core_Block_Template</mage_core_block_template> + <mage_page_block>Mage_Page_Block_</mage_page_block> + <mage_designeditor_block>Mage_DesignEditor_Block_</mage_designeditor_block> + <mage_checkout_block_onepage>Mage_Checkout_Block_Onepage_</mage_checkout_block_onepage> + <mage_customer_block_account_navigation>Mage_Customer_Block_Account_Navigation</mage_customer_block_account_navigation> + <mage_paypal_block_express_review_details>Mage_Paypal_Block_Express_Review_Details</mage_paypal_block_express_review_details> + <mage_poll_block_activepoll>Mage_Poll_Block_ActivePoll</mage_poll_block_activepoll> + <mage_sales_block_guest_links>Mage_Sales_Block_Guest_Links</mage_sales_block_guest_links> + <mage_catalog_block_product_compare_sidebar>Mage_Catalog_Block_Product_Compare_Sidebar</mage_catalog_block_product_compare_sidebar> + <mage_checkout_block_cart_sidebar>Mage_Checkout_Block_Cart_Sidebar</mage_checkout_block_cart_sidebar> + <mage_wishlist_block_customer_sidebar>Mage_Wishlist_Block_Customer_Sidebar</mage_wishlist_block_customer_sidebar> + <mage_reports_block_product_viewed>Mage_Reports_Block_Product_Viewed</mage_reports_block_product_viewed> + <mage_reports_block_product_compared>Mage_Reports_Block_Product_Compared</mage_reports_block_product_compared> + <mage_sales_block_reorder_sidebar>Mage_Sales_Block_Reorder_Sidebar</mage_sales_block_reorder_sidebar> + <mage_paypal_block_express_shortcut>Mage_Paypal_Block_Express_Shortcut</mage_paypal_block_express_shortcut> + <mage_paypaluk_block_express_shortcut>Mage_PaypalUk_Block_Express_Shortcut</mage_paypaluk_block_express_shortcut> + </white_list> + <black_list> + <mage_page_block_html_pager>Mage_Page_Block_Html_Pager</mage_page_block_html_pager> + </black_list> + </block> + <container> + <white_list> + <root>root</root> + <head>head</head> + <after_body_start>after_body_start</after_body_start> + <header>header</header> + <footer>footer</footer> + <before_body_end>before_body_end</before_body_end> + <top_links>top.links</top_links> + <top_menu>top.menu</top_menu> + </white_list> + </container> + </design_editor> <events> - <backend_auth_user_logout> + <controller_action_predispatch> <observers> - <designeditor> + <design_editor_theme> <class>Mage_DesignEditor_Model_Observer</class> - <method>adminSessionUserLogout</method> - </designeditor> + <method>setTheme</method> + </design_editor_theme> </observers> - </backend_auth_user_logout> + </controller_action_predispatch> </events> - </adminhtml> + </vde> <admin> <routers> <adminhtml> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/css/styles.css b/app/code/core/Mage/DesignEditor/view/adminhtml/css/styles.css similarity index 82% rename from app/code/core/Mage/DesignEditor/view/frontend/css/styles.css rename to app/code/core/Mage/DesignEditor/view/adminhtml/css/styles.css index 25298d4e9f87b97d6e7ea0a17365320cfd1c8aa6..2d1032ebf0b41e05eecebff0f75762990e2e441c 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/css/styles.css +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/css/styles.css @@ -22,6 +22,97 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ +.theme-element { + position: relative; + height:351px; + width:351px; +} + +.theme-front { + position: absolute; +} + +.theme-back { + background-color: #424242; + display: block; + position: absolute; + width: 100%; + height: 100%; + + opacity: 0; + + transition: opacity .25s ease-in-out; + -moz-transition: opacity .25s ease-in-out; + -webkit-transition: opacity .25s ease-in-out; +} + +.theme-title { + color: white; + font-size: 20px; +} + +.theme-back:hover { + opacity: 1; +} + +.infinite_scroll { + height:100%; + width: 900px; + position: relative; +} + +div.theme-preview-actions .theme-preview-about { + float: left; + display: none; +} +div.theme-preview-actions .btn-apply-theme { + float: right; +} +div.theme-preview-actions .theme-preview-window { + margin: 0 10px; + display: none; +} +div.theme-preview-actions .theme-preview-back, +span.back-to-selected-theme { + float: left; + cursor: pointer; + margin: 0 20px 0 0; + width: 28px; + height: 29px; + background: url(../images/theme-preview-back.png) 0 0 no-repeat; +} + +.theme-element-customizations{ + width:351px; +} + +.theme-assigned-to-storeview .theme-title{ + color: black; +} +.theme-front-customizations{ + position: relative; + height:351px; + width:351px; +} +.theme-front-customizations .theme-buttons{ + padding: 30px; + margin-top: -100px; + display: block; + position: absolute; + z-index: 1; + background-color: #424242; +} + +.theme-loader { + display: none; + position: relative; + float: left; +} + +.theme-container { + float: left; +} + #vde_toolbar { position: fixed; margin-top: -54pt; @@ -32,11 +123,8 @@ text-align:left; box-shadow:0 0 4pt 1pt #cbcbcb; } -body { - margin-top: 54pt; -} .vde_breadcrumbs, #vde_toolbar_row { - padding:0 3em; + padding:0 0 0 1em; height:26pt; line-height:26pt; vertical-align:middle; @@ -51,7 +139,6 @@ body { border-top:1pt solid #dddcd8; border-bottom:1pt solid #dddcd8; position:relative; - z-index:100; } #vde_toolbar_row .vde_toolbar_cell { @@ -300,3 +387,8 @@ body { .vde_element_remove { display: none; } +.vde_container_frame { + border: none; + margin-top: 0px; + width: 100%; +} diff --git a/app/code/core/Mage/DesignEditor/view/frontend/page.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/editor.phtml similarity index 69% rename from app/code/core/Mage/DesignEditor/view/frontend/page.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/editor.phtml index a8ef2dbc5088c94eb51ccc8dfd3300da5b13da46..38f3617c1f300905044c59a70eb75c4ab4c18331 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/page.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/editor.phtml @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category design - * @package Mage_DesignEditor + * @package default_default * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ @@ -29,12 +29,10 @@ <head> <?php echo $this->getChildHtml('head') ?> </head> -<body> -<?php echo $this->getChildHtml('after_body_start') ?> -<?php foreach ($this->getChildNames() as $name): ?> - <?php if ($name != 'head' && $name != 'after_body_start'): ?> - <?php echo $this->getChildHtml($name) ?> - <?php endif; ?> -<?php endforeach; ?> +<body id="html-body"<?php echo $this->getBodyClass() ? ' class="' . $this->getBodyClass() . '"' : ''; ?>> + <?php echo $this->getChildHtml('content') ?> + <div id="loading-mask" style="display:none"> + <p class="loader" id="loading_mask_loader"><img src="<?php echo $this->getViewFileUrl('images/ajax-loader-tr.gif') ?>" alt="<?php echo Mage::helper('Mage_DesignEditor_Helper_Data')->__('Loading...') ?>"/><br/><?php echo Mage::helper('Mage_DesignEditor_Helper_Data')->__('Please wait...') ?></p> + </div> </body> </html> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/toolbar.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/container.phtml similarity index 71% rename from app/code/core/Mage/DesignEditor/view/frontend/toolbar.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/editor/container.phtml index 1c91ab44d0f5673f563ff16d3b5e94ae84a47c42..46ef16dd1378356c9e533f3720c430a605913621 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/toolbar.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/container.phtml @@ -24,19 +24,15 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php /** @var $this Mage_DesignEditor_Block_Toolbar */ ?> -<div id="vde_toolbar"> - <?php $messages = $this->getMessages(); ?> - <?php foreach ($messages as $message): ?> - <p class="item-msg <?php echo $message->getType() ?>"><?php echo $this->escapeHtml($message->getCode()) ?></p> - <?php endforeach; ?> - <?php echo $this->getChildHtml(); ?> -</div> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Editor_Container */ ?> +<?php echo $this->getChildHtml('design_editor_toolbar'); ?> +<?php echo $this->getChildHtml('theme.selector.storeview'); ?> +<iframe name="vde_container_frame" id="vde_container_frame" class="vde_container_frame" src="<?php echo $this->getFrameUrl(); ?>"></iframe> <script type="text/javascript"> (function ($) { $( document ).ready(function( ){ - $( window ).vde_page(<?php echo $this->getOptionsJson(); ?>); + $('iframe.vde_container_frame').iframeAutoHeight({minHeight: 240}); }); })(jQuery); </script> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/row.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar.phtml similarity index 85% rename from app/code/core/Mage/DesignEditor/view/frontend/toolbar/row.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar.phtml index 5d3ae45043d925119d6bc1eca6f945e72be9e204..674a1df76057a38ea5e35653ecbe21f1b7848782 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/row.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar.phtml @@ -26,8 +26,12 @@ ?> <?php /** @var $this Mage_Core_Block_Template */ ?> <div id="vde_toolbar_row"> - <?php $layout = $this->getLayout(); ?> - <?php foreach ($this->getChildNames() as $name): ?> - <?php echo $layout->renderElement($name) ?> - <?php endforeach; ?> + <?php echo $this->getChildHtml(); ?> </div> +<script type="text/javascript"> +(function ($) { + $(document).ready(function( ){ + $(window).vde_page(); + }); +})(jQuery); +</script> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/buttons.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/buttons.phtml similarity index 50% rename from app/code/core/Mage/DesignEditor/view/frontend/toolbar/buttons.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/buttons.phtml index 53f9b08b368235f71c3a54dbf592d1777ffba906..c2e0243df6889a23d2b81e9e2f351c2ad451754c 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/buttons.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/buttons.phtml @@ -24,16 +24,26 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php /** @var $this Mage_DesignEditor_Block_Toolbar_Buttons */ ?> -<div id="vde_toolbar_buttons"> - <a href="<?php echo $this->getViewLayoutUrl(); ?>" title="<?php echo $this->__('View Layout'); ?>" class="vde_button view-layout"> - <?php echo $this->__('View Layout'); ?> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_Buttons */ ?> +<?php if ($this->isNavigationMode()) : + $modeName = $this->__('Design Mode'); + $modeUrl = $this->getDesignModeUrl(); +else: + $modeName = $this->__('Navigation Mode'); + $modeUrl = $this->getNavigationModeUrl(); +endif; ?> +<div id="vde_toolbar_buttons" <?php echo $this->getUiId()?>> + <?php echo $this->getAssignButtonHtml(); ?> + <a href="<?php echo $modeUrl; ?>" title="<?php echo $modeName; ?>" class="vde_button switch-mode"> + <?php echo $modeName; ?> </a> - <a href="<?php echo $this->getCompactLogUrl(); ?>" title="<?php echo $this->__('Compact Log'); ?>" class="vde_button compact-log"> - <?php echo $this->__('Compact Log'); ?> + <?php if ($this->isDesignMode()) : ?> + <a href="<?php echo $this->getViewLayoutUrl(); ?>" title="<?php echo $this->__('View Layout'); ?>" + class="vde_button view-layout"> + <?php echo $this->__('View Layout'); ?> + </a> + <?php endif; ?> + <a href="<?php echo $this->getBackUrl(); ?>" title="<?php echo $this->__('Back'); ?>" class="vde_button"> + <?php echo $this->__('Back'); ?> </a> - <a href="<?php echo $this->getExitUrl(); ?>" title="<?php echo $this->__('Quit'); ?>" class="vde_button"> - <?php echo $this->__('Quit'); ?> - </a> - <div style="clear:both;"></div> </div> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/handles_hierarchy.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/handles_hierarchy.phtml similarity index 57% rename from app/code/core/Mage/DesignEditor/view/frontend/toolbar/handles_hierarchy.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/handles_hierarchy.phtml index cc8dec606a76e2ca7b5e1b99fe701f3cf0cb75cf..c9b2617757a027da82477c3154b0fc7a86aafc89 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/handles_hierarchy.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/handles_hierarchy.phtml @@ -24,13 +24,16 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php /** @var $this Mage_DesignEditor_Block_Toolbar_HandlesHierarchy */ ?> -<div id="vde_handles_hierarchy" class="vde_toolbar_cell"> - <div class="vde_toolbar_cell_title"> - <?php echo $this->__('Page:'); ?> - <span class="vde_toolbar_cell_value"><?php echo $this->getSelectedHandleLabel(); ?></span> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy */ ?> +<?php if ($this->isDesignMode()) : ?> + <div id="vde_handles_hierarchy" class="vde_toolbar_cell" <?php echo $this->getUiId()?>> + <div class="vde_toolbar_cell_title"> + <?php echo $this->__('Page:'); ?> + <span class="vde_toolbar_cell_value"><?php echo $this->getSelectedHandleLabel(); ?></span> + </div> + <div class="vde_toolbar_cell_content"> + <div id="vde_handles_tree"<?php if ($this->getSelectedHandle()) : ?> + data-selected="li[rel='<?php echo $this->getSelectedHandle(); ?>']"<?php endif; ?>><?php echo $this->renderHierarchy(); ?></div> + </div> </div> - <div class="vde_toolbar_cell_content"> - <div id="vde_handles_tree"<?php if ($this->getSelectedHandle()) : ?> data-selected="li[rel='<?php echo $this->getSelectedHandle(); ?>']"<?php endif; ?>><?php echo $this->renderHierarchy(); ?></div> - </div> -</div> +<?php endif; ?> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/highlighting.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/view_options.phtml similarity index 74% rename from app/code/core/Mage/DesignEditor/view/frontend/toolbar/highlighting.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/view_options.phtml index 9279ed6cc7f54de6554c01c1660694626d2d8594..6caa3fc3195a367db20faae3dffe8e561de10ed9 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/highlighting.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/editor/toolbar/view_options.phtml @@ -24,14 +24,14 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php /** @var $this Mage_DesignEditor_Block_Template */ ?> -<div class="vde_toolbar_cell"> - <div class="vde_toolbar_cell_title"><?php echo $this->__('View Options'); ?></div> - <div class="vde_toolbar_cell_content"> - <div id="vde_highlighting" class="vde_cell_list_item<?php if (!$this->isHighlightingDisabled()) echo ' checked'; ?>"> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_ViewOptions */ ?> +<?php if ($this->isDesignMode()) : ?> + <div id="vde_view_options" class="vde_toolbar_cell" <?php echo $this->getUiId()?>> + <div class="vde_toolbar_cell_title"><?php echo $this->__('View Options'); ?></div> + <div class="vde_toolbar_cell_content"> + <div id="vde_highlighting" class="vde_cell_list_item checked"> <?php echo $this->__('Highlight Elements'); ?> </div> + </div> </div> -</div> - - +<?php endif; ?> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/arrow_down.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/arrow_down.png new file mode 100644 index 0000000000000000000000000000000000000000..74b9101acd79117141a3a7bd19f723f553b82590 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/arrow_down.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/arrow_up.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/arrow_up.png new file mode 100644 index 0000000000000000000000000000000000000000..002eeb9762fa6b0018ec6dc2b03f693de10ba790 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/arrow_up.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/block.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/block.png new file mode 100644 index 0000000000000000000000000000000000000000..14fa330a3322b8cb627fdf00967543f7bca8b6e3 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/block.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/button.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/button.png new file mode 100644 index 0000000000000000000000000000000000000000..0bf9ef7d7dc3d119a63be819815af42a04dd4e07 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/button.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/button_hover.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/button_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..026f59ba9468785886845de576afc755cedd8f3b Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/button_hover.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/checked.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/checked.png new file mode 100644 index 0000000000000000000000000000000000000000..52633ea72fe5ddf867277a72d14dbb9c3620ff84 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/checked.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/container.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/container.png new file mode 100644 index 0000000000000000000000000000000000000000..2d38b19590241e447b58c7952a33ec72d28cef99 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/container.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/container_hover.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/container_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8d42bf0694de35e8dc9990c570e9aeb0493afead Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/container_hover.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/jstree_plus_minus.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/jstree_plus_minus.png new file mode 100644 index 0000000000000000000000000000000000000000..af4d3ec39a3f658d61d847920d9191b0d9383cf5 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/jstree_plus_minus.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/stub.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/stub.png new file mode 100644 index 0000000000000000000000000000000000000000..3c30037a3b3328ef35a3ccc07772711713c2cddd Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/stub.png differ diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/images/theme-preview-back.png b/app/code/core/Mage/DesignEditor/view/adminhtml/images/theme-preview-back.png new file mode 100644 index 0000000000000000000000000000000000000000..b48f5907705743791a7cd111add6aee662e9f081 Binary files /dev/null and b/app/code/core/Mage/DesignEditor/view/adminhtml/images/theme-preview-back.png differ diff --git a/app/code/core/Mage/DesignEditor/view/frontend/js/base.js b/app/code/core/Mage/DesignEditor/view/adminhtml/js/base.js similarity index 92% rename from app/code/core/Mage/DesignEditor/view/frontend/js/base.js rename to app/code/core/Mage/DesignEditor/view/adminhtml/js/base.js index b801592c50eca7173cf087a9ab448070eacaf257..f263c3bfa43a7e9cd5932503eeb08f672540388f 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/js/base.js +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/js/base.js @@ -24,12 +24,12 @@ */ (function($) { - /** * Widget tree */ $.widget('vde.vde_tree', { options: { + container_frame: '.vde_container_frame', ui: { select_limit: 1, selected_parent_close: false @@ -56,7 +56,7 @@ var link = $(data.rslt.obj).find('a:first'); $(this).trigger('link_selected.' + self.widgetName, [link]); if (data.rslt.e) { // User clicked the link, not just tree initialization - window.location = link.attr('href'); + $(self.options.container_frame).attr('src', link.attr('href')); } }); } @@ -103,22 +103,23 @@ }) .on('link_selected.vde_tree', function(e, link) { titleText.text(link.text()); + self.hide(e); }) .find(this.options.titleSelector) .on('click.' + self.widgetName, function(e) { self.element.hasClass(self.options.activeClass) ? self.hide(e): self.show(e); - }) + }); $('body').on('click', function(e) { var widgetInstancesSelector = ':' + self.namespace + '-' + self.widgetName; $(widgetInstancesSelector).not($(e.target).parents(widgetInstancesSelector)).vde_menu('hide'); }) }, - show: function(e) { + show: function() { this.element.addClass(this.options.activeClass).trigger('activate_toolbar_cell.' + this.widgetName); }, - hide: function(e) { + hide: function() { this.element.removeClass(this.options.activeClass); } }); @@ -147,6 +148,11 @@ this.element.addClass(this.options.checkedClass); this.element.trigger('checked.' + this.widgetName); } + }, + setChecked: function() { + if (!this.element.hasClass(this.options.checkedClass)) { + this.element.addClass(this.options.checkedClass); + } } }); })(jQuery); diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/js/design_editor.js b/app/code/core/Mage/DesignEditor/view/adminhtml/js/design_editor.js new file mode 100644 index 0000000000000000000000000000000000000000..91c92506f623a8df1c23b94ba3d434bb84af455d --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/js/design_editor.js @@ -0,0 +1,222 @@ +/** + * 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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ + +(function($) { + + /** + * Widget block + */ + $.widget( "vde.block", { _create: function() {}} ); + + /** + * Widget panel + */ + $.widget('vde.vde_panel', { + options: { + cellSelector: '.vde_toolbar_cell', + handlesHierarchySelector: '#vde_handles_hierarchy', + treeSelector: '#vde_handles_tree', + viewLayoutButtonSelector: '.view-layout', + viewLayoutUrl: null, + editorFrameSelector: null + }, + _create: function() { + this._initCells(); + this._initViewLayoutButton(); + }, + _initCells : function() { + var self = this; + this.element.find( this.options.cellSelector ).each( function(){ + $( this ).is( self.options.handlesHierarchySelector ) ? + $( this ).vde_menu( {treeSelector : self.options.treeSelector, slimScroll:true } ) : + $( this ).vde_menu(); + }); + this.element.find( this.options.cellSelector ).vde_menu(); + }, + _initViewLayoutButton: function() { + var button = $(this.options.viewLayoutButtonSelector); + this.options.viewLayoutUrl = button.attr('href'); + button.bind( + 'click', $.proxy(this._onViewLayoutButtonClick, this) + ); + }, + _onViewLayoutButtonClick: function(e) { + try { + var historyObject = $(this.options.editorFrameSelector).get(0).contentWindow.vdeHistoryObject; + if (historyObject.getItems().length == 0) { + /** @todo temporary report */ + alert($.mage.__('No changes found.')); + return false; + } + var data = this._preparePostItems(historyObject.getItems()); + var compactXml = this._post(this.options.viewLayoutUrl, data); + alert(compactXml); + } catch (e) { + alert(e.message); + } finally { + return false; + } + + }, + _preparePostItems: function(items) { + var postData = {}; + $.each(items, function(index, item){ + postData[index] = item.getPostData(); + }); + return postData; + }, + _post: function(action, data) { + var url = action; + var postResult; + $.ajax({ + url: url, + type: 'POST', + dataType: 'JSON', + data: {historyData: data}, + async: false, + success: function(data) { + if (data.error) { + /** @todo add error validator */ + throw Error($.mage.__('Some problem with save action')); + return; + } + postResult = data.success; + }, + error: function(data) { + throw Error($.mage.__('Some problem with save action')); + } + }); + return postResult; + }, + _destroy: function() { + this.element.find( this.options.cellSelector ).each( function(i, element) { + $(element).data('vde_menu').destroy(); + }); + this._super(); + } + }); + + /** + * Widget page + */ + $.widget('vde.vde_page', { + options: { + frameSelector: 'iframe#vde_container_frame', + containerSelector: '.vde_element_wrapper.vde_container', + panelSelector: '#vde_toolbar_row', + highlightElementSelector: '.vde_element_wrapper', + highlightElementTitleSelector: '.vde_element_title', + highlightCheckboxSelector: '#vde_highlighting', + cookieHighlightingName: 'vde_highlighting', + historyToolbarSelector: '.vde_history_toolbar' + }, + editorFrame: null, + _create: function () { + var self = this; + $(this.options.frameSelector).load(function() { + self.editorFrame = $(this).contents(); + self._initPanel(); + }); + }, + _initPanel: function () { + $(this.options.panelSelector).vde_panel({editorFrameSelector: this.options.frameSelector}) + } + }); + + /** + * Widget page highlight functionality + */ + var pageBasePrototype = $.vde.vde_page.prototype; + $.widget('vde.vde_page', $.extend({}, pageBasePrototype, { + _create: function () { + pageBasePrototype._create.apply(this, arguments); + if (this.options.highlightElementSelector) { + this._initHighlighting(); + this._bind(); + } + }, + _bind: function () { + var self = this; + this.element + .on('checked.vde_checkbox', function () { + self._highlight(); + }) + .on('unchecked.vde_checkbox', function () { + self._unhighlight(); + }); + }, + _initHighlighting: function () { + if (this.options.highlightCheckboxSelector) { + $(this.options.highlightCheckboxSelector) + .vde_checkbox(); + } + + this.frameChanged = false; + var self = this; + $(this.options.frameSelector).load(function() { + self.highlightBlocks = {}; + if (self.frameChanged) { + $(self.options.highlightCheckboxSelector).vde_checkbox('setChecked'); + } else { + self.frameChanged = true; + } + }); + }, + _highlight: function () { + var self = this; + this.editorFrame.find(this.options.highlightElementSelector).each(function () { + $(this) + .append(self._getChildren($(this).attr('id'))) + .show() + .children(self.options.highlightElementTitleSelector).slideDown('fast'); + }); + this.highlightBlocks = {}; + }, + _unhighlight: function () { + var self = this; + this.editorFrame.find(this.options.highlightElementSelector).each(function () { + var elem = $(this); + elem.children(self.options.highlightElementTitleSelector).slideUp('fast', function () { + var children = elem.contents(':not(' + self.options.highlightElementTitleSelector + ')'); + var parentId = elem.attr('id'); + children.each(function () { + self._storeChild(parentId, this); + }); + elem.after(children).hide(); + }); + }); + }, + _storeChild: function(parentId, child) { + if (!this.highlightBlocks[parentId]) { + this.highlightBlocks[parentId] = []; + } + this.highlightBlocks[parentId].push(child); + }, + _getChildren: function(parentId) { + return (!this.highlightBlocks[parentId]) ? [] : this.highlightBlocks[parentId]; + } + })); + +})( jQuery ); diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/js/infinitescroll.js b/app/code/core/Mage/DesignEditor/view/adminhtml/js/infinitescroll.js new file mode 100644 index 0000000000000000000000000000000000000000..1c9985f5e60323f6fd267aee0aa4ea5ee1d3acd5 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/js/infinitescroll.js @@ -0,0 +1,166 @@ + /** + * 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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ + +( function ( $ ) { + + $.widget('vde.infinite_scroll', { + _locked: false, + _loader: '.theme-loader', + _container: '.theme-container', + _defaultElementSize: 400, + _elementsInRow: 2, + _pageSize: 4, + options: { + url: '', + loadDataOnCreate: true + }, + + /** + * Load data + * @public + */ + loadData: function() { + if (this._isLocked()) { + return + } + this.setLocked(true); + + $.ajax({ + url: this.options.url, + type: 'GET', + dataType: 'JSON', + data: { 'page_size': this._pageSize }, + context: $(this), + success: $.proxy(function(data) { + if (data.content) { + if (this.options.url === '') { + this.setLocked(false); + return; + } + this.element.find(this._container).append(data.content); + this.setLocked(false); + } + + var eventData = {}; + this.element.trigger('loaded', eventData); + }, this), + error: $.proxy(function() { + this.options.url = ''; + throw Error($.mage.__('Some problem with theme loading')); + }, this) + }); + }, + + /** + * Set is locked + * @param {boolean} status locked status + * @protected + */ + setLocked: function(status) { + (status) ? $(this._loader).show() : $(this._loader).hide(); + this._locked = status; + }, + + /** + * Load data is container empty + * @public + */ + loadDataIsContainerEmpty: function() { + if ($(this._container).children().length == 0) { + this.loadData(); + } + }, + + /** + * Infinite scroll creation + * @protected + */ + _create: function() { + if (this.element.find(this._container).children().length == 0) { + this._pageSize = this._calculatePagesSize(); + } + + this._bind(); + }, + + /** + * Calculate default pages count + * + * @return {number} + * @protected + */ + _calculatePagesSize: function() { + elementsCount = Math.ceil($(window).height() / this._defaultElementSize) * this._elementsInRow; + return (elementsCount % 2) ? elementsCount++ : elementsCount; + }, + + /** + * Get is locked + * @return {boolean} + * @protected + */ + _isLocked: function() { + return this._locked; + }, + + /** + * Bind handlers + * @protected + */ + _bind: function() { + if (this.options.loadDataOnCreate) { + $(document).ready( + $.proxy(this.loadData, this) + ); + } + + $(window).resize( + $.proxy(function(event) { + if (this._isScrolledBottom() && this.options.url) { + this.loadData(); + } + }, this) + ); + + $(window).scroll( + $.proxy(function(event) { + if (this._isScrolledBottom() && this.options.url) { + this.loadData(); + } + }, this) + ); + }, + + /** + * Check is scrolled bottom + * @return {boolean} + * @protected + */ + _isScrolledBottom: function() { + return ($(window).scrollTop() + $(window).height() >= $(document).height() - this._defaultElementSize) + } + }); + +})(jQuery); diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/js/theme-selector.js b/app/code/core/Mage/DesignEditor/view/adminhtml/js/theme-selector.js new file mode 100644 index 0000000000000000000000000000000000000000..2b13910d41f7a1924c6faaa5183db774662cfa1e --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/js/theme-selector.js @@ -0,0 +1,222 @@ +/** + * 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 mage + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +/*jshint jquery:true*/ +(function($) { + $.widget("vde.themeSelector", { + options: { + assignEvent: 'assign', + assignSaveEvent: 'assign-save', + previewEvent: 'preview', + deleteEvent: 'delete', + loadEvent: 'loaded', + storeView: { + windowSelector: '#store-view-window' + }, + assignSaveUrl: null, + afterAssignSaveUrl: null, + storesByThemes: {}, + isMultipleStoreViewMode: null + }, + + /** + * Identifier of a theme currently processed + * + * It is set in showStoreViews(), used and then cleared in _onAssignSave() + */ + themeId: null, + + /** + * Form creation + * @protected + */ + _create: function() { + this._bind(); + }, + + /** + * Bind handlers + * @protected + */ + _bind: function() { + //this.element is <body> + this.element.on(this.options.assignEvent, $.proxy(this._onAssign, this)); + this.element.on(this.options.assignSaveEvent, $.proxy(this._onAssignSave, this)); + this.element.on(this.options.previewEvent, $.proxy(this._onPreview, this)); + this.element.on(this.options.deleteEvent, $.proxy(this._onDelete, this)); + this.element.on('keyup', $.proxy(function(e) { + //ESC button + if (e.keyCode == 27) { + var popUp = $(this.options.storeView.windowSelector); + popUp.hide(); + this.themeId = null; + } + }, this)); + + $('body').on(this.options.loadEvent, function() { + $('*[data-widget-button]').button(); + }); + }, + + /** + * Preview action + * @protected + */ + _onPreview: function(event, data) { + document.location = data.preview_url; + }, + + /** + * Delete action + * @protected + */ + _onDelete: function(event, data) { + deleteConfirm($.mage.__('Are you sure you want to do this?'), data['url']); + }, + + /** + * Assign event handler + * @protected + */ + _onAssign: function(event, data) { + if (this.options.isMultipleStoreViewMode) { + this.showStoreViews(data.theme_id); + } else { + if (!this._confirm($.mage.__('You are about to change this theme for your live store, are you sure want to do this?'))) { + return; + } + this.assignSaveTheme(data.theme_id, null); + } + }, + + /** + * "Assign Save" button click handler + * @protected + */ + _onAssignSave: function(event, data) { + var stores = []; + var checkedValue = 1; + $(this.options.storeView.windowSelector).find('form').serializeArray().each(function(object, index) { + if (object.value == checkedValue) { + stores.push(object.name.match('storeviews\\[(\\d)\\]')[1] * 1); + } + }); + + if (!this._isStoreChanged(this.themeId, stores)) { + alert($.mage.__('No stores were reassigned.')); + return; + } + + var popUp = $(this.options.storeView.windowSelector); + popUp.hide(); + + this.assignSaveTheme(this.themeId, stores); + this.themeId = null; + }, + + /** + * Check if the stores changed + * @protected + */ + _isStoreChanged: function(themeId, storesToAssign) { + var assignedStores = this.options.storesByThemes[themeId] || [] ; + var isChanged = !( + storesToAssign.length == assignedStores.length + && $(storesToAssign).not(assignedStores).length == 0 + ); + + return isChanged; + }, + + /** + * Assign event handlers + * @protected + */ + _confirm: function(message) { + return confirm(message); + }, + + /** + * Show store-view selector window + * @public + */ + showStoreViews: function(themeId) { + var popUp = $(this.options.storeView.windowSelector); + var storesByThemes = this.options.storesByThemes; + popUp.find('input[type=checkbox]').each(function(index, element) { + element = $(element); + var storeViewId = element.attr('id').replace('storeview_', '') * 1; + var checked = true; + if (!storesByThemes[themeId] || storesByThemes[themeId].indexOf(storeViewId) == -1) { + checked = false; + } + element.attr('checked', checked); + }); + this.themeId = themeId; + popUp.show(); + }, + + /** + * Send AJAX request to assign theme to store-views + * @public + */ + assignSaveTheme: function(themeId, stores) { + if (!this.options.assignSaveUrl) { + throw Error($.mage.__('Url to assign themes to store is not defined')); + } + + var data = { + theme_id: themeId, + stores: stores + }; + //TODO since we can't convert data to JSON string we use magic numbers + var DEFAULT_STORE = '-1'; + var EMPTY_STORES = '-2'; + if (data.stores === null) { + data.stores = DEFAULT_STORE; + } else if (data.stores.length == 0) { + data.stores = EMPTY_STORES; + } + $.post(this.options.assignSaveUrl, data, $.proxy(function(response) { + if (response.error) { + alert($.mage.__('Error') + ': "' + response.error + '".'); + } else { + var defaultStore = 0; + var url = [ + this.options.afterAssignSaveUrl + 'store_id', + stores ? stores[0] : defaultStore, + 'theme_id', + themeId + ].join('/'); + this.options.storesByThemes[themeId] = stores; + + setTimeout(function() {$('body').loader('show');}, 500); + document.location = url; + } + }, this)).error(function() { + alert($.mage.__('Error: unknown error.')); + }); + } + }); +})(jQuery); diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/layout.xml b/app/code/core/Mage/DesignEditor/view/adminhtml/layout.xml index 7d3da53ea01bc8fb5c67196e18aac6b4451c90a2..b39004e5381bd1375c562aa882fd871fc696fc19 100644 --- a/app/code/core/Mage/DesignEditor/view/adminhtml/layout.xml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/layout.xml @@ -27,21 +27,79 @@ --> <layout> <adminhtml_system_design_editor_index> + <reference name="head"> + <action method="addJs"><file>Mage_DesignEditor::js/infinitescroll.js</file></action> + <action method="addJs"><file>Mage_DesignEditor::js/theme-selector.js</file></action> + <action method="addCss"><file>Mage_DesignEditor::css/styles.css</file></action> + </reference> <reference name="content"> - <block type="Mage_DesignEditor_Block_Adminhtml_Launcher_Form_Container" name="design_editor_launcher_form_container"> - <block type="Mage_DesignEditor_Block_Adminhtml_Launcher_Form" name="design_editor_launcher_form" as="form"/> - </block> - <block type="Mage_DesignEditor_Block_Adminhtml_Theme_List" name="design_editor_theme_list" as="list" template="Mage_DesignEditor::theme/list.phtml"> - <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Item" name="design_editor_theme_item" as="item" template="Mage_DesignEditor::theme/item.phtml"> - <block type="Mage_Backend_Block_Template" name="design_editor_theme" as="theme" template="Mage_DesignEditor::theme.phtml" /> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_Tabs" name="theme.selector.tabs"> + <action method="addTab"><name>available_themes</name><block>available.themes.tab</block></action> + <action method="addTab"><name>customizations</name><block>customizations.themes.tab</block></action> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_Tab_Available" name="available.themes.tab"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available" name="available.theme.list" template="Mage_DesignEditor::theme/list/available.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme" name="available.theme.item" as="item" template="Mage_DesignEditor::theme.phtml"/> + </block> + </block> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_Tab_Customizations" name="customizations.themes.tab" template="Mage_DesignEditor::theme/selector/myCustomizationsTab.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Assigned" name="assigned.theme.list" template="Mage_DesignEditor::theme/list/customized.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme" name="assigned.theme" as="theme" template="Mage_DesignEditor::theme_customizations.phtml"/> + </block> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Unassigned" name="unassigned.theme.list" template="Mage_DesignEditor::theme/list/customized.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme" name="unassigned.theme" as="theme" template="Mage_DesignEditor::theme_customizations.phtml" /> + </block> </block> </block> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_StoreView" name="theme.selector.storeview" template="Mage_DesignEditor::theme/selector/storeview.phtml" /> </reference> </adminhtml_system_design_editor_index> - <adminhtml_system_design_editor_exit> + <adminhtml_system_design_editor_firstentrance> + <reference name="head"> + <action method="addJs"><file>Mage_DesignEditor::js/infinitescroll.js</file></action> + <action method="addJs"><file>Mage_DesignEditor::js/theme-selector.js</file></action> + <action method="addCss"><file>Mage_DesignEditor::css/styles.css</file></action> + </reference> <reference name="content"> - <block type="Mage_Adminhtml_Block_Template" name="design_editor_exit" as="exit" template="Mage_DesignEditor::exit.phtml"/> + <block type="Mage_Backend_Block_Template" name="available.theme.list.container" as="theme_container" template="Mage_DesignEditor::theme/selector/firstEntrance.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available" name="available.theme.list" template="Mage_DesignEditor::theme/list/available.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme" name="design.editor.theme" as="theme" template="Mage_DesignEditor::theme.phtml" /> + </block> + </block> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_StoreView" name="theme.selector.storeview" template="Mage_DesignEditor::theme/selector/storeview.phtml" /> + </reference> + </adminhtml_system_design_editor_firstentrance> + + <adminhtml_system_design_editor_loadthemelist> + <container name="root" label="Root" output="1"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available" name="available.theme.list" template="Mage_DesignEditor::theme/list/available_ajax.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme" name="design.editor.theme" as="theme" template="Mage_DesignEditor::theme.phtml"/> + </block> + </container> + </adminhtml_system_design_editor_loadthemelist> + + <adminhtml_system_design_editor_launch> + <reference name="root"> + <action method="setTemplate"><file>Mage_DesignEditor::editor.phtml</file></action> + </reference> + <reference name="head"> + <action method="addJs"><file>Mage_DesignEditor::js/theme-selector.js</file></action> + <action method="addJs"><file>Mage_DesignEditor::js/base.js</file></action> + <action method="addJs"><file>Mage_DesignEditor::js/design_editor.js</file></action> + <action method="addJs"><file>jquery/jquery.iframe-auto-height.plugin.1.9.0.js</file></action> + <action method="addJs"><file>jquery/jstree/jquery.jstree.js</file></action> + <action method="addJs"><file>jquery/slimScroll/slimScroll.min.js</file></action> + <action method="addCss"><file>Mage_DesignEditor::css/styles.css</file></action> + </reference> + <reference name="content"> + <block type="Mage_DesignEditor_Block_Adminhtml_Editor_Container" name="design_editor" template="Mage_DesignEditor::editor/container.phtml"> + <block type="Mage_Backend_Block_Template" name="design_editor_toolbar" template="Mage_DesignEditor::editor/toolbar.phtml"> + <block type="Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy" name="design_editor_toolbar_handles_hierarchy" template="Mage_DesignEditor::editor/toolbar/handles_hierarchy.phtml" /> + <block type="Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_ViewOptions" name="design_editor_toolbar_view_options" template="Mage_DesignEditor::editor/toolbar/view_options.phtml" /> + <block type="Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_Buttons" name="design_editor_toolbar_buttons" template="Mage_DesignEditor::editor/toolbar/buttons.phtml" /> + </block> + <block type="Mage_DesignEditor_Block_Adminhtml_Theme_Selector_StoreView" name="theme.selector.storeview" template="Mage_DesignEditor::theme/selector/storeview.phtml" /> + </block> </reference> - </adminhtml_system_design_editor_exit> + </adminhtml_system_design_editor_launch> </layout> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme.phtml index 12abb71481d39f22f6ce3acaba08feae823d882d..26118cc1aad8170a0cbc14cdffbef308ce439399 100644 --- a/app/code/core/Mage/DesignEditor/view/adminhtml/theme.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme.phtml @@ -25,8 +25,22 @@ */ ?> -<?php /** @var $this Mage_Backend_Block_Template */ ?> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme */?> -<div style="margin:0 auto; height:200px; width:200px; border:1px solid black;"> - <img src="<?php echo $this->getTheme()->getPreviewImageUrl() ?>" style="display:block; height:200px; width:200px;" alt="" /> -</div> +<li class="theme" id="theme-id-<?php echo $this->getTheme()->getId() ?>" style="margin:20px; float:left;"> + <ul class="theme-element"> + <li class="theme-front"> + <div style="margin:0 auto; height:350px; width:350px; border:1px solid black;"> + <img src="<?php echo $this->getTheme()->getPreviewImageUrl() ?>" style="display:block; height:350px; width:350px;" alt="" /> + </div> + </li> + <li class="theme-back"> + <div style="padding: 30px;"> + <div class="theme-title"> + <?php echo $this->getTheme()->getThemeTitle() ?> + </div> + <?php echo $this->getButtonsHtml() ?> + </div> + </li> + </ul> +</li> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list.phtml deleted file mode 100644 index a22cc8ab57b145f45eb9fd518459aff71006dc7c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list.phtml +++ /dev/null @@ -1,56 +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 Mage_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> - -<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme_List */ ?> - -<div class="content-header"> - <?php echo $this->getHeaderHtml() ?> -</div> -<div class="entry-edit"> - <div class="fieldset"> - <div class="hor-scroll"> - <?php $featuredItems = $this->getListItems()?> - <?php if (count($featuredItems)): ?> - <ul> - <?php echo join("\n", $featuredItems)?> - </ul> - <?php else: ?> - <?php echo $this->__('No featured themes to display') ?> - <?php endif ?> - <div style="clear:both;"></div> - - <?php $nonFeaturedItems = $this->getListItems(false)?> - <?php if (count($nonFeaturedItems)): ?> - <a onclick="$('vde-non-featured-theme').toggle();" href="#"><?php echo $this->__('Other themes'); ?></a> - <ul id="vde-non-featured-theme" style="display: none;"> - <?php echo join("\n", $nonFeaturedItems)?> - </ul> - <div style="clear:both;"></div> - <?php endif ?> - </div> - </div> -</div> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/available.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/available.phtml new file mode 100644 index 0000000000000000000000000000000000000000..73d080cc22f0bb2618f8a83ecd4699f8c0600e99 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/available.phtml @@ -0,0 +1,54 @@ +<?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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +?> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available */?> + +<div class="entry-edit"> + <div class="infinite_scroll"> + <ul id="theme-container" class="theme-container"></ul> + <div class="theme-loader"> + <img src="<?php echo $this->getViewFileUrl('images/ajax-loader-tr.gif') ?>"/> + </div> + </div> +</div> +<script type="text/javascript"> + (function ($) { + $( document ).ready(function( ) { + <?php if ($this->getTabId()): ?> + $('.infinite_scroll').infinite_scroll({ + url : '<?php echo $this->getUrl('*/*/loadthemelist') ?>', + loadDataOnCreate : false + }); + $('.infinite_scroll').infinite_scroll('setLocked', true); + + $('a[name="<?php echo $this->getTabId() ?>"]').on("click", function(event) { + $('.infinite_scroll').infinite_scroll('setLocked', false); + $('.infinite_scroll').infinite_scroll('loadDataIsContainerEmpty'); + }); + <?php endif; ?> + }); + })(jQuery); +</script> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/container.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/available_ajax.phtml similarity index 77% rename from app/code/core/Mage/DesignEditor/view/frontend/container.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/available_ajax.phtml index 219c4c002ba178fbd53d906fc2437cbe96635e7f..a14511af1f0430e107ae903d920993e9270b2633 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/container.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/available_ajax.phtml @@ -24,4 +24,9 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -<?php echo $this->getChildHtml() ?> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Available */ ?> +<?php echo join("\n", $this->getListItems()) ?> + +<script type="text/javascript"> + jQuery('.infinite_scroll').infinite_scroll({url :'<?php echo $this->getNextPageUrl() ?>'}); +</script> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/customized.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/customized.phtml new file mode 100644 index 0000000000000000000000000000000000000000..104c2d697eaeaba4171beada4be9b413e6e6bc35 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/list/customized.phtml @@ -0,0 +1,39 @@ +<?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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +?> +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract */?> + +<div> + <h3><?php echo $this->getTabTitle() ?></h3> + <ul> + <?php $themeItems = $this->getListItems(); ?> + <?php if ($themeItems): ?> + <?php echo join("\n", $themeItems) ?> + <?php else: ?> + <li><?php echo $this->__('There are no items here') ?></li> + <?php endif; ?> + </ul> +</div> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/item.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/firstEntrance.phtml similarity index 70% rename from app/code/core/Mage/DesignEditor/view/adminhtml/theme/item.phtml rename to app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/firstEntrance.phtml index 33f943bae1e883e458f286ef866cd7bbdc92de4a..5254dca3d68ecaa63ea61afb497e251f41a1fd13 100644 --- a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/item.phtml +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/firstEntrance.phtml @@ -25,12 +25,12 @@ */ ?> -<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme_Item */?> +<?php /** @var $this Mage_Backend_Block_Template */?> +<div> + <h3><?php echo $this->__('Choose a theme to start with') ?></h3> + <div><?php echo $this->getChildHtml('available.theme.list') ?></div> +</div> -<li style="height:300px; width:240px; margin:20px; float:left;"> - <?php echo $this->getThemeHtml() ?> - <div style="margin:5px 20px;"> - <h4><sup><?php echo $this->getTheme()->getIsFeatured() ? 'F' : 'X'?></sup> <?php echo $this->getTheme()->getThemeTitle()?></h4> - <?php echo $this->getLaunchButtonHtml() ?> - </div> -</li> +<script type="text/javascript"> + jQuery('.infinite_scroll').infinite_scroll({url :'<?php echo $this->getUrl('*/*/loadthemelist') ?>'}); +</script> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/myCustomizationsTab.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/myCustomizationsTab.phtml new file mode 100644 index 0000000000000000000000000000000000000000..3ddea290b1c0fdf95a000ab5de6ac11b1658251f --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/myCustomizationsTab.phtml @@ -0,0 +1,41 @@ +<?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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +?> +<?php /** @var $this Mage_Backend_Block_Template */?> + +<div><?php echo $this->getChildHtml('assigned.theme.list') ?></div> +<hr style="clear: both; margin-bottom: 40px;" /> +<div><?php echo $this->getChildHtml('unassigned.theme.list') ?></div> + +<script type="text/javascript"> + <?php if ($this->getTabId()): ?> + (function ($) { + $('a[name="<?php echo $this->getTabId() ?>"]').on("click", function(event) { + $('.infinite_scroll').infinite_scroll('setLocked', true) + }) + })(jQuery); + <?php endif; ?> +</script> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/storeview.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/storeview.phtml new file mode 100644 index 0000000000000000000000000000000000000000..187fdf1d629d72717ee9b00b88eced59e1da0c86 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme/selector/storeview.phtml @@ -0,0 +1,79 @@ +<?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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +?> + +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme_Selector_StoreView */?> + +<div style="position:absolute; z-index:500;"> + <div id="store-view-window" style="position:fixed; left:50%; margin-left:-355px; width:650px; top:15%; border:2px solid #555; background:#fff; display:none;"> + <div style="padding-top:10px; text-align:center; border-bottom:2px solid #555; background-color:#eee;"> + <h2><?php echo $this->__('Select Storeviews to make your changes live:') ?></h2> + </div> + <form method="post" action=""> + <ul class="websites"> + <?php foreach ($this->getWebsiteStructure() as $website => $stores): ?> + <li class="website"> + <p class="title" style="font-size:1.7em; color:#777; font-weight:bold; padding:15px 20px;"> + <?php echo $website; ?> + </p> + <ul class="stores"> + <?php foreach ($stores as $store => $storeViews): ?> + <li class="store"> + <p class="title" style="font-size:1.7em; color:#777; padding:15px 25px; border-top:2px solid #ccc; border-bottom:2px solid #ccc;"> + <?php echo $store; ?> + </p> + <ul class="storeviews"> + <?php foreach ($storeViews as $storeView => $id): ?> + <li class="storeview"> + <p class="title" style="font-size:1.7em; color:#777; padding:10px 40px;"> + <input type="hidden" name="storeviews[<?php echo $id; ?>]" value="0" /> + <input type="checkbox" id="storeview_<?php echo $id ?>" name="storeviews[<?php echo $id; ?>]" value="1" style="position:relative; top:-1px;" /> + <label for="storeview_<?php echo $id ?>" style="color:rgb(0,176,244); margin-left:5px;"> + <?php echo $storeView; ?> + </label> + </p> + </li> + <?php endforeach; ?> + </ul> + </li> + <?php endforeach; ?> + </ul> + </li> + <?php endforeach; ?> + </ul> + <div style="text-align:right; padding:10px;"> + <?php echo $this->getAssignSaveButtonHtml(); ?> + </div> + </form> + </div> +</div> +<script type="text/javascript"> + (function ($) { + $( document ).ready(function( ) { + $( 'body' ).themeSelector(<?php echo $this->getOptionsJson(); ?>); + }); + })(jQuery); +</script> diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/theme_customizations.phtml b/app/code/core/Mage/DesignEditor/view/adminhtml/theme_customizations.phtml new file mode 100644 index 0000000000000000000000000000000000000000..a829abaaa6b5a6156b147c3f90c0fe12e2426404 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/adminhtml/theme_customizations.phtml @@ -0,0 +1,49 @@ +<?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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +?> + +<?php /** @var $this Mage_DesignEditor_Block_Adminhtml_Theme */?> + +<li class="theme" id="theme-id-<?php echo $this->getTheme()->getId() ?>" style="margin:20px; float:left;"> + <ul class="theme-element-customizations"> + <li class="theme-assigned-to-storeview"> + <span class="theme-title"> + <?php echo $this->getTheme()->getThemeTitle() ?> + </span> + <?php if ($this->getTheme()->getAssignedStores()): ?> + <?php echo $this->__('Store View applied to:') . ' ' . implode(', ', $this->getStoresTitles()) ?> + <?php endif; ?> + </li> + <li class="theme-front-customizations"> + <div style="margin:0 auto; height:350px; width:350px; border:1px solid black;"> + <img src="<?php echo $this->getTheme()->getPreviewImageUrl() ?>" style="display:block; height:350px; width:350px;" alt="" /> + <div class="theme-buttons"> + <?php echo $this->getButtonsHtml() ?> + </div> + </div> + </li> + </ul> +</li> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/css/design.css b/app/code/core/Mage/DesignEditor/view/frontend/css/design.css new file mode 100644 index 0000000000000000000000000000000000000000..03ae0a294f91866857aab0e1461d8c73708dfb19 --- /dev/null +++ b/app/code/core/Mage/DesignEditor/view/frontend/css/design.css @@ -0,0 +1,295 @@ +/** + * 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 Mage_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +#vde_toolbar { + position: fixed; + margin-top: -54pt; + width: 100%; + z-index: 999; + font:10pt Arial, Helvetica, sans-serif; + color:#555; + text-align:left; + box-shadow:0 0 4pt 1pt #cbcbcb; +} +.vde_breadcrumbs, #vde_toolbar_row { + padding:0 3em; + height:26pt; + line-height:26pt; + vertical-align:middle; +} +.vde_breadcrumbs { + text-transform:uppercase; + background:white; +} + +#vde_toolbar_row { + background:#f0efe9; + border-top:1pt solid #dddcd8; + border-bottom:1pt solid #dddcd8; + position:relative; + z-index:100; +} + +#vde_toolbar_row .vde_toolbar_cell { + float: left; + margin-left:-11pt; + margin-right:10pt; + border-right:1pt solid transparent; + border-left:1pt solid transparent; + padding:0 10pt; + position:relative; +} +#vde_toolbar_row .vde_toolbar_cell:hover, #vde_toolbar_row .vde_toolbar_cell.active { + background-color:white; + border-right:1pt solid #deddd9; + border-left:1pt solid #deddd9; +} +#vde_toolbar_buttons { + float: right; + z-index: 1000; + position: relative; + line-height:21pt; + padding:2pt 0; +} +#vde_toolbar_buttons a.vde_button { + display:block; + border:1px solid #c9c6be; + box-shadow:0 0 1pt 0 #c9c6be; + border-radius:3pt; + padding:0 1.7em; + color:#555; + text-decoration:none; + background-image:url(../images/button.png); + background-size:contain; + float: left; + margin-right:3px; +} +#vde_toolbar_buttons a.vde_button:hover { + box-shadow:0 0 1pt 1pt #c9c6be; + background-image:url(../images/button_hover.png); +} +#vde_toolbar .item-msg { + border-style: solid; + border-width: 1px; + padding: 4px; +} + +#vde_toolbar .error { + border-color: red; + color: red; +} + +.vde_element_wrapper { + margin-bottom: 3px; + padding: 0px 2px 2px 2px; + border: 2px solid #69a8cf; + border-radius: 4px; +} +.vde_element_title { + font-family:Arial, Helvetica, sans-serif; + margin: -2px 0 0 -4px; + padding: 0; + border-width: 2px 5px 6px 7px; + border-image: url(../images/block.png) 2 5 6 7 stretch stretch; + border-image-outset: fill; + -webkit-border-image: url(../images/block.png) 2 5 6 7 stretch stretch; + -moz-border-image: url(../images/block.png) 2 5 6 7 stretch stretch; + color: black; + font-size: 8pt; + font-weight: bold; + max-width: 150px; + height: 18px; + overflow: hidden; + text-align: left; + line-height: 17px; + cursor: default; +} +.vde_element_remove { + margin: -26px -6px 0px -4px; + padding: 0px; + border-width: 2px 5px 6px 7px; + border-image: url(../images/stub.png) 2 5 6 7 stretch stretch; + border-image-outset: fill; + -webkit-border-image: url(../images/stub.png) 2 5 6 7 stretch stretch; + -moz-border-image: url(../images/stub.png) 2 5 6 7 stretch stretch; + max-width: 20px; + height: 18px; + overflow: hidden; + text-align: right; + line-height: 17px; + cursor: default; + float: right; +} +.vde_element_wrapper.vde_container { + border: 2px solid #7bc361; +} +.vde_container > .vde_element_title { + border-image: url(../images/container.png) 2 5 6 7 stretch stretch; + -webkit-border-image: url(../images/container.png) 2 5 6 7 stretch stretch; + -moz-border-image: url(../images/container.png) 2 5 6 7 stretch stretch; +} +.vde_element_wrapper.vde_stub { + border: 2px solid #92978d; +} +.vde_stub > .vde_element_title { + border-image: url(../images/stub.png) 2 5 6 7 stretch stretch; + -webkit-border-image: url(../images/stub.png) 2 5 6 7 stretch stretch; + -moz-border-image: url(../images/stub.png) 2 5 6 7 stretch stretch; +} +.vde_container.vde_container_hover { + border-color: #006400; +} +.vde_container.vde_container_hover > .vde_element_title { + border-image: url(../images/container_hover.png) 2 5 6 7 stretch stretch; + -webkit-border-image: url(../images/container_hover.png) 2 5 6 7 stretch stretch; + -moz-border-image: url(../images/container_hover.png) 2 5 6 7 stretch stretch; +} +.vde_placeholder { + background-color: #F5F5DC; +} +.vde_wrapper_hidden, .vde_wrapper_hidden .vde_element_title { + display: none; +} + +.vde_toolbar_cell_title { + font-weight: bold; + cursor: pointer; + padding-right:12pt; + background: url(../images/arrow_down.png) right center no-repeat; +} +.vde_toolbar_cell.active .vde_toolbar_cell_title { + background-image: url(../images/arrow_up.png); +} +.vde_toolbar_cell_value { + font-weight: normal; +} +#vde_toolbar_row .vde_toolbar_cell_content, #vde_toolbar_row .vde_toolbar_cell_content * { + color:#f0efe9; +} +.vde_toolbar_cell_content { + display: none; + position: absolute; + top:2.5em; + left:0; + background: #494949; + padding:.5em 0; + z-index: 190; + min-width:20em; + margin-top:1pt; + border-radius:0 0 5pt 5pt; + -moz-box-shadow:0 1pt 2pt 1pt #6c6c6c; + -webkit-box-shadow:0 1pt 2pt 1pt #6c6c6c; + box-shadow:0 1pt 2pt 1pt #6c6c6c; +} +.vde_toolbar_cell.active .vde_toolbar_cell_content { + display: block; +} +.vde_toolbar_cell_content > div { + white-space: nowrap; + vertical-align: middle; + padding: 0 10px; +} +.vde_toolbar_cell_content .vde_cell_list_item { + padding-left:18pt; + cursor: pointer; +} +.vde_toolbar_cell_content .vde_cell_list_group { + padding-left:5pt; + font-style:italic; + cursor:default; +} +.vde_toolbar_cell_content .vde_cell_list_item:hover, #vde_handles_tree .jstree-clicked, #vde_handles_tree .jstree-hovered { + background-color:#7b7b7b; +} +.vde_toolbar_cell_content .checked { + background:url(../images/checked.png) no-repeat 5pt center; +} +.vde_breadcrumbs a { + font-weight: bold; + text-decoration: none; + color: #2483c7; +} + +.vde_breadcrumbs a:hover { + text-decoration: underline; +} + +.vde_breadcrumbs .vde_breadcrumbs_separator { + margin:0 0.3em; +} + +#visual_design_editor_theme a { + display:block; + text-decoration:none; +} +.ui-sortable-helper { + opacity: 0.9; +} + +#vde_handles_hierarchy .vde_toolbar_cell_content { + padding: 1em .5em 1em 0; +} +#vde_handles_tree { + max-height: 30em; /* max allowed height */ + overflow: hidden; /* don't display native scrollbars */ + padding-right: .5em; + text-align: left; + background-color: transparent; +} +#vde_handles_tree li { + overflow: hidden; +} +#vde_handles_tree a { + margin-left: .5em; + padding: .5em; + width: 100%; +} +#vde_handles_tree .jstree-clicked, #vde_handles_tree .jstree-hovered { + border: none; +} +#vde_handles_tree .jstree-closed > .jstree-icon { + background: url(../images/jstree_plus_minus.png) top left no-repeat; +} +#vde_handles_tree .jstree-open > .jstree-icon { + background: url(../images/jstree_plus_minus.png) top right no-repeat; +} +#vde_handles_tree .vde_option_fragment a { + color: #eea243; +} + +.vde_history_toolbar { + position: fixed; + left:0; top:150px; + width:220px; + background: #f0efe9; + border-bottom: 1pt solid #dddcd8; + box-shadow: 0 0 4pt 1pt #cbcbcb; + padding: 0 3pt; + line-height: 13pt; +} +.vde_history_toolbar ul {} +.vde_history_toolbar ul li { + white-space: nowrap; + overflow: hidden; +} diff --git a/app/code/core/Mage/DesignEditor/view/frontend/js/design_editor.js b/app/code/core/Mage/DesignEditor/view/frontend/js/design_editor.js index 3ff092a29dc04647b0b798af6d8000e4106c0ed2..5b8f74f25af4984bef981fcb41803a269b1fc4d9 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/js/design_editor.js +++ b/app/code/core/Mage/DesignEditor/view/frontend/js/design_editor.js @@ -24,7 +24,6 @@ */ (function($) { - /** * Widget block */ @@ -50,9 +49,9 @@ this.element.data('sortable', this); self.options = $.extend({}, self.options, { start: function( event, ui ) { - ui.placeholder.css( { height: $( ui.helper ).outerHeight( true ) } ); - self.element.vde_container('option', 'connectWith', $(self.options.connectWithSelector).not(ui.item)) - .vde_container('refresh'); + ui.placeholder.css({ height: $(ui.helper).outerHeight(true) }); + self.element.vde_container('option', 'connectWith', $(self.options.connectWithSelector) + .not(ui.item)).vde_container('refresh'); }, over: function(event, ui) { self.element.addClass(self.options.hoverClass); @@ -140,35 +139,6 @@ } })); - /** - * Widget panel - */ - $.widget('vde.vde_panel', { - options: { - cellSelector: '.vde_toolbar_cell', - handlesHierarchySelector: '#vde_handles_hierarchy', - treeSelector: '#vde_handles_tree' - }, - _create: function() { - this._initCells(); - }, - _initCells : function() { - var self = this; - this.element.find( this.options.cellSelector ).each( function(){ - $( this ).is( self.options.handlesHierarchySelector ) ? - $( this ).vde_menu( {treeSelector : self.options.treeSelector, slimScroll:true } ) : - $( this ).vde_menu(); - }); - this.element.find( this.options.cellSelector ).vde_menu(); - }, - _destroy: function() { - this.element.find( this.options.cellSelector ).each( function(i, element) { - $(element).data('vde_menu').destroy(); - }); - this._super(); - } - }); - /** * Widget history * @@ -204,28 +174,12 @@ * @todo move out from history toolbar send POST data functionality */ $.widget( "vde.vde_historyToolbar" , { - options:{ - compactLogButtonSelector: '.compact-log', - viewLayoutButtonSelector: '.view-layout', - baseUrl: null, - compactLogUrl: null, - viewLayoutUrl: null - }, + options: {}, _history: null, _create: function() { this._initToolbar(); - this._initButtons(); }, _initToolbar : function() {}, - _initButtons : function() { - $(this.options.compactLogButtonSelector).bind( - 'click', $.proxy(this._onCompactLogButtonClick, this) - ); - - $(this.options.viewLayoutButtonSelector).bind( - 'click', $.proxy(this._onViewLayoutButtonClick, this) - ); - }, _initEventObservers: function() { this._history.element.bind( this._history.getEventName('add'), @@ -235,46 +189,10 @@ _onHistoryAddItem: function(e, change) { this.addItem(change); }, - _onCompactLogButtonClick: function(e) { - try { - if (this._history.getItems().length == 0) { - /** @todo temporary report */ - alert($.mage.__('No changes found.')); - return false; - } - var data = this._preparePostItems(this._history.getItems()); - var items = this._post(this.options.compactLogUrl, data); - this._compactLogToHistory(items); - } catch (e) { - alert(e.message); - } finally { - return false; - } - }, - _onViewLayoutButtonClick: function(e) { - try { - if (this._history.getItems().length == 0) { - /** @todo temporary report */ - alert($.mage.__('No changes found.')); - return false; - } - var data = this._preparePostItems(this._history.getItems()); - var compactXml = this._post(this.options.viewLayoutUrl, data); - alert(compactXml); - } catch (e) { - alert(e.message); - } finally { - return false; - } - - }, setHistory: function(history) { this._history = history; this._initEventObservers(); }, - setBaseUrl: function(baseUrl) { - this.option('baseUrl', baseUrl); - }, setItems: function(items) { //this.deleteItems(); $.each(items, function(index, item){this.addItem(item)}); @@ -285,16 +203,6 @@ addItem: function(change) { this.element.find('ul').append('<li>' + change.getTitle() + '</li>'); }, - _compactLogToHistory: function(items) { - this._history.deleteItems(); - this.deleteItems(); - var self = this; - $.each(items[0], function(index, item) { - var change = $.fn.changeFactory.getInstance('layout'); - change.setActionData(item); - self._history.addItem(change); - }); - }, _preparePostItems: function(items) { var postData = {}; $.each(items, function(index, item){ @@ -303,10 +211,9 @@ return postData; }, _post: function(action, data) { - var url = action; var postResult; $.ajax({ - url: url, + url: action, type: 'POST', dataType: 'JSON', data: data, @@ -315,11 +222,10 @@ if (data.error) { /** @todo add error validator */ throw Error($.mage.__('Some problem with save action')); - return; } postResult = data.success; }, - error: function(data) { + error: function() { throw Error($.mage.__('Some problem with save action')); } }); @@ -330,132 +236,30 @@ /** * Widget page */ - $.widget('vde.vde_page', { + $.widget('vde.vde_connector', { options: { containerSelector: '.vde_element_wrapper.vde_container', - panelSelector: '#vde_toolbar', highlightElementSelector: '.vde_element_wrapper', highlightElementTitleSelector: '.vde_element_title', highlightCheckboxSelector: '#vde_highlighting', - cookieHighlightingName: 'vde_highlighting', - historyToolbarSelector: '.vde_history_toolbar', - baseUrl: null, - compactLogUrl: null, - viewLayoutUrl: null + historyToolbarSelector: '.vde_history_toolbar' }, _create: function () { this._initContainers(); - this._initPanel(); }, _initContainers: function () { $(this.options.containerSelector) .vde_container().disableSelection(); - }, - _initPanel: function () { - $(this.options.panelSelector).vde_panel(); } }); - /** - * Widget page highlight functionality - */ - var pageBasePrototype = $.vde.vde_page.prototype; - $.widget('vde.vde_page', $.extend({}, pageBasePrototype, { - _create: function () { - pageBasePrototype._create.apply(this, arguments); - if (this.options.highlightElementSelector) { - this._initHighlighting(); - this._bind(); - } - }, - _bind: function () { - var self = this; - this.element - .on('checked.vde_checkbox', function () { - self._highlight(); - }) - .on('unchecked.vde_checkbox', function () { - self._unhighlight(); - }); - }, - _initHighlighting: function () { - if (this.options.highlightCheckboxSelector) { - $(this.options.highlightCheckboxSelector) - .vde_checkbox(); - } - this.highlightBlocks = {}; - if ($.mage.cookies.get(this.options.cookieHighlightingName) == 'off') { - this._processMarkers(); - } - - }, - _highlight: function () { - $.mage.cookies.clear(this.options.cookieHighlightingName); - var self = this; - $(this.options.highlightElementSelector).each(function () { - $(this) - .append(self._getChildren($(this).attr('id'))) - .show() - .children(self.options.highlightElementTitleSelector).slideDown('fast'); - }); - this.highlightBlocks = {}; - }, - _unhighlight: function () { - $.mage.cookies.set(this.options.cookieHighlightingName, 'off'); - var self = this; - $(this.options.highlightElementSelector).each(function () { - var elem = $(this); - elem.children(self.options.highlightElementTitleSelector).slideUp('fast', function () { - var children = elem.contents(':not(' + self.options.highlightElementTitleSelector + ')'); - var parentId = elem.attr('id'); - children.each(function () { - self._storeChild(parentId, this); - }); - elem.after(children).hide(); - }); - }); - }, - _processMarkers: function () { - var self = this, - parentsIdsStack = [], - currentParentId; - $('*').contents().each(function () { - if (this.nodeType == Node.COMMENT_NODE) { - if (this.data.substr(0, 9) == 'start_vde') { - currentParentId = this.data.substr(6, this.data.length); - parentsIdsStack.push(currentParentId); - this.parentNode.removeChild(this); - } else if (this.data.substr(0, 7) == 'end_vde') { - if (this.data.substr(4, this.data.length) !== currentParentId) { - throw "Could not find closing element for opened '" + currentParentId + "' element"; - } - parentsIdsStack.pop(); - currentParentId = parentsIdsStack[parentsIdsStack.length - 1]; - this.parentNode.removeChild(this); - } - } else if (currentParentId) { - self._storeChild(currentParentId, this); - } - }) - }, - _storeChild: function(parentId, child) { - if (!this.highlightBlocks[parentId]) { - this.highlightBlocks[parentId] = []; - } - this.highlightBlocks[parentId].push(child); - }, - _getChildren: function(parentId) { - return (!this.highlightBlocks[parentId]) ? [] : this.highlightBlocks[parentId]; - } - })); - /** * Widget page history init */ - var pagePrototype = $.vde.vde_page.prototype; - $.widget( "vde.vde_page", $.extend({}, pagePrototype, { + var pagePrototype = $.vde.vde_connector.prototype; + $.widget( "vde.vde_connector", $.extend({}, pagePrototype, { _create: function() { - pagePrototype._create.apply( this, arguments ); + pagePrototype._create.apply(this, arguments); var history = this._initHistory(); this._initHistoryToolbar(history); this._initRemoveOperation(history); @@ -463,7 +267,8 @@ }, _initHistory: function() { // @TODO can we make this not a widget but global object? - return $( window ).vde_history().data('vde_history'); + window.vdeHistoryObject = $( window ).vde_history().data('vde_history'); + return window.vdeHistoryObject; }, _initHistoryToolbar: function(history) { if (!history) { @@ -473,9 +278,6 @@ var toolbar = $( this.options.historyToolbarSelector).vde_historyToolbar().data('vde_historyToolbar'); if (toolbar) { toolbar.setHistory(history); - toolbar.option('baseUrl', this.options.baseUrl); - toolbar.option('compactLogUrl', this.options.compactLogUrl); - toolbar.option('viewLayoutUrl', this.options.viewLayoutUrl); } } }, @@ -493,10 +295,6 @@ }, _destroy: function() { //DOM structure can be missed when test executed - var panelContainer = $(this.options.panelSelector); - if (panelContainer.size()) { - panelContainer.vde_panel('destroy'); - } var toolbarContainer = $(this.options.historyToolbarSelector); if (toolbarContainer.length) { toolbarContainer.vde_historyToolbar('destroy'); @@ -531,9 +329,8 @@ .css('display', 'block') .find('a').bind('click', $.proxy(self._onRemoveButtonClick, self)); }, - _onRemoveButtonClick: function(e) { + _onRemoveButtonClick: function() { var change = $.fn.changeFactory.getInstance('layout'); - var block = this.element; change.setData({ action: 'remove', block: this.element.data('name'), @@ -552,4 +349,7 @@ } }); + $(document).ready(function( ){ + $(window).vde_connector(); + }); })( jQuery ); diff --git a/app/code/core/Mage/DesignEditor/view/frontend/js/settimeout_override.js b/app/code/core/Mage/DesignEditor/view/frontend/js/settimeout_override.js deleted file mode 100644 index c1e2859847c77a1eb4ae8681a0cd7f5c817a9e20..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/view/frontend/js/settimeout_override.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 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 Mage_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ - -(function() { - - var bindBeforeUnload = function() { - window.onbeforeunload = function(e) { - var e = e || window.event; - var messageText = 'Automatic redirect has been triggered.'; - // For IE and Firefox - if (e) { - e.returnValue = messageText; - } - // For Chrome and Safari - return messageText; - }; - } - - var unbindBeforeUnload = function () { - window.onbeforeunload = null; - } - - window.setTimeout = (function(oldSetTimeout) { - return function(func, delay) { - return oldSetTimeout(function() { - try { - bindBeforeUnload(); - func(); - unbindBeforeUnload(); - } - catch (exception) { - unbindBeforeUnload(); - throw exception; - } - }, delay); - }; - })(window.setTimeout); - - window.setInterval = (function(oldSetInterval) { - return function(func, delay) { - return oldSetInterval(function() { - try { - bindBeforeUnload(); - func(); - unbindBeforeUnload(); - } - catch (exception) { - unbindBeforeUnload(); - throw exception; - } - }, delay); - }; - })(window.setInterval); - -})(); diff --git a/app/code/core/Mage/DesignEditor/view/frontend/layout.xml b/app/code/core/Mage/DesignEditor/view/frontend/layout.xml index 522113e6a20b7d2183285219d3892b4bae82e934..addd373f8f119a9edde0d161abf234570ae16b08 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/layout.xml +++ b/app/code/core/Mage/DesignEditor/view/frontend/layout.xml @@ -26,35 +26,28 @@ */ --> <layout> - <design_editor_toolbar> - <reference name="head"> - <action method="addJs"><file>Mage_DesignEditor::js/settimeout_override.js</file></action> - <action method="addJs"><file>jquery/jquery-ui-1.9.0.custom.min.js</file></action> - <action method="addJs"><file>Mage_DesignEditor::js/base.js</file></action> + <designeditor_page_type> + <reference name="root"> + <block type="Mage_DesignEditor_Block_Page_Html_Head" name="head" as="head" /> + <block type="Mage_DesignEditor_Block_Page_Html_Head_Vde" name="vde_head" as="vde_head" /> + </reference> + + <reference name="vde_head"> + <action method="addJs"><file>jquery/jquery-1.7.1.min.js</file></action> + <action method="addJs"><file>mage/jquery-no-conflict.js</file></action> + <action method="addJs"><file>jquery/head.js</file></action> + <action method="addJs"><file>mage/mage.js</file></action> + <action method="addJs"><file>mage/decorate.js</file></action> + <action method="addJs"><file>mage/translate.js</file></action> + <action method="addJs"><file>jquery/ui/jquery-ui.js</file></action> + <action method="addJs"><file>jquery/jquery.tmpl.min.js</file></action> <action method="addJs"><file>Mage_DesignEditor::js/design_editor.js</file></action> <action method="addJs"><file>Mage_DesignEditor::js/change/layout.js</file></action> - <action method="addJs"><file>jquery/jstree/jquery.jstree.js</file></action> - <action method="addJs"><file>jquery/slimScroll/slimScroll.min.js</file></action> - <action method="addCss"><file>Mage_DesignEditor::css/styles.css</file></action> + <action method="addCss"><file>Mage_DesignEditor::css/design.css</file></action> </reference> - <!-- Toolbar block has been intentionally declared outside of containers to be rendered manually --> - <block type="Mage_DesignEditor_Block_Toolbar" name="design_editor_toolbar" template="toolbar.phtml"> - <block type="Mage_DesignEditor_Block_Toolbar_Breadcrumbs" name="design_editor_toolbar_breadcrumbs" template="toolbar/breadcrumbs.phtml"/> - <block type="Mage_DesignEditor_Block_Template" name="design_editor_toolbar_row" template="toolbar/row.phtml"> - <block type="Mage_DesignEditor_Block_Toolbar_HandlesHierarchy" name="design_editor_toolbar_handles_hierarchy" template="toolbar/handles_hierarchy.phtml"/> - <block type="Mage_DesignEditor_Block_Toolbar_Theme" name="design_editor_toolbar_theme" template="toolbar/theme.phtml"/> - <block type="Mage_DesignEditor_Block_Template" name="design_editor_toolbar_highlighting" template="toolbar/highlighting.phtml"/> - <block type="Mage_DesignEditor_Block_Toolbar_Buttons" name="design_editor_toolbar_buttons" template="toolbar/buttons.phtml"/> - <block type="Mage_DesignEditor_Block_Toolbar_History" name="design_editor_toolbar_history" template="toolbar/history.phtml"/> - </block> - </block> - </design_editor_toolbar> - <design_editor_page> - <reference name="root"> - <action method="setTemplate"><template>Mage_DesignEditor::page.phtml</template></action> - <block type="Mage_Page_Block_Html_Head" name="head" as="head"/> - <block type="Mage_DesignEditor_Block_Container" name="after_body_start" template="container.phtml"/> + <reference name="before_body_end"> + <block type="Mage_DesignEditor_Block_Toolbar_History" name="design_editor_toolbar_history" template="toolbar/history.phtml"/> </reference> - </design_editor_page> + </designeditor_page_type> </layout> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/breadcrumbs.phtml b/app/code/core/Mage/DesignEditor/view/frontend/toolbar/breadcrumbs.phtml deleted file mode 100644 index af23c6e3192ddc1e93ee44e9447bf7c77183990c..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/breadcrumbs.phtml +++ /dev/null @@ -1,41 +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 Mage_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<?php /** @var $this Mage_DesignEditor_Block_Toolbar_Breadcrumbs */ ?> -<div class="vde_breadcrumbs"> - <?php $isFirstItem = true; ?> - <?php foreach ($this->getBreadcrumbs() as $breadcrumb) : ?> - <?php if (!$isFirstItem) : ?> - <span class="vde_breadcrumbs_separator">/</span> - <?php endif; ?> - <?php if ($breadcrumb['url']) : ?> - <a href="<?php echo $breadcrumb['url']; ?>"><?php echo $breadcrumb['label']; ?></a> - <?php else : ?> - <span><?php echo $breadcrumb['label']; ?></span> - <?php endif; ?> - <?php $isFirstItem = false; ?> - <?php endforeach; ?> -</div> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/theme.phtml b/app/code/core/Mage/DesignEditor/view/frontend/toolbar/theme.phtml deleted file mode 100644 index 10883d7f52a0ad9bc684bf06c221fd4d45b0bdfa..0000000000000000000000000000000000000000 --- a/app/code/core/Mage/DesignEditor/view/frontend/toolbar/theme.phtml +++ /dev/null @@ -1,46 +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 Mage_DesignEditor - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ -?> -<?php /** @var $this Mage_DesignEditor_Block_Toolbar_Theme */ ?> -<div id="theme_selector" class="vde_toolbar_cell"> - <div class="vde_toolbar_cell_title"> - <?php echo $this->__('Theme:'); ?> - <span class="vde_toolbar_cell_value"><?php echo $this->escapeHtml($this->getTheme()->getThemeTitle()) ?></span> - </div> - <div class="vde_toolbar_cell_content"> - <dl id="<?php echo $this->getSelectHtmlId(); ?>"> - <?php foreach ($this->getTheme()->getCollection() as $theme): ?> - <?php $checked = $this->isThemeSelected($theme->getId()) ? ' checked' : '' ?> - <dd class="vde_cell_list_item<?php echo $checked ?>"> - <?php $url = $this->getUrl('design/editor/theme', array('_query' => array( - 'theme_id' => $theme->getId() - ))) ?> - <a href="<?php echo $url?>"><?php echo $this->escapeHtml($theme->getThemeTitle()) ?></a> - </dd> - <?php endforeach; ?> - </dl> - </div> -</div> diff --git a/app/code/core/Mage/DesignEditor/view/frontend/wrapping.phtml b/app/code/core/Mage/DesignEditor/view/frontend/wrapping.phtml index cb518638ba9248a30a5364bf307472edcf6f9f8e..02ce02ea8cd2e40814add4369e176756c7e57559 100644 --- a/app/code/core/Mage/DesignEditor/view/frontend/wrapping.phtml +++ b/app/code/core/Mage/DesignEditor/view/frontend/wrapping.phtml @@ -28,23 +28,16 @@ <?php $elementId = $this->getElementId(); $elementHtml = $this->getElementHtml(); -$hideWrapping = $this->isHighlightingDisabled(); $cssClass = 'vde_element_wrapper' . ($this->getIsManipulationAllowed() ? ' vde_draggable vde_removable' : '') - . ($this->getIsContainer() ? ' vde_container' : '') - . ($hideWrapping ? ' vde_wrapper_hidden' : ''); + . ($this->getIsContainer() ? ' vde_container' : ''); ?> <div id="<?php echo $elementId; ?>" class="<?php echo $cssClass; ?>" data-name="<?php echo $this->getElementName() ?>"> <div class="vde_element_title"><?php echo $this->getElementTitle() ?></div> <?php if ($this->getIsManipulationAllowed()): ?> <?php echo $this->getRemoveButton($elementId) ?> <?php endif; ?> - <?php if (!$hideWrapping) : ?> - <?php echo $elementHtml; ?> - <?php endif; ?> -</div> -<?php if ($hideWrapping && strlen($elementHtml)) : ?> <!--start_<?php echo $elementId; ?>--> <?php echo $elementHtml; ?> <!--end_<?php echo $elementId; ?>--> -<?php endif;?> +</div> diff --git a/app/code/core/Mage/GiftMessage/Helper/Message.php b/app/code/core/Mage/GiftMessage/Helper/Message.php index 14c0557c43e18e7003491c0e28bad607ee502c1c..60e5aeb7a41315e4058cb3af06de30edecbf2e24 100644 --- a/app/code/core/Mage/GiftMessage/Helper/Message.php +++ b/app/code/core/Mage/GiftMessage/Helper/Message.php @@ -71,7 +71,7 @@ class Mage_GiftMessage_Helper_Message extends Mage_Core_Helper_Data return ''; } - return Mage::getSingleton('Mage_Core_Model_Layout')->createBlock('Mage_GiftMessage_Block_Message_Inline') + return Mage::app()->getLayout()->createBlock('Mage_GiftMessage_Block_Message_Inline') ->setId('giftmessage_form_' . $this->_nextId++) ->setDontDisplayContainer($dontDisplayContainer) ->setEntity($entity) diff --git a/app/code/core/Mage/Install/Controller/Action.php b/app/code/core/Mage/Install/Controller/Action.php index f45efa4d3d52b61da6f0b9c9c7f97d523ea84f1c..6c61d248c580b69f52c41c491fbdce97a06a6fee 100644 --- a/app/code/core/Mage/Install/Controller/Action.php +++ b/app/code/core/Mage/Install/Controller/Action.php @@ -27,16 +27,11 @@ class Mage_Install_Controller_Action extends Mage_Core_Controller_Varien_Action { - /** - * Currently used area - * - * @var string - */ - protected $_currentArea = 'install'; - protected function _construct() { parent::_construct(); + + $this->setCurrentArea('install'); $this->setFlag('', self::FLAG_NO_CHECK_INSTALLATION, true); } diff --git a/app/code/core/Mage/Oauth/view/adminhtml/layout.xml b/app/code/core/Mage/Oauth/view/adminhtml/layout.xml index 4f8931147fda0cfe29221bb29da425bd9ce4243c..b34dd97682273fab4be4ab0210c968912b98915f 100644 --- a/app/code/core/Mage/Oauth/view/adminhtml/layout.xml +++ b/app/code/core/Mage/Oauth/view/adminhtml/layout.xml @@ -87,7 +87,7 @@ <action method="removeItem"><type>js</type><name>varien/js.js</name></action> <action method="removeItem"><type>js</type><name>mage/adminhtml/hash.js</name></action> <action method="removeItem"><type>js</type><name>mage/adminhtml/events.js</name></action> - <action method="removeItem"><type>js</type><name>mage/adminhtml/loader.js</name></action> + <action method="removeItem"><type>js</type><name>mage/adminhtml/varienLoader.js</name></action> <action method="removeItem"><type>js</type><name>mage/adminhtml/grid.js</name></action> <action method="removeItem"><type>js</type><name>mage/adminhtml/tabs.js</name></action> <action method="removeItem"><type>js</type><name>mage/adminhtml/accordion.js</name></action> diff --git a/app/code/core/Mage/Page/Block/Template/Links.php b/app/code/core/Mage/Page/Block/Template/Links.php index a5d6b80fee135b01ae415390c8a5b318631090c6..814e7f5e52f0d179f8b369e6ecf3a10d883edefc 100644 --- a/app/code/core/Mage/Page/Block/Template/Links.php +++ b/app/code/core/Mage/Page/Block/Template/Links.php @@ -75,25 +75,25 @@ class Mage_Page_Block_Template_Links extends Mage_Core_Block_Template * @param string $afterText * @return Mage_Page_Block_Template_Links */ - public function addLink($label, $url='', $title='', $prepare=false, $urlParams=array(), - $position=null, $liParams=null, $aParams=null, $beforeText='', $afterText='') - { - if (is_null($label) || false===$label) { + public function addLink($label, $url = '', $title = '', $prepare = true, $urlParams = array(), + $position = null, $liParams = null, $aParams = null, $beforeText = '', $afterText = '' + ) { + if (is_null($label) || false === $label) { return $this; } $link = new Varien_Object(array( - 'label' => $label, - 'url' => ($prepare ? $this->getUrl($url, (is_array($urlParams) ? $urlParams : array())) : $url), - 'title' => $title, - 'li_params' => $this->_prepareParams($liParams), - 'a_params' => $this->_prepareParams($aParams), - 'before_text' => $beforeText, - 'after_text' => $afterText, + 'label' => $label, + 'url' => ($prepare ? $this->getUrl($url, (is_array($urlParams) ? $urlParams : array())) : $url), + 'title' => $title, + 'li_params' => $this->_prepareParams($liParams), + 'a_params' => $this->_prepareParams($aParams), + 'before_text' => $beforeText, + 'after_text' => $afterText, )); $this->_links[$this->_getNewPosition($position)] = $link; if (intval($position) > 0) { - ksort($this->_links); + ksort($this->_links); } return $this; diff --git a/app/code/core/Mage/Page/view/frontend/template/links.phtml b/app/code/core/Mage/Page/view/frontend/template/links.phtml index c488598a9c72c7c8728d989595f5d2e73289fec7..42aff1bb3ec8bc48d26eff23c779a5f337628b46 100644 --- a/app/code/core/Mage/Page/view/frontend/template/links.phtml +++ b/app/code/core/Mage/Page/view/frontend/template/links.phtml @@ -27,6 +27,7 @@ <?php /** * @see Mage_Page_Block_Template_Links + * @var $this Mage_Page_Block_Template_Links */ ?> <?php $_links = $this->getLinks(); ?> diff --git a/app/code/core/Mage/PageCache/Model/Observer.php b/app/code/core/Mage/PageCache/Model/Observer.php index be8da7486db5a96d4d67f4550762cae4fd1c2836..9bfe434d314c4426cc710df2b9a1d52e079bc3e4 100644 --- a/app/code/core/Mage/PageCache/Model/Observer.php +++ b/app/code/core/Mage/PageCache/Model/Observer.php @@ -105,12 +105,12 @@ class Mage_PageCache_Model_Observer } /** - * Temporary disabling full page caching if Design Editor was launched. + * Temporary disabling full page caching by setting bo-cache cookie * * @param Varien_Event_Observer $observer * @return Mage_PageCache_Model_Observer */ - public function designEditorSessionActivate(Varien_Event_Observer $observer) + public function setNoCacheCookie(Varien_Event_Observer $observer) { if (!$this->isCacheEnabled()) { return $this; @@ -120,12 +120,12 @@ class Mage_PageCache_Model_Observer } /** - * Activating full page cache after Design Editor was deactivated + * Activating full page cache aby deleting no-cache cookie * * @param Varien_Event_Observer $observer * @return Mage_PageCache_Model_Observer */ - public function designEditorSessionDeactivate(Varien_Event_Observer $observer) + public function deleteNoCacheCookie(Varien_Event_Observer $observer) { if (!$this->isCacheEnabled()) { return $this; diff --git a/app/code/core/Mage/PageCache/etc/config.xml b/app/code/core/Mage/PageCache/etc/config.xml index 88633eef92487035be3d632dd37eec1285175212..7b178b40a258f1a5a281bfdb95a2ba377489090b 100644 --- a/app/code/core/Mage/PageCache/etc/config.xml +++ b/app/code/core/Mage/PageCache/etc/config.xml @@ -46,22 +46,22 @@ </controls> </external_cache> <events> - <design_editor_session_activate> + <design_editor_activate> <observers> <mage_pagecache> <class>Mage_PageCache_Model_Observer</class> - <method>designEditorSessionActivate</method> + <method>setNoCacheCookie</method> </mage_pagecache> </observers> - </design_editor_session_activate> - <design_editor_session_deactivate> + </design_editor_activate> + <design_editor_deactivate> <observers> <mage_pagecache> <class>Mage_PageCache_Model_Observer</class> - <method>designEditorSessionDeactivate</method> + <method>deleteNoCacheCookie</method> </mage_pagecache> </observers> - </design_editor_session_deactivate> + </design_editor_deactivate> </events> </global> <adminhtml> diff --git a/app/code/core/Mage/Paypal/Helper/Hss.php b/app/code/core/Mage/Paypal/Helper/Hss.php index 2130fcab1a527a9551208af32b00baf7de348ba3..29030c7ca8a85b001dffc1129ded037950e55d14 100644 --- a/app/code/core/Mage/Paypal/Helper/Hss.php +++ b/app/code/core/Mage/Paypal/Helper/Hss.php @@ -57,7 +57,7 @@ class Mage_Paypal_Helper_Hss extends Mage_Core_Helper_Abstract } } - if ($blockObject = Mage::getSingleton('Mage_Core_Model_Layout')->getBlock($block)) { + if ($blockObject = Mage::app()->getLayout()->getBlock($block)) { return $blockObject->getTemplate(); } diff --git a/app/code/core/Mage/Persistent/Model/Persistent/Config.php b/app/code/core/Mage/Persistent/Model/Persistent/Config.php index 7173e5f08b5b3e6178bad84b689f165001167268..c20517be48600c05a53bba0c5975140a74b2e395 100644 --- a/app/code/core/Mage/Persistent/Model/Persistent/Config.php +++ b/app/code/core/Mage/Persistent/Model/Persistent/Config.php @@ -104,7 +104,7 @@ class Mage_Persistent_Model_Persistent_Config foreach ($elements as $info) { switch ($type) { case 'blocks': - $this->fireOne($info, Mage::getSingleton('Mage_Core_Model_Layout')->getBlock($info['name_in_layout'])); + $this->fireOne($info, Mage::app()->getLayout()->getBlock($info['name_in_layout'])); break; } } diff --git a/app/code/core/Mage/Rss/view/frontend/layout.xml b/app/code/core/Mage/Rss/view/frontend/layout.xml index 0554bf830b14fec5b5c1e3c82f48b25d7aeff2d0..9478b8caeecbc2102478a1c1ef09be067619c805 100644 --- a/app/code/core/Mage/Rss/view/frontend/layout.xml +++ b/app/code/core/Mage/Rss/view/frontend/layout.xml @@ -31,7 +31,7 @@ --> <default> <reference name="footer_links"> - <action method="addLink" translate="label title" module="Mage_Rss" ifconfig="rss/config/active"><label>RSS</label><url>rss</url><title>RSS</title><prepare>true</prepare><urlParams/><position/><li/><a>class="link-rss"</a></action> + <action method="addLink" translate="label title" module="Mage_Rss" ifconfig="rss/config/active"><label>RSS</label><url>rss</url><title>RSS</title><urlParams/><position/><li/><a>class="link-rss"</a></action> </reference> <block type="Mage_Rss_Block_List" name="head_rss" ifconfig="rss/config/active" /> </default> diff --git a/app/code/core/Mage/Theme/Block/Adminhtml/System/Design/Theme/Grid.php b/app/code/core/Mage/Theme/Block/Adminhtml/System/Design/Theme/Grid.php index be07927cd5396d1033552aa7b70656ef1575cb00..431ecab5e94f4d722de9fffbef5372907594dbf9 100644 --- a/app/code/core/Mage/Theme/Block/Adminhtml/System/Design/Theme/Grid.php +++ b/app/code/core/Mage/Theme/Block/Adminhtml/System/Design/Theme/Grid.php @@ -63,39 +63,45 @@ class Mage_Theme_Block_Adminhtml_System_Design_Theme_Grid extends Mage_Adminhtml protected function _prepareColumns() { $this->addColumn('theme_title', array( - 'header' => $this->__('Theme Title'), - 'index' => 'theme_title', - 'filter_index' => 'main_table.theme_title', + 'header' => $this->__('Theme Title'), + 'index' => 'theme_title', + 'filter_index' => 'main_table.theme_title', + 'column_css_class' => 'theme-title' )); $this->addColumn('parent_theme_title', array( - 'header' => $this->__('Parent Theme'), - 'index' => 'parent_theme_title', - 'filter_index' => 'parent.theme_title' + 'header' => $this->__('Parent Theme'), + 'index' => 'parent_theme_title', + 'filter_index' => 'parent.theme_title', + 'column_css_class' => 'parent-theme-title' )); $this->addColumn('theme_path', array( - 'header' => $this->__('Theme Path'), - 'index' => 'theme_path', - 'filter_index' => 'main_table.theme_path' + 'header' => $this->__('Theme Path'), + 'index' => 'theme_path', + 'filter_index' => 'main_table.theme_path', + 'column_css_class' => 'theme-path' )); $this->addColumn('theme_version', array( - 'header' => $this->__('Theme Version'), - 'index' => 'theme_version', - 'filter_index' => 'main_table.theme_version' + 'header' => $this->__('Theme Version'), + 'index' => 'theme_version', + 'filter_index' => 'main_table.theme_version', + 'column_css_class' => 'theme-version' )); $this->addColumn('magento_version_from', array( - 'header' => $this->__('Magento Version From'), - 'index' => 'magento_version_from', - 'filter_index' => 'main_table.magento_version_from' + 'header' => $this->__('Magento Version From'), + 'index' => 'magento_version_from', + 'filter_index' => 'main_table.magento_version_from', + 'column_css_class' => 'magento-version-from' )); $this->addColumn('magento_version_to', array( - 'header' => $this->__('Magento Version To'), - 'index' => 'magento_version_to', - 'filter_index' => 'main_table.magento_version_to' + 'header' => $this->__('Magento Version To'), + 'index' => 'magento_version_to', + 'filter_index' => 'main_table.magento_version_to', + 'column_css_class' => 'magento-version-to' )); return parent::_prepareColumns(); diff --git a/app/code/core/Mage/Theme/controllers/Adminhtml/System/Design/ThemeController.php b/app/code/core/Mage/Theme/controllers/Adminhtml/System/Design/ThemeController.php index fc42a401bc6b0796be86cc929bb8855bdfd818de..82c8cd4a58666f045e37ad0c2515a5a7f9cfcf90 100644 --- a/app/code/core/Mage/Theme/controllers/Adminhtml/System/Design/ThemeController.php +++ b/app/code/core/Mage/Theme/controllers/Adminhtml/System/Design/ThemeController.php @@ -114,6 +114,7 @@ class Mage_Theme_Adminhtml_System_Design_ThemeController extends Mage_Adminhtml_ */ public function deleteAction() { + $redirectBack = (bool)$this->getRequest()->getParam('back', false); $themeId = $this->getRequest()->getParam('id'); try { if ($themeId) { @@ -126,7 +127,10 @@ class Mage_Theme_Adminhtml_System_Design_ThemeController extends Mage_Adminhtml_ $this->_getSession()->addException($e, $this->__('Cannot delete the theme.')); Mage::logException($e); } - $this->_redirect('*/*/'); + /** + * @todo Temporary solution. Theme module should not know about the existence of editor module. + */ + $redirectBack ? $this->_redirect('*/system_design_editor/index/') : $this->_redirect('*/*/'); } /** diff --git a/app/code/core/Mage/User/view/adminhtml/admin/forgotpassword.phtml b/app/code/core/Mage/User/view/adminhtml/admin/forgotpassword.phtml index 9c172acf3fd4b9609aa3fff9c0b52a2aba9b2d86..70f5ce2f8542edaef68032d4bf99474b8aa2de69 100644 --- a/app/code/core/Mage/User/view/adminhtml/admin/forgotpassword.phtml +++ b/app/code/core/Mage/User/view/adminhtml/admin/forgotpassword.phtml @@ -35,7 +35,7 @@ <link rel="shortcut icon" href="<?php echo $this->getViewFileUrl('Mage_Page::favicon.ico'); ?>" type="image/x-icon" /> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-1.8.2.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('mage/jquery-no-conflict.js') ?>"></script> - <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-ui-1.9.1.custom.min.js') ?>"></script> + <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-ui-1.9.2.custom.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery.tmpl.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery.validate.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('mage/validation.js') ?>"></script> diff --git a/app/code/core/Mage/User/view/adminhtml/admin/resetforgottenpassword.phtml b/app/code/core/Mage/User/view/adminhtml/admin/resetforgottenpassword.phtml index 8f2cb7ab66e8279124146763737e4d30e92a84c8..964d37e6f5f7848d48fd5155822f6854cc89663d 100644 --- a/app/code/core/Mage/User/view/adminhtml/admin/resetforgottenpassword.phtml +++ b/app/code/core/Mage/User/view/adminhtml/admin/resetforgottenpassword.phtml @@ -36,7 +36,7 @@ <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-1.8.2.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('mage/jquery-no-conflict.js') ?>"></script> - <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-ui-1.9.1.custom.min.js') ?>"></script> + <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery-ui-1.9.2.custom.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery.tmpl.min.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('jquery/jquery.validate.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getViewFileUrl('mage/validation.js') ?>"></script> diff --git a/app/code/core/Mage/Webapi/Model/ConfigAbstract.php b/app/code/core/Mage/Webapi/Model/ConfigAbstract.php index 49ec164803cc3657a86141dc3d5a655db330ba17..5d46e73b36d91daa41190ac3ff22f9fdb21e3f64 100644 --- a/app/code/core/Mage/Webapi/Model/ConfigAbstract.php +++ b/app/code/core/Mage/Webapi/Model/ConfigAbstract.php @@ -207,7 +207,7 @@ abstract class Mage_Webapi_Model_ConfigAbstract */ public function getTypeToClassMap() { - return $this->_data['type_to_class_map']; + return !is_null($this->_data['type_to_class_map']) ? $this->_data['type_to_class_map'] : array(); } /** diff --git a/app/design/adminhtml/default/basic/boxes.css b/app/design/adminhtml/default/basic/boxes.css index c7742b01b15484894994f9a8c8f5d634a633a92e..abe64804507ed13d8757226d64ef48d0a3561632 100644 --- a/app/design/adminhtml/default/basic/boxes.css +++ b/app/design/adminhtml/default/basic/boxes.css @@ -269,12 +269,16 @@ ul.tabs a, ul.tabs a:hover { text-decoration:none; } ul.tabs a, ul.tabs a:hover { color:#000; } ul.tabs, ul.tabs a { background:url(images/tabs_link_bg.gif) repeat-y 100% #E7EFEF; } ul.tabs a:hover { background-color:#D8E6E6; background-image:url(images/tabs_link_over_bg.gif); } -ul.tabs a.active { padding:0; border-bottom:1px solid #bebebe; background:none; } -ul.tabs a:hover.active { padding:0; } +ul.tabs a.active, +ul.tabs .ui-state-active a { padding:0; border-bottom:1px solid #bebebe; background:none; } +ul.tabs a:hover.active, +ul.tabs .ui-state-active a:hover { padding:0; } ul.tabs span { background:url(images/tabs_span_bg.gif) repeat-x 0 100%; padding:.3em 0.5em .28em 1.5em; cursor:pointer; } ul.tabs span em { float:right; } ul.tabs a.active span, -ul.tabs a:hover.active span { background:#fff; font-weight:bold; } +ul.tabs a:hover.active span, +ul.tabs .ui-state-active a span, +ul.tabs .ui-state-active a:hover span { background:#fff; font-weight:bold; } ul.tabs a.subitem { padding-left:2.2em; } ul.tabs span.changed, ul.tabs span.error { float:right; background:0; padding:0; } @@ -287,7 +291,8 @@ ul.tabs-horiz { margin:0 0 18px 0; background:url(images/horiz ul.tabs-horiz li { float:left; margin:0 4px; } ul.tabs-horiz li a { display:block; background:#e2e2e2; border:1px solid #ccc; padding:2px 10px; color:#333 !important; text-decoration:none !important; } ul.tabs-horiz li a.notloaded { /* not used for now */ } -ul.tabs-horiz li a.active { border-bottom:1px solid #fff; background:#fff; } +ul.tabs-horiz li a.active, +ul.tabs-horiz .ui-state-active a { border-bottom:1px solid #fff; background:#fff; } /* MESSAGES diff --git a/app/design/frontend/default/iphone/Mage_Contacts/layout.xml b/app/design/frontend/default/iphone/Mage_Contacts/layout.xml index baa1507312e12a02794e28b39b5f1bc137cbecf1..d08b850b47055c6df39b9179e0782059ddd42e1e 100644 --- a/app/design/frontend/default/iphone/Mage_Contacts/layout.xml +++ b/app/design/frontend/default/iphone/Mage_Contacts/layout.xml @@ -28,7 +28,7 @@ <layout version="0.1.0"> <default> <reference name="footer_links"> - <action method="addLink" translate="label title" module="Mage_Contacts" ifconfig="contacts/contacts/enabled"><label>Contact Us</label><url>contacts</url><title>Contact Us</title><prepare>true</prepare></action> + <action method="addLink" translate="label title" module="Mage_Contacts" ifconfig="contacts/contacts/enabled"><label>Contact Us</label><url>contacts</url><title>Contact Us</title></action> </reference> </default> diff --git a/app/design/frontend/default/modern/Mage_Contacts/layout.xml b/app/design/frontend/default/modern/Mage_Contacts/layout.xml index aab9199270b5fbcfadcd1f8e03f0a4aa6dc10898..af7a554e988c93721d1df36e067e287bd8976204 100644 --- a/app/design/frontend/default/modern/Mage_Contacts/layout.xml +++ b/app/design/frontend/default/modern/Mage_Contacts/layout.xml @@ -28,7 +28,7 @@ <layout version="0.1.0"> <default> <reference name="footer_links"> - <action method="addLink" translate="label title" module="Mage_Contacts" ifconfig="contacts/contacts/enabled"><label>Contact Us</label><url>contacts</url><title>Contact Us</title><prepare>true</prepare></action> + <action method="addLink" translate="label title" module="Mage_Contacts" ifconfig="contacts/contacts/enabled"><label>Contact Us</label><url>contacts</url><title>Contact Us</title></action> </reference> </default> diff --git a/app/design/frontend/default/modern/Mage_Rss/layout.xml b/app/design/frontend/default/modern/Mage_Rss/layout.xml index 89ee62a998f979cd27e927195110fdf2b9e59bb6..d2e8220e4e6bd389162478da9efd5254d14811e6 100644 --- a/app/design/frontend/default/modern/Mage_Rss/layout.xml +++ b/app/design/frontend/default/modern/Mage_Rss/layout.xml @@ -28,7 +28,7 @@ <layout version="0.1.0"> <default> <reference name="footer_links"> - <action method="addLink" translate="label title" module="Mage_Rss" ifconfig="rss/config/active"><label>RSS</label><url>rss</url><title>RSS</title><prepare>true</prepare><urlParams/><position/><li/><a>class="link-rss"</a></action> + <action method="addLink" translate="label title" module="Mage_Rss" ifconfig="rss/config/active"><label>RSS</label><url>rss</url><title>RSS</title><urlParams/><position/><li/><a>class="link-rss"</a></action> </reference> <block type="Mage_Rss_Block_List" name="head_rss" ifconfig="rss/config/active" /> </default> diff --git a/dev/api-tests/integration/etc/local-mysql.xml.dist b/dev/api-tests/integration/etc/local-mysql.xml.dist deleted file mode 100644 index a59c35ed33d69b41894f50bdc8bfc4820e1341cc..0000000000000000000000000000000000000000 --- a/dev/api-tests/integration/etc/local-mysql.xml.dist +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * 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 Magento - * @package Magento - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<config> - <global> - <install> - <!-- Important: validity of installation date indicates whether an application is installed or not --> - <date><![CDATA[d-d-d-d-d]]></date> - </install> - <crypt> - <key><![CDATA[k-k-k-k-k]]></key> - </crypt> - <disable_local_modules>false</disable_local_modules> - <resources> - <db> - <table_prefix><![CDATA[]]></table_prefix> - </db> - <default_setup> - <connection> - <host><![CDATA[localhost]]></host> - <username><![CDATA[root]]></username> - <password><![CDATA[]]></password> - <dbname><![CDATA[magento_integration_tests]]></dbname> - <initStatements><![CDATA[SET NAMES utf8]]></initStatements> - <model><![CDATA[mysql4]]></model> - <type><![CDATA[pdo_mysql]]></type> - <pdoType><![CDATA[]]></pdoType> - <active>1</active> - </connection> - </default_setup> - </resources> - <session_save><![CDATA[files]]></session_save> - </global> - <admin> - <routers> - <adminhtml> - <args> - <frontName><![CDATA[admin]]></frontName> - </args> - </adminhtml> - </routers> - </admin> -</config> diff --git a/dev/build/publication/extruder/ce.txt b/dev/build/publication/extruder/ce.txt index 4306a0d6b9545d120330402ac79f0691bcf7f76e..8e48d9abae70f56b3e8b28ddb4d864ae2a527124 100644 --- a/dev/build/publication/extruder/ce.txt +++ b/dev/build/publication/extruder/ce.txt @@ -14,6 +14,7 @@ app/design/install/default/enterprise app/design/install/default/pro app/etc/enterprise.xml app/etc/modules +app/etc/aliases_to_classes_map.json dev/tests/integration/etc/modules/XEnterprise_Enabler.xml dev/tests/integration/testsuite/Enterprise dev/tests/integration/testsuite/integrity/modular/ViewFilesTest.php diff --git a/dev/tests/integration/framework/Magento/Test/ObjectManager.php b/dev/tests/integration/framework/Magento/Test/ObjectManager.php index f71f57f6473da8242b28960fd24b5638eb262542..b07495bf2c346fcde69cb3811a1ecfd31913048b 100644 --- a/dev/tests/integration/framework/Magento/Test/ObjectManager.php +++ b/dev/tests/integration/framework/Magento/Test/ObjectManager.php @@ -39,17 +39,6 @@ class Magento_Test_ObjectManager extends Magento_ObjectManager_Zend 'Mage_Core_Model_Layout_ScheduledStructure', ); - /** - * @param string $definitionsFile - * @param Zend\Di\Di $diInstance - */ - public function __construct($definitionsFile = null, Zend\Di\Di $diInstance = null) - { - $diInstance = $diInstance ? $diInstance : new Magento_Di(); - $diInstance->setInstanceManager(new Magento_Test_Di_InstanceManager()); - parent::__construct($definitionsFile, $diInstance); - } - /** * Clear InstanceManager cache * @@ -58,48 +47,20 @@ class Magento_Test_ObjectManager extends Magento_ObjectManager_Zend public function clearCache() { foreach ($this->_classesToDestruct as $className) { - $object = $this->get($className); - if ($object) { - // force to cleanup circular references - $object->__destruct(); + if ($this->hasSharedInstance($className)) { + $object = $this->get($className); + if ($object) { + // force to cleanup circular references + $object->__destruct(); + } } } $resource = $this->get('Mage_Core_Model_Resource'); - $this->_di->setInstanceManager(new Magento_Test_Di_InstanceManager()); + $this->_di->setInstanceManager(new Magento_Di_InstanceManager_Zend()); $this->addSharedInstance($this, 'Magento_ObjectManager'); $this->addSharedInstance($resource, 'Mage_Core_Model_Resource'); return $this; } - - /** - * Add shared instance - * - * @param object $instance - * @param string $classOrAlias - * @return Magento_Test_ObjectManager - * @throws Zend\Di\Exception\InvalidArgumentException - */ - public function addSharedInstance($instance, $classOrAlias) - { - $this->_di->instanceManager()->addSharedInstance($instance, $classOrAlias); - - return $this; - } - - /** - * Remove shared instance - * - * @param string $classOrAlias - * @return Magento_Test_ObjectManager - */ - public function removeSharedInstance($classOrAlias) - { - /** @var $instanceManager Magento_Test_Di_InstanceManager */ - $instanceManager = $this->_di->instanceManager(); - $instanceManager->removeSharedInstance($classOrAlias); - - return $this; - } } diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/ObjectManagerTest.php b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/ObjectManagerTest.php index aed1bdcfc8740bfe314e6f02c8cd129347a3f91b..067c3c0071f99df4d8da47ab00e43ad13f36619b 100644 --- a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/ObjectManagerTest.php +++ b/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/ObjectManagerTest.php @@ -36,7 +36,7 @@ class Magento_Test_ObjectManagerTest extends PHPUnit_Framework_TestCase const TEST_RESOURCE = 'test_resource'; /** - * ObjectManager instance for tests + * ObjectManager mock for tests * * @var Magento_Test_ObjectManager */ @@ -65,47 +65,68 @@ class Magento_Test_ObjectManagerTest extends PHPUnit_Framework_TestCase unset($this->_classesToDestruct); } - public function testClearCache() + /** + * @param bool $shared + * @dataProvider clearCacheDataProvider + */ + public function testClearCache($shared) { - $this->_prepareObjectManagerForClearCache(); + $this->_prepareObjectManagerForClearCache($shared); $this->_model->clearCache(); - $this->assertAttributeEquals($this->_classesToDestruct, '_classesToDestruct', $this->_model); + } + + /** + * @return array + */ + public function clearCacheDataProvider() + { + return array( + 'noSharedInstances' => array(false), + 'withSharedInstances' => array(true), + ); } /** * Prepare all required mocks for clearCache + * @param $shared */ - protected function _prepareObjectManagerForClearCache() + protected function _prepareObjectManagerForClearCache($shared) { - $diInstance = $this->getMock('Zend\Di\Di', array('get', 'instanceManager', 'setInstanceManager')); + $diInstance = $this->getMock('Magento_Di_Zend', array('get', 'instanceManager', 'setInstanceManager')); $instanceManager = $this->getMock( - 'Magento_Test_Di_InstanceManager', array('addSharedInstance'), array(), '', false + 'Magento_Di_InstanceManager_Zend', array('addSharedInstance', 'hasSharedInstance'), array(), '', false ); - $diInstance->expects($this->exactly(3)) + $diInstance->expects($this->exactly(7)) ->method('instanceManager') ->will($this->returnValue($instanceManager)); - $diInstance->expects($this->exactly(5)) + + $instanceManager->expects($this->any()) + ->method('hasSharedInstance') + ->will($this->returnValue($shared)); + + $getCallCount = $shared ? 5 : 1; + $diInstance->expects($this->exactly($getCallCount)) ->method('get') ->will($this->returnCallback(array($this, 'getCallback'))); - $diInstance->expects($this->exactly(2)) + $diInstance->expects($this->any()) ->method('setInstanceManager') - ->will($this->returnCallback(array($this, 'verifySetInstanceManager'))); + ->will($this->returnSelf()); $this->_model = new Magento_Test_ObjectManager(null, $diInstance); $instanceManager->expects($this->exactly(2)) ->method('addSharedInstance'); - $instanceManager->expects($this->at(0)) + $instanceManager->expects($this->at(4)) ->method('addSharedInstance') ->with($this->_model, 'Magento_ObjectManager'); - $instanceManager->expects($this->at(1)) + $instanceManager->expects($this->at(5)) ->method('addSharedInstance') ->with(self::TEST_RESOURCE, 'Mage_Core_Model_Resource'); } /** - * Callback method for Zend\Di\Di::get + * Callback method for Magento_Di_Zend::get * * @param string $className * @return PHPUnit_Framework_MockObject_MockObject|string @@ -115,85 +136,11 @@ class Magento_Test_ObjectManagerTest extends PHPUnit_Framework_TestCase if ($className != 'Mage_Core_Model_Resource') { $this->_classesToDestruct[] = $className; $mock = $this->getMock($className, array('__destruct'), array(), '', false); + $mock->expects($this->once()) + ->method('__destruct'); return $mock; } else { return self::TEST_RESOURCE; } } - - /** - * Callback method for Zend\Di\Di::setInstanceManager - * - * @param \Zend\Di\InstanceManager $instanceManager - */ - public function verifySetInstanceManager($instanceManager) - { - $this->assertInstanceOf('Magento_Test_Di_InstanceManager', $instanceManager); - $this->assertAttributeEmpty('sharedInstances', $instanceManager); - $this->assertAttributeEquals($this->_instanceCache, 'sharedInstancesWithParams', $instanceManager); - } - - public function testAddSharedInstance() - { - $object = new Varien_Object(); - $alias = 'Varien_Object_Alias'; - - $this->_prepareObjectManagerForAddSharedInstance($object, $alias); - $this->_model->addSharedInstance($object, $alias); - } - - /** - * Prepare all required mocks for addSharedInstance - * - * @param object $instance - * @param string $classOrAlias - */ - protected function _prepareObjectManagerForAddSharedInstance($instance, $classOrAlias) - { - $diInstance = $this->getMock('Zend\Di\Di', array('instanceManager')); - $instanceManager = $this->getMock( - 'Magento_Test_Di_InstanceManager', array('addSharedInstance'), array(), '', false - ); - - $instanceManager->expects($this->exactly(2)) - ->method('addSharedInstance'); - $instanceManager->expects($this->at(1)) - ->method('addSharedInstance') - ->with($instance, $classOrAlias); - $diInstance->expects($this->exactly(2)) - ->method('instanceManager') - ->will($this->returnValue($instanceManager)); - - $this->_model = new Magento_Test_ObjectManager(null, $diInstance); - } - - public function testRemoveSharedInstance() - { - $alias = 'Varien_Object_Alias'; - - $this->_prepareObjectManagerForRemoveSharedInstance($alias); - $this->_model->removeSharedInstance($alias); - } - - /** - * Prepare all required mocks for removeSharedInstance - * - * @param string $classOrAlias - */ - protected function _prepareObjectManagerForRemoveSharedInstance($classOrAlias) - { - $diInstance = $this->getMock('Zend\Di\Di', array('instanceManager')); - $instanceManager = $this->getMock( - 'Magento_Test_Di_InstanceManager', array('removeSharedInstance'), array(), '', false - ); - - $instanceManager->expects($this->once()) - ->method('removeSharedInstance') - ->with($classOrAlias); - $diInstance->expects($this->exactly(2)) - ->method('instanceManager') - ->will($this->returnValue($instanceManager)); - - $this->_model = new Magento_Test_ObjectManager(null, $diInstance); - } } diff --git a/dev/tests/integration/testsuite/Mage/Adminhtml/Controller/ActionTest.php b/dev/tests/integration/testsuite/Mage/Adminhtml/Controller/ActionTest.php index 13dc8e67772c8c8f29b6f7df6bf793001d7e519c..da999139cb6bfa70ef8ab8a288f37519c4c063ae 100644 --- a/dev/tests/integration/testsuite/Mage/Adminhtml/Controller/ActionTest.php +++ b/dev/tests/integration/testsuite/Mage/Adminhtml/Controller/ActionTest.php @@ -39,8 +39,10 @@ class Mage_Adminhtml_Controller_ActionTest extends Magento_Test_TestCase_Control array( 'request' => new Magento_Test_Request(), 'response' => new Magento_Test_Response(), + 'areaCode' => 'adminhtml', 'objectManager' => Mage::getObjectManager(), - 'frontController' => Mage::getModel('Mage_Core_Controller_Varien_Front') + 'frontController' => Mage::getObjectManager()->get('Mage_Core_Controller_Varien_Front'), + 'layoutFactory' => Mage::getObjectManager()->get('Mage_Core_Model_Layout_Factory') ) ); } diff --git a/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php b/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php index a0f4bcb42cbf438ecf15192ab57f4413bdeea5a0..5b6f80221cb14f5e449627d30b04385016c399b9 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Block/System/Config/FormTest.php @@ -136,7 +136,9 @@ class Mage_Backend_Block_System_Config_FormTest extends PHPUnit_Framework_TestCa { Mage::getModel( 'Mage_Core_Controller_Front_Action', - array('request' => Mage::app()->getRequest(), 'response' => Mage::app()->getResponse()) + array('request' => Mage::app()->getRequest(), 'response' => Mage::app()->getResponse(), + 'areaCode' => 'adminhtml' + ) ); Mage::app()->getRequest()->setParam('section', 'general'); /** @var $block Mage_Backend_Block_System_Config_Form */ diff --git a/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/DefaultTest.php b/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/DefaultTest.php index e949a7c6d19d19cea827f52055656440a179b655..bae597808cd9ebd131aa6799b5459e5a63a292f2 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/DefaultTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/DefaultTest.php @@ -40,12 +40,11 @@ class Mage_Backend_Controller_Router_DefaultTest extends PHPUnit_Framework_TestC protected function setUp() { $options = array( - 'area' => Mage::helper('Mage_Backend_Helper_Data')->getAreaCode(), - 'base_controller' => 'Mage_Backend_Controller_ActionAbstract', - 'frontName' => 'backend' + 'areaCode' => Mage::helper('Mage_Backend_Helper_Data')->getAreaCode(), + 'baseController' => 'Mage_Backend_Controller_ActionAbstract', ); - $this->_frontMock = $this->getMock('Mage_Core_Controller_Varien_Front'); - $this->_model = Mage::getModel('Mage_Backend_Controller_Router_Default', array('options' => $options)); + $this->_frontMock = $this->getMock('Mage_Core_Controller_Varien_Front', array(), array(), '', false); + $this->_model = Mage::getModel('Mage_Backend_Controller_Router_Default', $options); $this->_model->setFront($this->_frontMock); } diff --git a/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/Validator/DefaultTest.php b/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/Validator/DefaultTest.php index b7b1d1d22a5b015461834961a2dae63eea45c26b..29d63a59556de2552547d52eb79c18f31967de51 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/Validator/DefaultTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/Controller/Router/Validator/DefaultTest.php @@ -38,11 +38,11 @@ class Mage_Backend_Controller_Router_Validator_DefaultTest extends PHPUnit_Frame public function testConstructWithEmptyAreaFrontName() { $options = array( - 'area' => Mage::helper('Mage_Backend_Helper_Data')->getAreaCode(), - 'base_controller' => 'Mage_Backend_Controller_ActionAbstract', + 'areaCode' => Mage::helper('Mage_Backend_Helper_Data')->getAreaCode(), + 'baseController' => 'Mage_Backend_Controller_ActionAbstract', 'frontName' => 'backend' ); - Mage::getModel('Mage_Backend_Controller_Router_Default', array('options' => $options)); + Mage::getModel('Mage_Backend_Controller_Router_Default', $options); } /** @@ -52,10 +52,9 @@ class Mage_Backend_Controller_Router_Validator_DefaultTest extends PHPUnit_Frame public function testConstructWithNotEmptyAreaFrontName() { $options = array( - 'area' => Mage::helper('Mage_Backend_Helper_Data')->getAreaCode(), - 'base_controller' => 'Mage_Backend_Controller_ActionAbstract', - 'frontName' => 'backend' + 'areaCode' => Mage::helper('Mage_Backend_Helper_Data')->getAreaCode(), + 'baseController' => 'Mage_Backend_Controller_ActionAbstract', ); - Mage::getModel('Mage_Backend_Controller_Router_Default', array('options' => $options)); + Mage::getModel('Mage_Backend_Controller_Router_Default', $options); } } diff --git a/dev/tests/integration/testsuite/Mage/Backend/controllers/Adminhtml/AuthControllerTest.php b/dev/tests/integration/testsuite/Mage/Backend/controllers/Adminhtml/AuthControllerTest.php index 281b2c5c4819acc9e91831e985c1edcfe56b63e6..81dd6fed501e64df9f46ef542aae8706dc4f4b19 100644 --- a/dev/tests/integration/testsuite/Mage/Backend/controllers/Adminhtml/AuthControllerTest.php +++ b/dev/tests/integration/testsuite/Mage/Backend/controllers/Adminhtml/AuthControllerTest.php @@ -26,8 +26,7 @@ */ /** - * Test class for Mage_Backend_Adminhtml_AuthController. - * + * Test class for Mage_Backend_Adminhtml_AuthController */ class Mage_Backend_Adminhtml_AuthControllerTest extends Magento_Test_TestCase_ControllerAbstract { @@ -91,7 +90,9 @@ class Mage_Backend_Adminhtml_AuthControllerTest extends Magento_Test_TestCase_Co $this->_login(); $this->dispatch('backend/admin/auth/login'); - $expected = Mage::getSingleton('Mage_Backend_Model_Url')->getUrl('adminhtml/dashboard'); + /** @var $backendUrlModel Mage_Backend_Model_Url */ + $backendUrlModel = Mage::getObjectManager()->get('Mage_Backend_Model_Url'); + $expected = $backendUrlModel->getUrl('adminhtml/dashboard'); $this->assertRedirect($this->stringStartsWith($expected)); $this->_logout(); diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Helper/Product/ViewTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Helper/Product/ViewTest.php index 66772246edf2f49a0b00539da50790f8a70bc344..4d3809411f2917f1411a6e10cd96df0fc861178f 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/Helper/Product/ViewTest.php +++ b/dev/tests/integration/testsuite/Mage/Catalog/Helper/Product/ViewTest.php @@ -48,7 +48,14 @@ class Mage_Catalog_Helper_Product_ViewTest extends PHPUnit_Framework_TestCase ->setActionName('view'); $this->_controller = Mage::getModel( 'Mage_Catalog_ProductController', - array('request' => $request, 'response' => new Magento_Test_Response) + array( + $request, + new Magento_Test_Response(), + 'frontend', + Mage::getObjectManager(), + Mage::getObjectManager()->get('Mage_Core_Controller_Varien_Front'), + Mage::getObjectManager()->get('Mage_Core_Model_Layout_Factory') + ) ); } @@ -101,7 +108,11 @@ class Mage_Catalog_Helper_Product_ViewTest extends PHPUnit_Framework_TestCase { $controller = Mage::getModel( 'Mage_Core_Controller_Front_Action', - array('request' => new Magento_Test_Request, 'response' => new Magento_Test_Response) + array( + 'request' => new Magento_Test_Request, + 'response' => new Magento_Test_Response, + 'areaCode' => 'frontend' + ) ); $this->_helper->prepareAndRender(10, $controller); } diff --git a/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php b/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php index b6a34e0389bd9459006632f69f3a8cd0b534ec59..9ba8a13f2440a26e0312b83e11a1ea83b12597e9 100644 --- a/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php +++ b/dev/tests/integration/testsuite/Mage/Catalog/Model/Layer/Filter/ItemTest.php @@ -71,7 +71,14 @@ class Mage_Catalog_Model_Layer_Filter_ItemTest extends PHPUnit_Framework_TestCas { $action = Mage::getModel( 'Mage_Core_Controller_Front_Action', - array('request' => new Magento_Test_Request(), 'response' => new Magento_Test_Response()) + array( + new Magento_Test_Request(), + new Magento_Test_Response(), + 'frontend', + Mage::getObjectManager(), + Mage::getObjectManager()->get('Mage_Core_Controller_Varien_Front'), + Mage::getObjectManager()->get('Mage_Core_Model_Layout_Factory') + ) ); Mage::app()->getFrontController()->setAction($action); // done in action's constructor $this->assertStringEndsWith('/?cat%5B0%5D=valuePart1&cat%5B1%5D=valuePart2', $this->_model->getUrl()); diff --git a/dev/tests/integration/testsuite/Mage/Checkout/controllers/OnepageControllerTest.php b/dev/tests/integration/testsuite/Mage/Checkout/controllers/OnepageControllerTest.php index f6b8b1c601cb40802805755f3a1e537f449d9c55..d976d246cdfe99b00a96338e033cf60700353842 100644 --- a/dev/tests/integration/testsuite/Mage/Checkout/controllers/OnepageControllerTest.php +++ b/dev/tests/integration/testsuite/Mage/Checkout/controllers/OnepageControllerTest.php @@ -80,6 +80,7 @@ class Mage_Checkout_OnepageControllerTest extends Magento_Test_TestCase_Controll public function testReviewAction() { $this->dispatch('checkout/onepage/review'); + $this->assertContains('Place Order', $this->getResponse()->getBody()); $this->assertContains('checkout-review', $this->getResponse()->getBody()); } diff --git a/dev/tests/integration/testsuite/Mage/Cms/Controller/RouterTest.php b/dev/tests/integration/testsuite/Mage/Cms/Controller/RouterTest.php index 5a6d1807bce21a07efac2376093b790be3807104..560a4e21e60905cf760a99de6b5fe6c064a73af8 100644 --- a/dev/tests/integration/testsuite/Mage/Cms/Controller/RouterTest.php +++ b/dev/tests/integration/testsuite/Mage/Cms/Controller/RouterTest.php @@ -34,7 +34,10 @@ class Mage_Cms_Controller_RouterTest extends PHPUnit_Framework_TestCase protected function setUp() { - $this->_model = new Mage_Cms_Controller_Router(new Mage_Core_Model_Event_ManagerStub()); + $this->_model = new Mage_Cms_Controller_Router( + Mage::getObjectManager()->get('Mage_Core_Controller_Varien_Action_Factory'), + new Mage_Core_Model_Event_ManagerStub() + ); } /** @@ -42,7 +45,7 @@ class Mage_Cms_Controller_RouterTest extends PHPUnit_Framework_TestCase */ public function testMatch() { - $request = new Zend_Controller_Request_Http(); + $request = new Mage_Core_Controller_Request_Http(); //Open Node $request->setPathInfo('parent_node'); $controller = $this->_model->match($request); @@ -62,7 +65,7 @@ class Mage_Core_Model_Event_ManagerStub extends Mage_Core_Model_Event_Manager * @param array $params * @return Mage_Core_Model_App|null */ - public function dispatch($eventName, $params) + public function dispatch($eventName, array $params = array()) { switch ($eventName) { case 'cms_controller_router_match_before' : diff --git a/dev/tests/integration/testsuite/Mage/Cms/Helper/PageTest.php b/dev/tests/integration/testsuite/Mage/Cms/Helper/PageTest.php index 41cec3216436245a30f95c877a1c7cf96da47fc7..c528f51f2ac783d2c930a2e2a20657c988a39185 100644 --- a/dev/tests/integration/testsuite/Mage/Cms/Helper/PageTest.php +++ b/dev/tests/integration/testsuite/Mage/Cms/Helper/PageTest.php @@ -40,7 +40,14 @@ class Mage_Cms_Helper_PageTest extends PHPUnit_Framework_TestCase $result = $helper->renderPage( Mage::getModel( 'Mage_Core_Controller_Front_Action', - array('request' => new Magento_Test_Request, 'response' => new Magento_Test_Response) + array( + new Magento_Test_Request(), + new Magento_Test_Response(), + 'frontend', + Mage::getObjectManager(), + Mage::getObjectManager()->get('Mage_Core_Controller_Varien_Front'), + Mage::getObjectManager()->get('Mage_Core_Model_Layout_Factory') + ) ), $page->getId() ); diff --git a/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php b/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php index fc4a5cbae02fa842ec55995fb59ba611a4374d42..5339cb78c13dbd1c558fa56be44cfdbec153869d 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Block/AbstractTest.php @@ -310,7 +310,9 @@ class Mage_Core_Block_AbstractTest extends PHPUnit_Framework_TestCase public function testGetBlockHtml() { // Without layout - $block1 = Mage::app()->getLayout()->createBlock('Mage_Core_Block_Text'); + /** @var $blockFactory Mage_Core_Model_BlockFactory */ + $blockFactory = Mage::getObjectManager()->get('Mage_Core_Model_BlockFactory'); + $block1 = $blockFactory->createBlock('Mage_Core_Block_Text'); $block1->setText('Block text'); $block1->setNameInLayout('block'); $html = $this->_block->getBlockHtml('block'); diff --git a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php index 985a14330d1d98fb2f33a1ae9ceb6d11ad9b6d35..a8d0efa8f65f92c5ba1bc7eaf9decb79283851d5 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/ActionTest.php @@ -39,8 +39,10 @@ class Mage_Core_Controller_Varien_ActionTest extends PHPUnit_Framework_TestCase array( new Magento_Test_Request(), new Magento_Test_Response(), + 'frontend', Mage::getObjectManager(), - Mage::app()->getFrontController() + Mage::getObjectManager()->get('Mage_Core_Controller_Varien_Front'), + Mage::getObjectManager()->get('Mage_Core_Model_Layout_Factory') ) ); } @@ -99,12 +101,7 @@ class Mage_Core_Controller_Varien_ActionTest extends PHPUnit_Framework_TestCase public function testGetLayout($controllerClass, $expectedArea) { /** @var $controller Mage_Core_Controller_Varien_Action */ - $controller = new $controllerClass( - new Magento_Test_Request(), - new Magento_Test_Response(), - Mage::getObjectManager(), - Mage::app()->getFrontController() - ); + $controller = Mage::getObjectManager()->create($controllerClass, array('areaCode' => $expectedArea)); $this->assertInstanceOf('Mage_Core_Model_Layout', $controller->getLayout()); $this->assertEquals($expectedArea, $controller->getLayout()->getArea()); } @@ -248,9 +245,12 @@ class Mage_Core_Controller_Varien_ActionTest extends PHPUnit_Framework_TestCase $request->setDispatched(); /* Area-specific controller is used because area must be known at the moment of loading the design */ - $this->_model = Mage::getModel( - 'Mage_Core_Controller_Front_Action', - array('request' => $request, 'response' => new Magento_Test_Response()) + $this->_model = Mage::getObjectManager()->create('Mage_Core_Controller_Front_Action', + array( + 'request' => $request, + 'response' => new Magento_Test_Response(), + 'areaCode' => 'frontend' + ) ); $this->_model->dispatch('not_exists'); @@ -293,11 +293,11 @@ class Mage_Core_Controller_Varien_ActionTest extends PHPUnit_Framework_TestCase { Mage::getConfig()->setCurrentAreaCode($expectedArea); /** @var $controller Mage_Core_Controller_Varien_Action */ - $controller = new $controllerClass( - new Magento_Test_Request(), - new Magento_Test_Response(), - Mage::getObjectManager(), - Mage::app()->getFrontController() + $controller = Mage::getObjectManager()->create($controllerClass, + array( + 'areaCode' => $expectedArea, + 'response' => new Magento_Test_Response(), + ) ); $controller->preDispatch(); @@ -352,14 +352,8 @@ class Mage_Core_Controller_Varien_ActionTest extends PHPUnit_Framework_TestCase public function testSetCurrentArea($controllerClass, $setArea, $expectedArea) { /** @var $controller Mage_Core_Controller_Varien_Action */ - $controller = new $controllerClass( - new Magento_Test_Request(), - new Magento_Test_Response(), - Mage::getObjectManager(), - Mage::app()->getFrontController() - ); + $controller = Mage::getObjectManager()->create($controllerClass, array('areaCode' => 'random_area')); $this->assertInstanceOf($controllerClass, $controller->setCurrentArea($setArea)); $this->assertEquals($expectedArea, $controller->getLayout()->getArea()); } - } diff --git a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/FrontTest.php b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/FrontTest.php index ce21006a0741bdd5fe1af85d2062ed44e08f1d89..1e64b65412a2f10bcc70197b3c393e3de6b76399 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/FrontTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/FrontTest.php @@ -27,6 +27,11 @@ class Mage_Core_Controller_Varien_FrontTest extends PHPUnit_Framework_TestCase { + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + /** * @var Mage_Core_Controller_Varien_Front */ @@ -34,12 +39,8 @@ class Mage_Core_Controller_Varien_FrontTest extends PHPUnit_Framework_TestCase protected function setUp() { - $this->_model = Mage::getModel('Mage_Core_Controller_Varien_Front'); - } - - protected function tearDown() - { - $this->_model = null; + $this->_objectManager = Mage::getObjectManager(); + $this->_model = $this->_objectManager->create('Mage_Core_Controller_Varien_Front'); } public function testSetGetDefault() @@ -105,9 +106,9 @@ class Mage_Core_Controller_Varien_FrontTest extends PHPUnit_Framework_TestCase public function testGetRouterByRoute() { $this->_model->init(); - $this->assertInstanceOf('Mage_Core_Controller_Varien_Router_Standard', $this->_model->getRouterByRoute('')); + $this->assertInstanceOf('Mage_Core_Controller_Varien_Router_Base', $this->_model->getRouterByRoute('')); $this->assertInstanceOf( - 'Mage_Core_Controller_Varien_Router_Standard', + 'Mage_Core_Controller_Varien_Router_Base', $this->_model->getRouterByRoute('checkout') ); $this->assertInstanceOf('Mage_Core_Controller_Varien_Router_Default', $this->_model->getRouterByRoute('test')); @@ -117,11 +118,11 @@ class Mage_Core_Controller_Varien_FrontTest extends PHPUnit_Framework_TestCase { $this->_model->init(); $this->assertInstanceOf( - 'Mage_Core_Controller_Varien_Router_Standard', + 'Mage_Core_Controller_Varien_Router_Base', $this->_model->getRouterByFrontName('') ); $this->assertInstanceOf( - 'Mage_Core_Controller_Varien_Router_Standard', + 'Mage_Core_Controller_Varien_Router_Base', $this->_model->getRouterByFrontName('checkout') ); $this->assertInstanceOf( @@ -130,17 +131,42 @@ class Mage_Core_Controller_Varien_FrontTest extends PHPUnit_Framework_TestCase ); } - public function testRewrite() + /** + * @param string $sourcePath + * @param string $resultPath + * + * @dataProvider applyRewritesDataProvider + * @magentoConfigFixture global/rewrite/test_url/from /test\/(\w*)/ + * @magentoConfigFixture global/rewrite/test_url/to new_test/$1/subdirectory + * @magentoDataFixture Mage/Core/_files/url_rewrite.php + * @magentoDbIsolation enabled + */ + public function testApplyRewrites($sourcePath, $resultPath) { - $route = $this->_model->getRequest()->getRouteName(); - $controller = $this->_model->getRequest()->getControllerName(); - $action = $this->_model->getRequest()->getActionName(); + /** @var $request Mage_Core_Controller_Request_Http */ + $request = $this->_objectManager->create('Mage_Core_Controller_Request_Http'); + $request->setPathInfo($sourcePath); - $this->_model->rewrite(); + $this->_model->applyRewrites($request); + $this->assertEquals($resultPath, $request->getPathInfo()); + } - $this->assertEquals($route, $this->_model->getRequest()->getRouteName()); - $this->assertEquals($controller, $this->_model->getRequest()->getControllerName()); - $this->assertEquals($action, $this->_model->getRequest()->getActionName()); - $this->markTestIncomplete('Requires an URL rewrite fixture.'); + /** + * Data provider for testApplyRewrites + * + * @return array + */ + public function applyRewritesDataProvider() + { + return array( + 'url rewrite' => array( + '$sourcePath' => '/test_rewrite_path', // data from fixture + '$resultPath' => 'cms/page/view/page_id/1', // data from fixture + ), + 'configuration rewrite' => array( + '$sourcePath' => '/test/url/', + '$resultPath' => '/new_test/url/subdirectory/', + ), + ); } } diff --git a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/AbstractTest.php b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/AbstractTest.php index e9f4a7be487849814321679d2fc6a1c096dcf7db..f89ba0683f2660355115184581c4d72dca772f73 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/AbstractTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/AbstractTest.php @@ -34,7 +34,9 @@ class Mage_Core_Controller_Varien_Router_AbstractTest extends PHPUnit_Framework_ protected function setUp() { - $this->_model = $this->getMockForAbstractClass('Mage_Core_Controller_Varien_Router_Abstract'); + $this->_model = $this->getMockForAbstractClass('Mage_Core_Controller_Varien_Router_Abstract', array(), '', + false + ); } protected function tearDown() diff --git a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/BaseTest.php b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/BaseTest.php index c00001ec18371e4c978e518cc9d2c6f601272ce7..d280723eff62eca5e281f8bda29f38e93b6019fc 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/BaseTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Controller/Varien/Router/BaseTest.php @@ -35,10 +35,10 @@ class Mage_Core_Controller_Varien_Router_BaseTest extends PHPUnit_Framework_Test protected function setUp() { $options = array( - 'area' => 'frontend', - 'base_controller' => 'Mage_Core_Controller_Front_Action' + 'areaCode' => 'frontend', + 'baseController' => 'Mage_Core_Controller_Front_Action' ); - $this->_model = Mage::getModel('Mage_Core_Controller_Varien_Router_Base', array('options' => $options)); + $this->_model = Mage::getModel('Mage_Core_Controller_Varien_Router_Base', $options); $this->_model->setFront(Mage::getModel('Mage_Core_Controller_Varien_Front')); } @@ -47,30 +47,6 @@ class Mage_Core_Controller_Varien_Router_BaseTest extends PHPUnit_Framework_Test $this->_model = null; } - /** - * @dataProvider initOptionsDataProvider - * @expectedException Mage_Core_Exception - */ - public function testConstructor(array $options) - { - Mage::getModel('Mage_Core_Controller_Varien_Router_Base', array('options' => $options)); - } - - public function initOptionsDataProvider() - { - return array( - array( - array() - ), - array( - array('area' => 'frontend') - ), - array( - array('base_controller' => 'Mage_Core_Controller_Front_Action') - ) - ); - } - public function testCollectRoutes() { $this->_model->collectRoutes('frontend', 'standard'); diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/AppTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/AppTest.php index 73519b64ef5dd6eaa43deadb97f08e3d5b114823..2682f57e0d8158656a7599992792e0a4e098eb6b 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/AppTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/AppTest.php @@ -222,13 +222,6 @@ class Mage_Core_Model_AppTest extends PHPUnit_Framework_TestCase $this->assertSame($locale, $this->_model->getLocale()); } - public function testGetLayout() - { - $layout = $this->_mageModel->getLayout(); - $this->assertInstanceOf('Mage_Core_Model_Layout', $layout); - $this->assertSame($layout, $this->_mageModel->getLayout()); - } - public function testGetTranslator() { $translate = $this->_model->getTranslator(); diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/Email/Template/FilterTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/Email/Template/FilterTest.php index 71e586efa193800587ac642fc4b1be403614379f..46e43627afcbaa323a60cb8ee2248b05bfd6daac 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/Email/Template/FilterTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/Email/Template/FilterTest.php @@ -121,7 +121,9 @@ class Mage_Core_Model_Email_Template_FilterTest extends PHPUnit_Framework_TestCa $themeUtility = Mage::getModel('Mage_Core_Utility_Theme', array( dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'design' )); - $themeUtility->registerThemes()->setDesignTheme('test/default', $currentArea); + $themeUtility->registerThemes() + ->setDesignTheme('test/default', 'frontend') + ->setDesignTheme('test/default', 'adminhtml'); $this->_emulateCurrentArea($currentArea); $actualOutput = $this->_model->layoutDirective(array( @@ -170,8 +172,9 @@ class Mage_Core_Model_Email_Template_FilterTest extends PHPUnit_Framework_TestCa */ protected function _emulateCurrentArea($area) { - /** @var $layout Mage_Core_Model_Layout */ - $layout = Mage::getSingleton('Mage_Core_Model_Layout', array('area' => $area)); + /** @var $layoutFactory Mage_Core_Model_Layout_Factory */ + $layoutFactory = Mage::getObjectManager()->get('Mage_Core_Model_Layout_Factory'); + $layout = $layoutFactory->createLayout(array('area' => $area)); $this->assertEquals($area, $layout->getArea()); $this->assertEquals($area, Mage::app()->getLayout()->getArea()); } diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/ObserverTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/ObserverTest.php index 93288b65447b92d691fc9d52d3567dfc4e464ce2..42be0319adbae3efa06f303aa62cd7b07b0cae90 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/ObserverTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/ObserverTest.php @@ -38,9 +38,8 @@ class Mage_Core_Model_ObserverTest extends PHPUnit_Framework_TestCase */ public function testThemeRegistration() { - Mage::app()->getConfig()->getOptions()->setDesignDir(dirname(__FILE__) . DS . '_files' . DS . 'design'); - $eventObserver = $this->_createEventObserverForThemeRegistration(); + $eventObserver->getEvent()->setBaseDir(dirname(__FILE__) . DS . '_files' . DS . 'design'); /** @var $observer Mage_Core_Model_Observer */ $observer = Mage::getModel('Mage_Core_Model_Observer'); @@ -52,10 +51,10 @@ class Mage_Core_Model_ObserverTest extends PHPUnit_Framework_TestCase $iphoneModel = $this->_getThemeModel(); $iphoneModel->load('default/default_iphone', 'theme_path'); - $this->assertEquals('default', $defaultModel->getThemeCode()); + $this->assertEquals('Default', $defaultModel->getThemeTitle()); $this->assertEquals(null, $defaultModel->getParentId()); - $this->assertEquals('default_iphone', $iphoneModel->getThemeCode()); + $this->assertEquals('Iphone', $iphoneModel->getThemeTitle()); $this->assertEquals($defaultModel->getId(), $iphoneModel->getParentId()); } diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Theme/CollectionTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Theme/CollectionTest.php index ea5a695cf84c75d8622b8d134ab8770da3c0d108..a8e1e08562b3d7f6e923ace7c3d60c992b634162 100644 --- a/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Theme/CollectionTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/Model/Resource/Theme/CollectionTest.php @@ -1,4 +1,4 @@ - <?php +<?php /** * Magento * diff --git a/dev/tests/integration/testsuite/Mage/Core/Model/Theme/ServiceTest.php b/dev/tests/integration/testsuite/Mage/Core/Model/Theme/ServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..866bbb46bb6ee01d7b40e88a7017656c86af5c77 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/Core/Model/Theme/ServiceTest.php @@ -0,0 +1,90 @@ +<?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 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test theme service model + */ +class Mage_Core_Model_Theme_ServiceTest extends PHPUnit_Framework_TestCase +{ + /** + * @covers Mage_Core_Model_Theme_Service::getThemes + */ + public function testGetThemes() + { + /** @var $themeService Mage_Core_Model_Theme_Service */ + $themeService = Mage::getObjectManager()->create('Mage_Core_Model_Theme_Service'); + $collection = $themeService->getThemes(1, Mage_Core_Model_Resource_Theme_Collection::DEFAULT_PAGE_SIZE); + + $this->assertLessThanOrEqual( + Mage_Core_Model_Resource_Theme_Collection::DEFAULT_PAGE_SIZE, $collection->count() + ); + + /** @var $theme Mage_Core_Model_Theme */ + foreach ($collection as $theme) { + $this->assertEquals('frontend', $theme->getArea()); + $this->assertFalse($theme->isVirtual()); + } + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @covers Mage_Core_Model_Theme_Service::assignThemeToStores + */ + public function testAssignThemeToStores() + { + $originalCount = $this->_getThemeCollection()->count(); + + /** @var $themeService Mage_Core_Model_Theme_Service */ + $themeService = Mage::getObjectManager()->create('Mage_Core_Model_Theme_Service'); + /** @var $physicalTheme Mage_Core_Model_Theme_Service */ + $physicalTheme = $themeService->getThemes(1, 1)->fetchItem(); + $this->assertTrue((bool)$physicalTheme->getId(), 'Physical theme is not loaded'); + + $storeView = Mage::app()->getAnyStoreView()->getId(); + $themeService->assignThemeToStores($physicalTheme->getId(), array($storeView)); + $this->assertEquals($originalCount + 1, $this->_getThemeCollection()->count()); + + $configItem = Mage::app()->getConfig()->getConfigDataModel()->getCollection() + ->addFieldToSelect(array('value')) + ->addFieldToFilter('scope', Mage_Core_Model_Config::SCOPE_STORES) + ->addFieldToFilter('scope_id', $storeView) + ->fetchItem(); + $themeId = $this->_getThemeCollection()->setOrder('theme_id', Varien_Data_Collection_Db::SORT_ORDER_ASC) + ->getLastItem()->getId(); + + $this->assertEquals($configItem->getValue(), $themeId); + } + + /** + * @return Mage_Core_Model_Resource_Theme_Collection + */ + protected function _getThemeCollection() + { + return Mage::getObjectManager()->create('Mage_Core_Model_Resource_Theme_Collection'); + } +} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/TemplateTest.php b/dev/tests/integration/testsuite/Mage/Core/_files/url_rewrite.php similarity index 58% rename from dev/tests/integration/testsuite/Mage/DesignEditor/Block/TemplateTest.php rename to dev/tests/integration/testsuite/Mage/Core/_files/url_rewrite.php index 8491b090cf77d204c797f15922b21abda28c5951..8bf000801cd76643e30d3d4c0f23d5a992e35bc0 100644 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/TemplateTest.php +++ b/dev/tests/integration/testsuite/Mage/Core/_files/url_rewrite.php @@ -19,21 +19,29 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Magento - * @package Mage_DesignEditor + * @package Mage_Core * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -class Mage_DesignEditor_Block_TemplateTest extends PHPUnit_Framework_TestCase -{ - public function testIsHighlightingDisabled() - { - $block = Mage::app()->getLayout()->createBlock('Mage_DesignEditor_Block_Template'); - $this->assertFalse($block->isHighlightingDisabled()); - Mage::getSingleton('Mage_Core_Model_Cookie')->set(Mage_DesignEditor_Model_Session::COOKIE_HIGHLIGHTING, 'off'); - $this->assertTrue($block->isHighlightingDisabled()); - Mage::getSingleton('Mage_Core_Model_Cookie')->set(Mage_DesignEditor_Model_Session::COOKIE_HIGHLIGHTING, 'on'); - $this->assertFalse($block->isHighlightingDisabled()); - } +$objectManager = Mage::getObjectManager(); +$cmsPageId = 1; +$rewriteUrl = 'test_rewrite_path'; + +// get CMS page +/** @var $cmsPage Mage_Cms_Model_Page */ +$cmsPage = $objectManager->create('Mage_Cms_Model_Page'); +$cmsPage->load($cmsPageId); +if ($cmsPage->isObjectNew()) { + $cmsPage->setId($cmsPageId); + $cmsPage->save(); } + +// create URL rewrite +/** @var $rewrite Mage_Core_Model_Url_Rewrite */ +$rewrite = $objectManager->create('Mage_Core_Model_Url_Rewrite'); +$rewrite->setIdPath('cms_page/' . $cmsPage->getId()) + ->setRequestPath($rewriteUrl) + ->setTargetPath('cms/page/view/page_id/' . $cmsPage->getId()) + ->save(); diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/BreadcrumbsTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/BreadcrumbsTest.php deleted file mode 100644 index a28ead4305155c75ca2ac345e056a0f3c425b315..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/BreadcrumbsTest.php +++ /dev/null @@ -1,119 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_DesignEditor_Block_Toolbar_BreadcrumbsTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_DesignEditor_Block_Toolbar_Breadcrumbs - */ - protected $_block; - - protected function setUp() - { - $layoutUtility = new Mage_Core_Utility_Layout($this); - $pageTypesFixture = __DIR__ . '/../../../Core/Model/Layout/_files/_handles.xml'; - $layout = $layoutUtility->getLayoutFromFixture($pageTypesFixture, $layoutUtility->getLayoutDependencies()); - $this->_block = $layout->createBlock( - 'Mage_DesignEditor_Block_Toolbar_Breadcrumbs', - '', - array('data' => array('template' => 'toolbar/breadcrumbs.phtml')) - ); - } - - protected function tearDown() - { - $this->_block = null; - } - - /** - * Set the current route/controller/action - * - * @param string $routName - * @param string $controllerName - * @param string $actionName - */ - protected function _setControllerAction($routName, $controllerName, $actionName) - { - /** @var $controllerAction Mage_Core_Controller_Varien_Action */ - $controllerAction = $this->getMockForAbstractClass( - 'Mage_Core_Controller_Varien_Action', - array( - new Magento_Test_Request(), - new Magento_Test_Response(), - Mage::getObjectManager(), - Mage::app()->getFrontController() - ) - ); - /* Note: controller action instance registers itself within the front controller immediately after creation */ - $controllerAction->getRequest() - ->setRouteName($routName) - ->setControllerName($controllerName) - ->setActionName($actionName); - } - - public function testGetBreadcrumbsFromPageHandles() - { - $this->_block->getLayout()->getUpdate()->addPageHandles(array('catalog_product_view_type_simple')); - $this->assertEquals( - require(__DIR__ . '/_files/_breadcrumbs_simple_product.php'), - $this->_block->getBreadcrumbs() - ); - } - - /** - * @magentoAppIsolation enabled - */ - public function testGetBreadcrumbsFromDefaultLayoutHandle() - { - $this->_setControllerAction('catalog', 'product_view', 'type_simple'); - $this->assertEquals( - require(__DIR__ . '/_files/_breadcrumbs_simple_product.php'), - $this->_block->getBreadcrumbs() - ); - } - - public function testToHtmlFromPageHandles() - { - $this->_block->getLayout()->getUpdate()->addPageHandles(array('catalog_product_view_type_simple')); - $this->assertXmlStringEqualsXmlFile( - __DIR__ . '/_files/_breadcrumbs_simple_product.html', - $this->_block->toHtml() - ); - } - - /** - * @magentoAppIsolation enabled - */ - public function testToHtmlFromDefaultLayoutHandle() - { - $this->_setControllerAction('catalog', 'product_view', 'type_simple'); - $this->assertXmlStringEqualsXmlFile( - __DIR__ . '/_files/_breadcrumbs_simple_product.html', - $this->_block->toHtml() - ); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/HandlesHierarchyTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/HandlesHierarchyTest.php deleted file mode 100644 index 6a5da8961b4eddf17a96deef5e76f81cb1b6e346..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/HandlesHierarchyTest.php +++ /dev/null @@ -1,86 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_DesignEditor_Block_Toolbar_HandlesHierarchyTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_DesignEditor_Block_Toolbar_HandlesHierarchy - */ - protected $_block; - - protected function setUp() - { - $layoutUtility = new Mage_Core_Utility_Layout($this); - $pageTypesFixture = __DIR__ . '/../../../Core/Model/Layout/_files/_handles.xml'; - $this->_block = Mage::app()->getLayout()->createBlock('Mage_DesignEditor_Block_Toolbar_HandlesHierarchy'); - $this->_block->setLayout($layoutUtility->getLayoutFromFixture($pageTypesFixture, - $layoutUtility->getLayoutDependencies() - )); - } - - protected function tearDown() - { - $this->_block = null; - } - - public function testRenderHierarchy() - { - $expected = __DIR__ . '/_files/_handles_hierarchy.html'; - $actual = $this->_block->renderHierarchy(); - $this->assertXmlStringEqualsXmlFile($expected, $actual); - } - - public function testGetSelectedHandleFromPageHandles() - { - $this->_block->getLayout()->getUpdate()->addPageHandles(array('catalog_product_view_type_simple')); - $this->assertEquals('catalog_product_view_type_simple', $this->_block->getSelectedHandle()); - } - - public function testGetSelectedHandleFromAnyHandles() - { - $this->_block->getLayout()->getUpdate()->addHandle(array( - 'catalog_product_view', - 'catalog_product_view_type_grouped', - 'not_a_page_type', - )); - $this->assertEquals('catalog_product_view_type_grouped', $this->_block->getSelectedHandle()); - } - - public function testGetSelectedHandleLabel() - { - $this->assertNull($this->_block->getSelectedHandleLabel()); - $this->_block->setSelectedHandle('default'); - $this->assertEquals('All Pages', $this->_block->getSelectedHandleLabel()); - } - - public function testSetSelectedHandle() - { - $this->assertFalse($this->_block->getSelectedHandle()); - $this->_block->setSelectedHandle('catalog_product_view_type_configurable'); - $this->assertEquals('catalog_product_view_type_configurable', $this->_block->getSelectedHandle()); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/ThemeTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/ThemeTest.php deleted file mode 100644 index 84c1d3219eeb9fcaca4a37ec4b12d48aea080b38..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/ThemeTest.php +++ /dev/null @@ -1,100 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test for theme block functioning - */ -class Mage_DesignEditor_Block_Toolbar_ThemeTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_DesignEditor_Block_Toolbar_Theme - */ - protected $_block; - - protected function setUp() - { - $this->_block = Mage::app()->getLayout()->createBlock('Mage_DesignEditor_Block_Toolbar_Theme'); - } - - protected function tearDown() - { - $this->_block = null; - } - - /** - * @magentoDbIsolation enabled - * @magentoAppIsolation enabled - */ - public function testIsThemeSelected() - { - $themeOld = Mage::getObjectManager()->create('Mage_Core_Model_Theme') - ->setData($this->_getThemeSampleData()) - ->setThemePath('a/b') - ->setThemeCode('b') - ->save(); - - $themeNew = Mage::getObjectManager()->create('Mage_Core_Model_Theme') - ->setData($this->_getThemeSampleData()) - ->setThemePath('c/d') - ->setThemeCode('d') - ->save(); - - Mage::getDesign()->setDesignTheme($themeOld); - $isSelected = $this->_block->isThemeSelected($themeOld->getId()); - $this->assertTrue($isSelected); - - Mage::getDesign()->setDesignTheme($themeNew); - $isSelected = $this->_block->isThemeSelected($themeOld->getId()); - $this->assertFalse($isSelected); - } - - public function testGetSelectHtmlId() - { - $value = $this->_block->getSelectHtmlId(); - $this->assertNotEmpty($value); - } - - /** - * @return array - */ - protected function _getThemeSampleData() - { - return array( - 'theme_title' => 'Default', - 'theme_version' => '2.0.0.0', - 'parent_theme' => null, - 'is_featured' => true, - 'magento_version_from' => '2.0.0.0-dev1', - 'magento_version_to' => '*', - 'preview_image' => '', - 'area' => 'frontend', - 'theme_directory' => implode( - DIRECTORY_SEPARATOR, array(__DIR__, '_files', 'design', 'frontend', 'default', 'default') - ) - ); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_handles_hierarchy.html b/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_handles_hierarchy.html deleted file mode 100644 index c143c64253821c1e5529eec244ed99cfbd53dc5d..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_handles_hierarchy.html +++ /dev/null @@ -1,78 +0,0 @@ -<!-- -/** - * 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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) - */ ---> -<ul> - <li rel="print"> - <a href="http://localhost/index.php/design/editor/page/handle/print/">All Pages (Print Version)</a> - <ul> - <li rel="sales_order_print"> - <a href="http://localhost/index.php/design/editor/page/handle/sales_order_print/">Sales Order Print View</a> - </li> - <li rel="sales_guest_print"> - <a href="http://localhost/index.php/design/editor/page/handle/sales_guest_print/">Sales Order Print View (Guest)</a> - </li> - </ul> - </li> - <li rel="default"> - <a href="http://localhost/index.php/design/editor/page/handle/default/">All Pages</a> - <ul> - <li rel="catalog_category_default"> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_category_default/">Catalog Category (Non-Anchor)</a> - <ul> - <li rel="catalog_category_layered"> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_category_layered/">Catalog Category (Anchor)</a> - </li> - <li rel="catalog_product_view"> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_product_view/">Catalog Product View (Any)</a> - <ul> - <li rel="catalog_product_view_type_simple"> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_product_view_type_simple/">Catalog Product View (Simple)</a> - </li> - <li rel="catalog_product_view_type_configurable"> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_product_view_type_configurable/">Catalog Product View (Configurable)</a> - </li> - <li rel="catalog_product_view_type_grouped"> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_product_view_type_grouped/">Catalog Product View (Grouped)</a> - </li> - </ul> - </li> - </ul> - </li> - <li rel="catalogsearch_ajax_suggest" class="vde_option_fragment"> - <a href="http://localhost/index.php/design/editor/page/handle/catalogsearch_ajax_suggest/">Catalog Quick Search Form Suggestions</a> - </li> - <li rel="checkout_onepage_index"> - <a href="http://localhost/index.php/design/editor/page/handle/checkout_onepage_index/">One Page Checkout</a> - <ul> - <li rel="checkout_onepage_progress" class="vde_option_fragment"> - <a href="http://localhost/index.php/design/editor/page/handle/checkout_onepage_progress/">One Page Checkout Progress</a> - </li> - </ul> - </li> - </ul> - </li> -</ul> diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/ToolbarCrosscuttingTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Block/ToolbarCrosscuttingTest.php deleted file mode 100644 index 39a9e2cb139e99910ba2a281af79ddb3e57afbb6..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/ToolbarCrosscuttingTest.php +++ /dev/null @@ -1,69 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test for presence of the design editor toolbar on frontend pages - * - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @magentoDataFixture Mage/Catalog/controllers/_files/products.php - */ -class Mage_DesignEditor_Block_ToolbarCrosscuttingTest extends Magento_Test_TestCase_ControllerAbstract -{ - /** - * Assert that a page content contains the design editor toolbar - * - * @param string $content - */ - protected function _assertContainsToolbar($content) - { - $this->assertContains('id="vde_toolbar"', $content); - } - - public function testCmsHomePage() - { - $this->dispatch('cms/index/index'); - $this->_assertContainsToolbar($this->getResponse()->getBody()); - } - - public function testCustomerAccountLogin() - { - $this->dispatch('customer/account/login'); - $this->_assertContainsToolbar($this->getResponse()->getBody()); - } - - public function testCatalogProductView() - { - $this->dispatch('catalog/product/view/id/1'); - $this->_assertContainsToolbar($this->getResponse()->getBody()); - } - - public function testCheckoutCart() - { - $this->dispatch('checkout/cart/index'); - $this->_assertContainsToolbar($this->getResponse()->getBody()); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/ToolbarTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Block/ToolbarTest.php deleted file mode 100644 index 32e63d306ead8e8bcb712a254bf0b75709e43714..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/ToolbarTest.php +++ /dev/null @@ -1,90 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_DesignEditor_Block_ToolbarTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_DesignEditor_Block_Toolbar - */ - protected $_block; - - protected function setUp() - { - $layout = Mage::app()->getLayout(); - $this->_block = $layout->createBlock( - 'Mage_DesignEditor_Block_Toolbar', - 'block', - array('template' => 'toolbar.phtml') - ); - } - - protected function tearDown() - { - $this->_block = null; - } - - /** - * Isolation has been raised because block pollutes the registry - * - * @magentoAppIsolation enabled - */ - public function testToHtmlDesignEditorInactive() - { - $this->assertEmpty($this->_block->toHtml()); - } - - /** - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testToHtmlDesignEditorActive() - { - $this->assertNotEmpty($this->_block->toHtml()); - $this->assertContains(' id="vde_toolbar"', $this->_block->toHtml()); - } - - public function testGetMessages() - { - /** @var $session Mage_DesignEditor_Model_Session */ - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - $this->assertEmpty($session->getMessages()->getItems()); - - $session->addError('test error'); - $session->addSuccess('test success'); - - $blockMessages = $this->_block->getMessages(); - $this->assertInternalType('array', $blockMessages); - $this->assertEquals(2, count($blockMessages)); - - $this->assertInstanceOf('Mage_Core_Model_Message_Error', $blockMessages[0]); - $this->assertEquals('test error', $blockMessages[0]->getCode()); - $this->assertInstanceOf('Mage_Core_Model_Message_Success', $blockMessages[1]); - $this->assertEquals('test success', $blockMessages[1]->getCode()); - - $this->assertEmpty($session->getMessages()->getItems()); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Model/LayoutTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/LayoutTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f09ef56d0eec08c2cf2ad34243f7c5e289aba806 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/LayoutTest.php @@ -0,0 +1,106 @@ +<?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_DesignEditor + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test for VDE layout + */ +class Mage_DesignEditor_Model_LayoutTest extends PHPUnit_Framework_TestCase +{ + /** + * @covers Mage_DesignEditor_Model_Layout::sanitizeLayout + * @expectedException Mage_Core_Exception + * @expectedExceptionMessage Invalid block type: Namespace_Module_Block_NotSafe + */ + public function testGenerateElements() + { + $layout = $this->_getLayoutWithTestUpdate(); + $layout->generateElements(); + + $expectedXml = new Varien_Simplexml_Element(file_get_contents(__DIR__ . '/_files/expected_layout_update.xml')); + $this->assertStringMatchesFormat($expectedXml->asNiceXml(), $layout->getNode()->asNiceXml()); + + $layout = $this->_getLayoutWithTestUpdate(false); + $layout->generateElements(); + } + + /** + * Retrieve test layout with test layout update + * + * @param bool $isSanitizeBlocks + * @param bool $enableWrapping + * @return Mage_DesignEditor_Model_Layout + */ + protected function _getLayoutWithTestUpdate($isSanitizeBlocks = true, $enableWrapping = true) + { + /** @var $layout Mage_DesignEditor_Model_Layout */ + $layout = Mage::getObjectManager()->create('Mage_DesignEditor_Model_Layout'); + $layout->setSanitizing($isSanitizeBlocks); + $layout->setWrapping($enableWrapping); + $layout->getUpdate()->addUpdate(file_get_contents(__DIR__ . '/_files/layout_update.xml')); + $layout->generateXml(); + + return $layout; + } + + /** + * @covers Mage_DesignEditor_Model_Layout::_renderBlock + * @covers Mage_DesignEditor_Model_Layout::_renderContainer + * @covers Mage_DesignEditor_Model_Layout::_wrapElement + */ + public function testRenderElement() + { + $blockName = 'safe.block'; + $containerName = 'content'; + + $blockWrapper = 'class="vde_element_wrapper vde_draggable vde_removable" data-name="' . $blockName . '"'; + $blockTitle = '<div class="vde_element_title">' . $blockName . '</div>'; + $containerWrapper = 'class="vde_element_wrapper vde_container" data-name="' . $containerName . '"'; + $containerTitle = '<div class="vde_element_title">' . ucfirst($containerName) . '</div>'; + + $layout = $this->_getLayoutWithTestUpdate(); + $layout->generateElements(); + + $actualContent = $layout->renderElement($blockName); + $this->assertContains($blockWrapper, $actualContent); + $this->assertContains($blockTitle, $actualContent); + + $actualContent = $layout->renderElement($containerName); + $this->assertContains($containerWrapper, $actualContent); + $this->assertContains($containerTitle, $actualContent); + + $layout = $this->_getLayoutWithTestUpdate(true, false); + $layout->generateElements(); + + $actualContent = $layout->renderElement($blockName); + $this->assertNotContains($blockWrapper, $actualContent); + $this->assertNotContains($blockTitle, $actualContent); + + $actualContent = $layout->renderElement($containerName); + $this->assertNotContains($containerWrapper, $actualContent); + $this->assertNotContains($containerTitle, $actualContent); + } +} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Model/ObserverTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/ObserverTest.php deleted file mode 100644 index 9c97ec396a9dd642336417cd164664dac2e06091..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Model/ObserverTest.php +++ /dev/null @@ -1,323 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** - * Test for theme changing observer - */ -class Mage_DesignEditor_Model_ObserverTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_DesignEditor_Model_Observer - */ - protected $_observer; - - /** - * @var Varien_Event_Observer - */ - protected $_eventObserver; - - protected function setUp() - { - $this->_observer = Mage::getModel('Mage_DesignEditor_Model_Observer'); - - $this->_eventObserver = new Varien_Event_Observer(); - $this->_eventObserver->setEvent(new Varien_Event(array('layout' => Mage::app()->getLayout()))); - } - - protected function tearDown() - { - $this->_observer = null; - } - - /** - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @magentoConfigFixture current_store admin/security/session_lifetime 100 - */ - public function testPreDispatchDeactivateDesignEditor() - { - /** @var $session Mage_DesignEditor_Model_Session */ - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - $this->assertNotEmpty($session->getData(Mage_DesignEditor_Model_Session::SESSION_DESIGN_EDITOR_ACTIVE)); - /* active admin session */ - $this->_observer->preDispatch($this->_eventObserver); - $this->assertNotEmpty($session->getData(Mage_DesignEditor_Model_Session::SESSION_DESIGN_EDITOR_ACTIVE)); - /* expired admin session */ - $session->setUpdatedAt(time() - 101); - $this->_observer->preDispatch($this->_eventObserver); - $this->assertEmpty($session->getData(Mage_DesignEditor_Model_Session::SESSION_DESIGN_EDITOR_ACTIVE)); - } - - /** - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testPreDispatchApplyDesign() - { - $newTheme = 'default/blank'; - $this->assertNotEquals($newTheme, Mage::getDesign()->getDesignTheme()->getThemePath()); - $this->_observer->preDispatch($this->_eventObserver); - $this->assertEquals($newTheme, Mage::getDesign()->getDesignTheme()->getThemePath()); - } - - /** - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testPreDispatchWrongThemeId() - { - /** @var $session Mage_DesignEditor_Model_Session */ - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - $session->setThemeId(0); - $this->_observer->preDispatch($this->_eventObserver); - $this->assertFalse($session->isDesignEditorActive()); - } - - /** - * @magentoAppIsolation enabled - */ - public function testPreDispatchApplyDesignInactive() - { - $newTheme = 'default/blank'; - $oldTheme = Mage::getDesign()->getDesignTheme(); - $this->assertNotEquals($newTheme, $oldTheme); - $this->_observer->preDispatch($this->_eventObserver); - $this->assertEquals($oldTheme, Mage::getDesign()->getDesignTheme()); - } - - /** - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testAddToolbar() - { - $layoutUpdate = Mage::app()->getLayout()->getUpdate(); - $this->assertNotContains(Mage_DesignEditor_Model_Observer::HANDLE_TOOLBAR, $layoutUpdate->getHandles()); - $this->_observer->addToolbar($this->_eventObserver); - $this->assertContains(Mage_DesignEditor_Model_Observer::HANDLE_TOOLBAR, $layoutUpdate->getHandles()); - } - - /** - * @magentoAppIsolation enabled - */ - public function testDisableBlocksOutputCachingInactive() - { - Mage::app()->getCacheInstance()->allowUse(Mage_Core_Block_Abstract::CACHE_GROUP); - $this->_observer->disableBlocksOutputCaching(new Varien_Event_Observer()); - $this->assertTrue(Mage::app()->useCache(Mage_Core_Block_Abstract::CACHE_GROUP)); - } - - /** - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testDisableBlocksOutputCachingActive() - { - Mage::app()->getCacheInstance()->allowUse(Mage_Core_Block_Abstract::CACHE_GROUP); - $this->_observer->disableBlocksOutputCaching(new Varien_Event_Observer()); - $this->assertFalse(Mage::app()->useCache(Mage_Core_Block_Abstract::CACHE_GROUP)); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testSetDesignEditorFlag() - { - /** @var $headBlock Mage_Page_Block_Html_Head */ - $headBlock = Mage::app()->getLayout()->createBlock('Mage_Page_Block_Html_Head'); - /** @var $layout Mage_Core_Model_Layout */ - $layout = Mage::getModel('Mage_Core_Model_Layout'); - $layout->addBlock($headBlock, 'head'); - $this->assertEmpty($headBlock->getDesignEditorActive()); - $observerData = new Varien_Event_Observer(array('event' => new Varien_Object(array('layout' => $layout)))); - $this->_observer->setDesignEditorFlag($observerData); - $this->assertNotEmpty($headBlock->getDesignEditorActive()); - } - - /** - * @param string $elementName - * @param string $elementHtml - * @param string $expectedOutput - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @dataProvider wrapPageElementDataProvider - */ - public function testWrapPageElement($elementName, $elementHtml, $expectedOutput) - { - //@TODO Consider remaking the test cause now it's very fragile. - // Trivial change of wrapper template requires modifications in data provider - - $actualOutput = $this->_wrapElement($elementName, $elementHtml); - $this->assertXmlStringEqualsXmlString( - "<root>$expectedOutput</root>", - "<root>$actualOutput</root>", - "\n" . $expectedOutput . "\ndiffers from\n" . $actualOutput - ); - } - - /** - * @return array - */ - public function wrapPageElementDataProvider() - { - $removeLink = sprintf('<a href="#remove"><img src="%s" alt="Remove" /></a>', - Mage::getDesign()->getViewFileUrl('images/btn_remove.gif') - ); - return array( - 'non-draggable block' => array( - 'non_draggable_block', - '<b>Non-Draggable Block</b>', - '<b>Non-Draggable Block</b>', - ), - 'non-draggable VDE block' => array( - 'non_draggable_vde_block', - '<b>Non-Draggable VDE Block</b>', - '<b>Non-Draggable VDE Block</b>', - ), - 'draggable block' => array( - 'draggable_block', - '<b>Draggable Block</b>', - '<div id="vde_element_ZHJhZ2dhYmxlX2Jsb2Nr" class="vde_element_wrapper vde_draggable vde_removable" - data-name="draggable_block"> - <div class="vde_element_title">draggable_block</div> - <div class="vde_element_title vde_element_remove" - id="vde_element_ZHJhZ2dhYmxlX2Jsb2Nr_remove">' . $removeLink . '</div> - <b>Draggable Block</b> - </div>', - ), - 'non-draggable container' => array( - 'non_draggable_container', - '<b>Non-Draggable Container Text</b>', - '<div id="vde_element_bm9uX2RyYWdnYWJsZV9jb250YWluZXI" class="vde_element_wrapper vde_container" - data-name="non_draggable_container"> - <div class="vde_element_title">Non-Draggable Container</div> - <b>Non-Draggable Container Text</b> - </div>', - ), - 'draggable container' => array( - 'draggable_container', - '<b>Draggable Container Text</b>', - '<div id="vde_element_ZHJhZ2dhYmxlX2NvbnRhaW5lcg" - class="vde_element_wrapper vde_draggable vde_removable vde_container" - data-name="draggable_container"> - <div class="vde_element_title">Draggable Container</div> - <div class="vde_element_title vde_element_remove" - id="vde_element_ZHJhZ2dhYmxlX2NvbnRhaW5lcg_remove">' . $removeLink . '</div> - <b>Draggable Container Text</b> - </div>', - ), - 'VDE toolbar injection' => array( - 'after_body_start', - '<b>Page Top Container Text</b>', - '<div>VDE Toolbar</div> - <div id="vde_element_YWZ0ZXJfYm9keV9zdGFydA" class="vde_element_wrapper vde_container" - data-name="after_body_start"> - <div class="vde_element_title">Page Top</div> - <b>Page Top Container Text</b> - </div>', - ), - ); - } - - /** - * @magentoAppIsolation enabled - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testWrapPageElementHighlightingDisabled() - { - //@TODO Consider remaking the test cause now it's very fragile. - // Trivial change of wrapper template requires modifications in data provider - - $elementName = 'draggable_block'; - $elementHtml = '<b>Draggable Block</b>'; - $expectedOutputFormat = - '<div id="vde_element_ZHJhZ2dhYmxlX2Jsb2Nr" ' - . 'class="vde_element_wrapper vde_draggable vde_removable vde_wrapper_hidden" ' - . 'data-name="draggable_block">%w' - . '<div class="vde_element_title">draggable_block</div>%w' - . '<div class="vde_element_title vde_element_remove" id="vde_element_ZHJhZ2dhYmxlX2Jsb2Nr_remove">%w' - . '<a href="#remove">%w' - . '<img src="' . Mage::getDesign()->getViewFileUrl('images/btn_remove.gif') - . '" alt="Remove" />%w' - . '</a>%w' - . '</div>%w' - . '</div>%w' - . '<!--start_vde_element_ZHJhZ2dhYmxlX2Jsb2Nr-->%w' - . '<b>Draggable Block</b>%w' - . '<!--end_vde_element_ZHJhZ2dhYmxlX2Jsb2Nr-->%w'; - - Mage::getSingleton('Mage_Core_Model_Cookie')->set(Mage_DesignEditor_Model_Session::COOKIE_HIGHLIGHTING, 'off'); - $actualOutput = $this->_wrapElement($elementName, $elementHtml); - $this->assertStringMatchesFormat($expectedOutputFormat, $actualOutput); - } - - /** - * Process wrapping of an element - * - * Generates layout and should be used with magentoAppIsolation enabled - * - * @param string $elementName - * @param string $elementHtml - * @return string - */ - protected function _wrapElement($elementName, $elementHtml) - { - // create a layout object mock with fixture data - $utility = new Mage_Core_Utility_Layout($this);; - $layoutMock = $utility->getLayoutFromFixture(__DIR__ . '/../_files/observer_test.xml', - $utility->getLayoutDependencies() - ); - - // load the fixture data. This will populate layout structure as well - $layoutMock->getUpdate()->addHandle('test_handle')->load(); - $layoutMock->generateXml()->generateElements(); - - $transport = new Varien_Object(array('output' => $elementHtml)); - $observer = new Varien_Event_Observer(array( - 'event' => new Varien_Event(array( - 'layout' => $layoutMock, - 'element_name' => $elementName, - 'transport' => $transport, - )) - )); - - $this->_observer->wrapPageElement($observer); - return $transport->getData('output'); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testAdminSessionUserLogout() - { - /** @var $session Mage_DesignEditor_Model_Session */ - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - $this->assertTrue($session->isDesignEditorActive()); - $this->_observer->adminSessionUserLogout(); - $this->assertFalse($session->isDesignEditorActive()); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Model/SessionTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/SessionTest.php deleted file mode 100644 index 6ccc1ea62724c4d85d41e86829453cec2ab7fe2d..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Model/SessionTest.php +++ /dev/null @@ -1,137 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_DesignEditor_Model_SessionTest extends PHPUnit_Framework_TestCase -{ - /** - * @var Mage_Backend_Model_Auth_Session - */ - protected static $_adminSession; - - /** - * @var Mage_DesignEditor_Model_Session - */ - protected $_model; - - protected function setUp() - { - $this->_model = Mage::getModel('Mage_DesignEditor_Model_Session'); - } - - protected function tearDown() - { - $this->_model = null; - } - - public function testIsDesignEditorActiveFalse() - { - $this->assertFalse($this->_model->isDesignEditorActive()); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @magentoAppIsolation enabled - */ - public function testIsDesignEditorActiveTrue() - { - $this->assertTrue($this->_model->isDesignEditorActive()); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @magentoConfigFixture current_store admin/security/session_lifetime 100 - * @magentoAppIsolation enabled - */ - public function testIsDesignEditorActiveAdminSessionExpired() - { - $this->assertTrue($this->_model->isDesignEditorActive()); - $this->_model->setUpdatedAt(time() - 101); - $this->assertFalse($this->_model->isDesignEditorActive()); - } - - /** - * @magentoDataFixture loginAdmin - */ - public function testActivateDesignEditor() - { - $this->assertFalse($this->_model->isDesignEditorActive()); - $this->_model->activateDesignEditor(); - $this->assertTrue($this->_model->isDesignEditorActive()); - } - - public static function loginAdmin() - { - $auth = Mage::getModel('Mage_Backend_Model_Auth'); - self::$_adminSession = $auth->getAuthStorage(); - $auth->login(Magento_Test_Bootstrap::ADMIN_NAME, Magento_Test_Bootstrap::ADMIN_PASSWORD); - } - - public static function loginAdminRollback() - { - $auth = Mage::getModel('Mage_Backend_Model_Auth'); - $auth->setAuthStorage(self::$_adminSession); - $auth->logout(); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testDeactivateDesignEditor() - { - $this->assertTrue($this->_model->isDesignEditorActive()); - $this->_model->deactivateDesignEditor(); - $this->assertFalse($this->_model->isDesignEditorActive()); - } - - public function testIsHighlightingDisabled() - { - $this->assertFalse($this->_model->isHighlightingDisabled()); - Mage::getSingleton('Mage_Core_Model_Cookie')->set(Mage_DesignEditor_Model_Session::COOKIE_HIGHLIGHTING, 'off'); - $this->assertTrue($this->_model->isHighlightingDisabled()); - Mage::getSingleton('Mage_Core_Model_Cookie')->set(Mage_DesignEditor_Model_Session::COOKIE_HIGHLIGHTING, 'on'); - $this->assertFalse($this->_model->isHighlightingDisabled()); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @depends testDeactivateDesignEditor - * @depends testIsHighlightingDisabled - */ - public function testIsHighlightingDisabledOnDeactivateDesignEditor() - { - Mage::getSingleton('Mage_Core_Model_Cookie')->set(Mage_DesignEditor_Model_Session::COOKIE_HIGHLIGHTING, 'off'); - $this->assertTrue($this->_model->isHighlightingDisabled()); - $this->_model->deactivateDesignEditor(); - $this->assertFalse($this->_model->isHighlightingDisabled()); - } - - public function testSetThemeId() - { - $this->_model->setThemeId(0); - $this->assertEquals(0, $this->_model->getThemeId()); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_breadcrumbs_simple_product.html b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/_files/expected_layout_update.xml similarity index 55% rename from dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_breadcrumbs_simple_product.html rename to dev/tests/integration/testsuite/Mage/DesignEditor/Model/_files/expected_layout_update.xml index a3c4b65ccd23b9d9dfe9a01123a75eb69e5897e2..8864a759cdb0ab663d86163ab9d1217e6fa412a2 100644 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/_files/_breadcrumbs_simple_product.html +++ b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/_files/expected_layout_update.xml @@ -25,12 +25,25 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> -<div class="vde_breadcrumbs"> - <a href="http://localhost/index.php/design/editor/page/handle/default/">All Pages</a> - <span class="vde_breadcrumbs_separator">/</span> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_category_default/">Catalog Category (Non-Anchor)</a> - <span class="vde_breadcrumbs_separator">/</span> - <a href="http://localhost/index.php/design/editor/page/handle/catalog_product_view/">Catalog Product View (Any)</a> - <span class="vde_breadcrumbs_separator">/</span> - <span>Catalog Product View (Simple)</span> -</div> +<layout> + <block name="root" type="Mage_Core_Block_Template" template="template.phtml"> + <block name="head" type="Mage_Page_Block_Html_Head"> + <action method="addJs"> + <arg>1</arg> + </action> + </block> + <container name="header" label="Header"> + <block name="safe.block" type="Mage_Page_Block_Html_Header"/> + </container> + <container name="content" label="Content"> + <block name="custom.not_safe" type="Mage_Core_Block_Template" template="Mage_DesignEditor::stub.phtml">%A</block> + <block type="Mage_Page_Block_Html" name="content_schedule_block"/> + </container> + </block> + <reference name="head"> + <action method="addJs"> + <arg>1</arg> + </action> + </reference> + <reference name="custom.not_safe">%A</reference> +</layout> diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/_files/observer_test.xml b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/_files/layout_update.xml similarity index 54% rename from dev/tests/integration/testsuite/Mage/DesignEditor/_files/observer_test.xml rename to dev/tests/integration/testsuite/Mage/DesignEditor/Model/_files/layout_update.xml index dbb8e7a95920210caa7c03efec6b52046b25e699..b1983cb8cfd285685f81931c51276f482ec3e63f 100644 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/_files/observer_test.xml +++ b/dev/tests/integration/testsuite/Mage/DesignEditor/Model/_files/layout_update.xml @@ -1,4 +1,3 @@ -<?xml version="1.0" encoding="UTF-8"?> <!-- /** * Magento @@ -19,25 +18,30 @@ * 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 + * @category Magento * @package Mage_DesignEditor * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> -<layouts> - <test_handle> - <block type="Mage_Core_Block_Text" name="non_draggable_block"/> - <container name="root" label="Root"> - <block type="Mage_Core_Block_Text" name="draggable_block"/> - <container name="draggable_container" label="Draggable Container"/> - <block type="Mage_DesignEditor_Block_Toolbar" name="non_draggable_vde_block" template="toolbar.phtml"/> - </container> - <container name="non_draggable_container" label="Non-Draggable Container"/> - <block type="Mage_Core_Block_Text" name="design_editor_toolbar"> - <action method="setText"><text><![CDATA[<div>VDE Toolbar</div>]]></text></action> +<block name="root" type="Mage_Core_Block_Template" template="template.phtml"> + <block name="head" type="Mage_Page_Block_Html_Head"> + <action method="addJs"><arg>1</arg></action> + </block> + <container name="header" label="Header"> + <block name="safe.block" type="Mage_Page_Block_Html_Header"/> + </container> + <container name="content" label="Content"> + <block name="custom.not_safe" type="Namespace_Module_Block_NotSafe"> + <action method="setTemplate"><arg>some_template.phtml</arg></action> </block> - <container name="after_body_start" label="Page Top"/> - </test_handle> -</layouts> + <block type="Mage_Page_Block_Html" name="content_schedule_block"/> + </container> +</block> +<reference name="head"> + <action method="addJs"><arg>1</arg></action> +</reference> +<reference name="custom.not_safe"> + <action method="rogueMethod"><block>1</block></action> +</reference> diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/_files/design_editor_active.php b/dev/tests/integration/testsuite/Mage/DesignEditor/_files/design_editor_active.php deleted file mode 100644 index 312d21b65b5e51e416730b190896c3fe77c52b14..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/_files/design_editor_active.php +++ /dev/null @@ -1,51 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -/** @var $session Mage_DesignEditor_Model_Session */ -$session = Mage::getModel('Mage_DesignEditor_Model_Session'); -/** @var $auth Mage_Backend_Model_Auth */ -$auth = Mage::getModel('Mage_Backend_Model_Auth'); -$auth->setAuthStorage($session); -$auth->login(Magento_Test_Bootstrap::ADMIN_NAME, Magento_Test_Bootstrap::ADMIN_PASSWORD); -$session->activateDesignEditor(); - -/** @var $theme Mage_Core_Model_Theme */ -$theme = Mage::getModel('Mage_Core_Model_Theme'); -$theme->setData(array( - 'theme_code' => 'blank', - 'area' => 'frontend', - 'parent_id' => null, - 'theme_path' => 'default/blank', - 'theme_version' => '2.0.0.0', - 'theme_title' => 'Default', - 'preview_image' => 'media/preview_image.jpg', - 'magento_version_from' => '2.0.0.0-dev1', - 'magento_version_to' => '*', - 'is_featured' => '0' -)); -$theme->save(); -$session->setThemeId($theme->getId()); diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorControllerTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorControllerTest.php index 3278ec1c9128c7846f55e20d56ed58325940471d..2ca9788cf21ca95b9e0988022134b1e05570d8bf 100644 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorControllerTest.php +++ b/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorControllerTest.php @@ -34,6 +34,17 @@ class Mage_DesignEditor_Adminhtml_System_Design_EditorControllerTest extends Mag */ protected static $_themeId; + /** + * @var Mage_Core_Helper_Data + */ + protected $_dataHelper; + + public function setUp() + { + parent::setUp(); + $this->_dataHelper = $this->_objectManager->get('Mage_Core_Helper_Data'); + } + /** * Create theme is db */ @@ -65,111 +76,95 @@ class Mage_DesignEditor_Adminhtml_System_Design_EditorControllerTest extends Mag $theme->load(self::$_themeId)->delete(); } - /** - * Assert that a page content contains the design editor form - * - * @param string $content - */ - protected function _assertContainsDesignEditor($content) - { - $expectedFormAction = 'http://localhost/index.php/backend/admin/system_design_editor/launch/'; - $this->assertContains('Visual Design Editor', $content); - $this->assertContains('<form id="edit_form" action="' . $expectedFormAction, $content); - $this->assertContains("jQuery('#edit_form').form()", $content); - } - - /** - * Skip the current test, if session identifier is not defined in the environment - */ - public function _requireSessionId() - { - if (!$this->_session->getSessionId()) { - $this->markTestSkipped('Test requires environment with non-empty session identifier.'); - } - } - - public function testIndexActionSingleStore() + public function testIndexAction() { $this->dispatch('backend/admin/system_design_editor/index'); - $this->_assertContainsDesignEditor($this->getResponse()->getBody()); - } + $content = $this->getResponse()->getBody(); - /** - * @magentoDataFixture Mage/Core/_files/store.php - * @magentoConfigFixture fixturestore_store web/unsecure/base_link_url http://example.com/ - */ - public function testIndexActionMultipleStores() - { - $this->dispatch('backend/admin/system_design_editor/index'); - $responseBody = $this->getResponse()->getBody(); - $this->_assertContainsDesignEditor($responseBody); - $this->assertContains('id="store_id" name="store_id"', $responseBody); - $this->assertContains('for="store_id"', $responseBody); - $this->assertContains('Store View', $responseBody); - $this->assertContains('Fixture Store</option>', $responseBody); - } - - /** - * @magentoDataFixture prepareTheme - */ - public function testLaunchActionSingleStore() - { - $session = Mage::getModel('Mage_DesignEditor_Model_Session'); - $this->assertFalse($session->isDesignEditorActive()); - $this->getRequest()->setParam('theme_id', self::$_themeId); - $this->dispatch('backend/admin/system_design_editor/launch'); - $this->assertTrue($session->isDesignEditorActive()); - - $this->_requireSessionId(); - $this->assertRedirect($this->equalTo('http://localhost/index.php/?SID=' . $this->_session->getSessionId())); + $this->assertContains('Choose a theme to start with', $content); + $this->assertContains('<div class="entry-edit">', $content); + $this->assertContains("jQuery('.infinite_scroll').infinite_scroll", $content); } public function testLaunchActionSingleStoreWrongThemeId() { - $session = Mage::getObjectManager()->create('Mage_DesignEditor_Model_Session'); - $this->assertFalse($session->isDesignEditorActive()); $this->getRequest()->setParam('theme_id', 999); $this->dispatch('backend/admin/system_design_editor/launch'); - $this->assertFalse($session->isDesignEditorActive()); - $this->_requireSessionId(); $expected = 'http://localhost/index.php/backend/admin/system_design_editor/index/'; $this->assertRedirect($this->stringStartsWith($expected)); } /** - * @magentoDataFixture prepareTheme - * @magentoDataFixture Mage/Core/_files/store.php - * @magentoConfigFixture fixturestore_store web/unsecure/base_link_url http://example.com/ + * @param array $source + * @param array $result + * @param bool $isXml + * + * @dataProvider getLayoutUpdateActionDataProvider */ - public function testLaunchActionMultipleStores() + public function testGetLayoutUpdateAction(array $source, array $result, $isXml = false) { - $this->getRequest()->setParam('store_id', Mage::app()->getStore('fixturestore')->getId()); - - $session = Mage::getModel('Mage_DesignEditor_Model_Session'); - $this->assertFalse($session->isDesignEditorActive()); - $this->getRequest()->setParam('theme_id', self::$_themeId); - $this->dispatch('backend/admin/system_design_editor/launch'); - $this->assertTrue($session->isDesignEditorActive()); - - $this->_requireSessionId(); - $expected = 'http://example.com/index.php/?SID=' . $this->_session->getSessionId() . '&___store=fixturestore'; - $this->assertRedirect($this->equalTo($expected)); + $this->getRequest()->setPost($source); + $this->dispatch('backend/admin/system_design_editor/getLayoutUpdate'); + $response = $this->_dataHelper->jsonDecode($this->getResponse()->getBody()); + + // convert to XML string to the same format as in $result + if ($isXml) { + foreach ($response as $code => $data) { + foreach ($data as $key => $value) { + $xml = new Varien_Simplexml_Element($value); + $response[$code][$key] = $xml->asNiceXml(); + } + } + } + $this->assertEquals($result, $response); } /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php + * Data provider for testGetLayoutUpdateAction + * + * @return array */ - public function testExitAction() + public function getLayoutUpdateActionDataProvider() { - $session = Mage::getModel('Mage_DesignEditor_Model_Session'); - $this->assertTrue($session->isDesignEditorActive()); - $this->dispatch('backend/admin/system_design_editor/exit'); - - $this->assertFalse($session->isDesignEditorActive()); - $this->assertContains( - '<script type="text/javascript">window.close();</script>', - $this->getResponse()->getBody() + $correctXml = new Varien_Simplexml_Element('<?xml version="1.0" encoding="UTF-8"?><layout/>'); + $correctXml = $correctXml->asNiceXml(); + + return array( + 'no history data' => array( + '$source' => array(), + '$result' => array( + Mage_Core_Model_Message::ERROR => array('Invalid post data') + ), + ), + 'correct data' => array( + '$source' => array('historyData' => array( + array ( + 'handle' => 'current_handle', + 'type' => 'layout', + 'element_name' => 'tags_popular', + 'action_name' => 'move', + 'destination_container' => 'content', + 'destination_order' => '1', + 'origin_container' => 'left', + 'origin_order' => '1', + ), + array ( + 'handle' => 'current_handle', + 'type' => 'layout', + 'element_name' => 'tags_popular', + 'action_name' => 'move', + 'destination_container' => 'left', + 'destination_order' => '1', + 'origin_container' => 'content', + 'origin_order' => '1', + ), + )), + '$result' => array( + Mage_Core_Model_Message::SUCCESS => array($correctXml) + ), + '$isXml' => true, + ), ); } } diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/EditorControllerTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/EditorControllerTest.php deleted file mode 100644 index 37ea087ea99eb0f2900df6abfc8eb474470387a6..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/EditorControllerTest.php +++ /dev/null @@ -1,159 +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 Magento - * @package Mage_DesignEditor - * @subpackage integration_tests - * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -class Mage_DesignEditor_EditorControllerTest extends Magento_Test_TestCase_ControllerAbstract -{ - /** - * @param string $handle - * @param string $expectedMessage - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @dataProvider pageActionErrorDataProvider - */ - public function testPageActionError($handle, $expectedMessage) - { - $this->getRequest()->setParam('handle', $handle); - $this->dispatch('design/editor/page'); - $this->assertEquals(503, $this->getResponse()->getHttpResponseCode()); - $this->assertStringMatchesFormat($expectedMessage, $this->getResponse()->getBody()); - } - - /** - * @return array - */ - public function pageActionErrorDataProvider() - { - return array( - 'no handle type' => array('', 'Invalid page handle specified.'), - 'invalid handle' => array('1nvalid_handle', 'Invalid page handle specified.'), - 'non-existing handle' => array( - 'non_existing_handle', 'Specified page type or page fragment type doesn\'t exist: %s' - ), - ); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - * @dataProvider pageActionDataProvider - * - * @param string $handle - * @param string $requiredModule - */ - public function testPageAction($handle, $requiredModule) - { - if (!in_array($requiredModule, Magento_Test_Helper_Factory::getHelper('config')->getEnabledModules())) { - $this->markTestSkipped("Test requires the module '$requiredModule' to be enabled."); - } - $this->getRequest()->setParam('handle', $handle); - $this->dispatch('design/editor/page'); - $this->assertEquals(200, $this->getResponse()->getHttpResponseCode()); - $controller = Mage::app()->getFrontController()->getAction(); - $this->assertInstanceOf('Mage_DesignEditor_EditorController', $controller); - $this->assertContains( - 'data-selected="li[rel=\'' . $handle . '\']"', - $this->getResponse()->getBody(), - 'Page type control should maintain the selection of the current page handle.' - ); - } - - public function pageActionDataProvider() - { - return array( - 'Catalog Product View' => array('catalog_product_view', 'Mage_Catalog'), - 'One Page Checkout Overview' => array('checkout_onepage_review', 'Mage_Checkout'), - 'Paypal Express Review Details' => array('paypal_express_review_details', 'Mage_Paypal'), - 'Paypal UK Express Review Details' => array('paypaluk_express_review_details', 'Mage_PaypalUk'), - ); - } - - public function testGetFullActionName() - { - $this->dispatch('design/editor/page'); - $controller = Mage::app()->getFrontController()->getAction(); - $this->assertNotInstanceOf('Mage_DesignEditor_EditorController', $controller); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testThemeAction() - { - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - $this->getRequest()->setParam('theme_id', $session->getThemeId()); - $this->dispatch('design/editor/theme'); - $this->assertRedirect(); - - $theme = Mage::getModel('Mage_Core_Model_Theme'); - $theme->load($session->getThemeId()); - - $this->assertEquals('default/blank', $theme->getThemePath()); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testThemeActionWrongValue() - { - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - $this->getRequest()->setParam('theme_id', $session->getThemeId()); - $this->dispatch('design/editor/theme'); - $this->assertRedirect(); - - $theme = Mage::getModel('Mage_Core_Model_Theme'); - $theme->load($session->getThemeId()); - - $this->assertNotEquals('wrong/theme/applied', $theme->getThemePath()); - } - - public function testThemeActionNonActivatedEditor() - { - $this->getRequest()->setParam('theme_id', 0); - $this->dispatch('design/editor/theme'); - $this->assert404NotFound(); - - $session = Mage::getSingleton('Mage_DesignEditor_Model_Session'); - - $theme = Mage::getModel('Mage_Core_Model_Theme'); - $theme->load($session->getThemeId()); - - $this->assertNotEquals('default/blank', $theme->getThemePath()); - } - - /** - * @magentoDataFixture Mage/DesignEditor/_files/design_editor_active.php - */ - public function testThemeActionRedirectUrl() - { - $expectedRedirectUrl = 'http://localhost/index.php/path/to/redirect/?value=1#anchor'; - - $this->getRequest()->setParam( - Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED, - Mage::helper('Mage_Core_Helper_Data')->urlEncode($expectedRedirectUrl) - ); - $this->dispatch('design/editor/theme'); - $this->assertRedirect($this->equalTo($expectedRedirectUrl)); - } -} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/PageControllerTest.php b/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/PageControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fe360e7f66d5a216f6b4b1f2560964f9cc928855 --- /dev/null +++ b/dev/tests/integration/testsuite/Mage/DesignEditor/controllers/PageControllerTest.php @@ -0,0 +1,147 @@ +<?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_DesignEditor + * @subpackage integration_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * All controller actions must be run with logged in admin user + */ +class Mage_DesignEditor_PageControllerTest extends Mage_Adminhtml_Utility_Controller +{ + /** + * Default page type url + */ + const PAGE_TYPE_URL = 'design/page/type'; + + /** + * VDE front name prefix + */ + const VDE_FRONT_NAME = 'vde_front_name'; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * Test handles + * + * @var array + */ + protected $_testHandles = array( + 'incorrect' => '123!@#', + 'not_existing' => 'not_existing_handle', + 'correct' => 'cms_index_index', + ); + + public function setUp() + { + parent::setUp(); + + $this->_objectManager = Mage::getObjectManager(); + } + + /** + * Method preDispatch forwards to noRoute action if user is not logged in admin area + */ + public function testPreDispatch() + { + $this->_auth->logout(); + + $this->dispatch(self::PAGE_TYPE_URL); + + $this->assertEquals('noRoute', $this->getRequest()->getActionName()); + } + + /** + * Exception cases in typeAction method + * + * @param string $url + * @param string $handle + * @param string $expectedMessage + * + * @dataProvider typeActionErrorsDataProvider + * @magentoConfigFixture vde/design_editor/frontName vde_front_name + */ + public function testTypeActionErrors($url, $handle, $expectedMessage) + { + $this->getRequest()->setParam('handle', $handle); + $this->dispatch($url); + + $response = $this->getResponse(); + $this->assertEquals(503, $response->getHttpResponseCode()); + $this->assertEquals($expectedMessage, $response->getBody()); + } + + /** + * Data provider for testTypeActionErrors + * + * @return array + */ + public function typeActionErrorsDataProvider() + { + return array( + 'invalid_handle' => array( + '$url' => self::PAGE_TYPE_URL, + '$handle' => $this->_testHandles['incorrect'], + '$expectedMessage' => 'Invalid page handle specified.', + ), + 'incorrect_layout' => array( + '$url' => self::PAGE_TYPE_URL, + '$handle' => $this->_testHandles['correct'], + '$expectedMessage' => 'Incorrect Design Editor layout.', + ), + 'not_existing_handle' => array( + '$url' => self::VDE_FRONT_NAME . '/' . self::PAGE_TYPE_URL, + '$handle' => $this->_testHandles['not_existing'], + '$expectedMessage' => 'Specified page type or page fragment type doesn\'t exist: "' + . $this->_testHandles['not_existing'] . '".', + ), + ); + } + + /** + * @magentoConfigFixture vde/design_editor/frontName vde_front_name + */ + public function testTypeAction() + { + $this->getRequest()->setParam('handle', $this->_testHandles['correct']); + $this->dispatch(self::VDE_FRONT_NAME . '/' . self::PAGE_TYPE_URL); + + // assert layout data + /** @var $layout Mage_Core_Model_Layout */ + $layout = $this->_objectManager->get('Mage_Core_Model_Layout'); + $handles = $layout->getUpdate()->getHandles(); + $this->assertContains($this->_testHandles['correct'], $handles); + $this->assertContains('designeditor_page_type', $handles); + $this->assertAttributeSame(true, '_sanitationEnabled', $layout); + $this->assertAttributeSame(true, '_wrappingEnabled', $layout); + + // assert response body + $responseBody = $this->getResponse()->getBody(); + $this->assertContains('class="vde_element_wrapper', $responseBody); // enabled wrapper + $this->assertContains('/css/design.css', $responseBody); // included wrapper CSS + } +} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/_files/design_editor_active_rollback.php b/dev/tests/integration/testsuite/Mage/Install/Controller/ActionTest.php similarity index 66% rename from dev/tests/integration/testsuite/Mage/DesignEditor/_files/design_editor_active_rollback.php rename to dev/tests/integration/testsuite/Mage/Install/Controller/ActionTest.php index 44dd7380551d4da30790bb8bd24c1fe71471f519..93cfe5402950e416011ed7b8fa8e2b835f7f74a1 100644 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/_files/design_editor_active_rollback.php +++ b/dev/tests/integration/testsuite/Mage/Install/Controller/ActionTest.php @@ -19,19 +19,18 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Magento - * @package Mage_DesignEditor + * @package Mage_Install * @subpackage integration_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** @var $session Mage_DesignEditor_Model_Session */ -$session = Mage::getModel('Mage_DesignEditor_Model_Session'); -/** @var $auth Mage_Backend_Model_Auth */ -$auth = Mage::getModel('Mage_Backend_Model_Auth'); -$auth->setAuthStorage($session); -$session->deactivateDesignEditor(); -$auth->logout(); -$session->unsThemeId(); -/** @var $theme Mage_Core_Model_Theme */ -$theme = Mage::getModel('Mage_Core_Model_Theme'); -$theme->load($session->getThemeId())->delete(); + +class Mage_Install_Controller_ActionTest extends Magento_Test_TestCase_ControllerAbstract +{ + public function testConstruct() + { + Mage::getObjectManager()->get('Mage_Core_Controller_Varien_Action_Factory') + ->createController('Mage_Install_Controller_Action', array('areaCode' => 'frontend')); + $this->assertEquals('install', Mage::getConfig()->getCurrentAreaCode()); + } +} diff --git a/dev/tests/integration/testsuite/Mage/PageCache/Model/ObserverTest.php b/dev/tests/integration/testsuite/Mage/PageCache/Model/ObserverTest.php index 549884ee4cc42862f7c35420cd6a57c8de7a9929..fc231a355dbdbd6d2219784e03636224981270cd 100644 --- a/dev/tests/integration/testsuite/Mage/PageCache/Model/ObserverTest.php +++ b/dev/tests/integration/testsuite/Mage/PageCache/Model/ObserverTest.php @@ -45,24 +45,24 @@ class Mage_PageCache_Model_ObserverTest extends PHPUnit_Framework_TestCase /** * @magentoConfigFixture current_store system/external_page_cache/enabled 1 */ - public function testDesignEditorSessionActivate() + public function testSetNoCacheCookie() { /** @var $cookie Mage_Core_Model_Cookie */ $cookie = Mage::getSingleton('Mage_Core_Model_Cookie'); $this->assertEmpty($cookie->get(Mage_PageCache_Helper_Data::NO_CACHE_COOKIE)); - $this->_observer->designEditorSessionActivate(new Varien_Event_Observer()); + $this->_observer->setNoCacheCookie(new Varien_Event_Observer()); $this->assertNotEmpty($cookie->get(Mage_PageCache_Helper_Data::NO_CACHE_COOKIE)); } /** * @magentoConfigFixture current_store system/external_page_cache/enabled 1 */ - public function testDesignEditorSessionDeactivate() + public function testDeleteNoCacheCookie() { /** @var $cookie Mage_Core_Model_Cookie */ $cookie = Mage::getSingleton('Mage_Core_Model_Cookie'); $cookie->set(Mage_PageCache_Helper_Data::NO_CACHE_COOKIE, '1'); - $this->_observer->designEditorSessionDeactivate(new Varien_Event_Observer()); + $this->_observer->deleteNoCacheCookie(new Varien_Event_Observer()); $this->assertEmpty($cookie->get(Mage_PageCache_Helper_Data::NO_CACHE_COOKIE)); } } diff --git a/dev/tests/integration/testsuite/Magento/DiTest.php b/dev/tests/integration/testsuite/Magento/DiTest.php index 9cc5010ee993e5e2b849ea18895f7d819f680eef..50ac76ee003a6dcc070e50f02996ee1398b8e8bb 100644 --- a/dev/tests/integration/testsuite/Magento/DiTest.php +++ b/dev/tests/integration/testsuite/Magento/DiTest.php @@ -87,7 +87,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase public static function setUpBeforeClass() { - $magentoDi = new Magento_Di(); + $magentoDi = new Magento_Di_Zend(); $magentoDi->instanceManager()->addTypePreference(self::TEST_INTERFACE, self::TEST_INTERFACE_IMPLEMENTATION); $magentoDi->instanceManager()->addAlias(self::TEST_CLASS_ALIAS, self::TEST_CLASS); self::$_objectManager = new Magento_ObjectManager_Zend(null, $magentoDi); diff --git a/dev/tests/js/jsTestDriver.php.dist b/dev/tests/js/jsTestDriver.php.dist index f4616e676907f6c9fe22efb0115ef616ed9d1c94..05683e5d48e82e534cb34f131038ca0dcd05fc8f 100644 --- a/dev/tests/js/jsTestDriver.php.dist +++ b/dev/tests/js/jsTestDriver.php.dist @@ -39,18 +39,21 @@ return array( '/pub/lib/jquery/ui/i18n', '/pub/lib/jquery/jquery-ui-timepicker-addon.js', '/pub/lib/jquery/jquery.tmpl.min.js', - '/app/code/core/Mage/DesignEditor/view/frontend/js/base.js', + '/app/code/core/Mage/DesignEditor/view/adminhtml/js/base.js', + '/app/code/core/Mage/DesignEditor/view/adminhtml/js/design_editor.js', '/app/code/core/Mage/DesignEditor/view/frontend/js/design_editor.js', + '/app/code/core/Mage/DesignEditor/view/adminhtml/js/infinitescroll.js', '/pub/lib/jquery/jstree/jquery.jstree.js', '/pub/lib/jquery/slimScroll/slimScroll.min.js', '/app/code/core/Mage/Page/view/frontend/js/cookies.js', - '/app/code/core/Mage/DesignEditor/view/frontend/css/styles.css', + '/app/code/core/Mage/DesignEditor/view/adminhtml/css/styles.css', '/pub/lib/mage/calendar.js', '/pub/lib/mage/translate.js', '/pub/lib/mage/loader.js', '/pub/lib/mage/edit-trigger.js', '/pub/lib/mage/translate-inline.js', '/pub/lib/mage/backend/form.js', + '/pub/lib/mage/backend/tabs.js', ), 'test' => array('/dev/tests/js/testsuite'), 'serve' => array('/pub/lib/mage/calendar'), diff --git a/dev/tests/js/testsuite/mage/button/button-test.js b/dev/tests/js/testsuite/mage/button/button-test.js index 9cdcf2bd496adbcf7caecf81f4f5dcd6105ad6d8..2a206be814467b7b4175090c4895a9f4b7fe37cf 100644 --- a/dev/tests/js/testsuite/mage/button/button-test.js +++ b/dev/tests/js/testsuite/mage/button/button-test.js @@ -44,4 +44,4 @@ ButtonTest.prototype.testBind = function() { jQuery('#test-button').button().click(); assertTrue(testEventTriggered); -}; \ No newline at end of file +}; diff --git a/app/code/core/Mage/DesignEditor/view/adminhtml/exit.phtml b/dev/tests/js/testsuite/mage/design_editor/adminhtml/js/infinitescroll.js similarity index 74% rename from app/code/core/Mage/DesignEditor/view/adminhtml/exit.phtml rename to dev/tests/js/testsuite/mage/design_editor/adminhtml/js/infinitescroll.js index 1364e703d106128015ec08f49fdad9ec587299ed..82d52aa9f87a2e0156fb945d47ecd8b11c74ca15 100644 --- a/app/code/core/Mage/DesignEditor/view/adminhtml/exit.phtml +++ b/dev/tests/js/testsuite/mage/design_editor/adminhtml/js/infinitescroll.js @@ -1,4 +1,3 @@ -<?php /** * Magento * @@ -18,10 +17,14 @@ * 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 Mage_DesignEditor + * @category mage.design_editor + * @package test * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -?> -<script type="text/javascript">window.close();</script> +InfiniteScroll = TestCase('InfiniteScroll'); +InfiniteScroll.prototype.testInit = function() { + jQuery(window).infinite_scroll({url: ''}); + assertEquals(true, jQuery(window).is(':vde-infinite_scroll')); + jQuery(window).infinite_scroll('destroy'); +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/checkbox-test.js b/dev/tests/js/testsuite/mage/design_editor/checkbox-test.js index 1521e7bd24e341d6e601f8ab4d47e5d8021394f8..b5c8a03811496093b9e2fb1ff10660d1eee03a1d 100644 --- a/dev/tests/js/testsuite/mage/design_editor/checkbox-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/checkbox-test.js @@ -22,7 +22,7 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -CheckboxTest = TestCase('CheckboxTest'); +CheckboxTest = TestCase('DesignEditor_CheckboxTest'); CheckboxTest.prototype.testInit = function() { /*:DOC += <div id="checkbox"></div> */ var checkbox = jQuery('#checkbox').vde_checkbox(); @@ -51,4 +51,4 @@ CheckboxTest.prototype.testClickEvent = function() { assertEquals(false, checkbox.hasClass(checkedClass)); assertEquals(true, uncheckedEventIsTriggered); checkbox.vde_checkbox('destroy'); -}; \ No newline at end of file +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/connector-test.js b/dev/tests/js/testsuite/mage/design_editor/connector-test.js new file mode 100644 index 0000000000000000000000000000000000000000..fdd79b39c0c7d725caeab6d856a10c5a2e51be2f --- /dev/null +++ b/dev/tests/js/testsuite/mage/design_editor/connector-test.js @@ -0,0 +1,76 @@ +/** + * 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.design_editor + * @package test + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +ConnectorTest = TestCase('DesignEditor_ConnectorTest'); +ConnectorTest.prototype.testDefaultOptions = function() { + var connector = jQuery(window).vde_connector(); + assertEquals('.vde_element_wrapper.vde_container', connector.vde_connector('option', 'containerSelector')); + assertEquals('.vde_element_wrapper', connector.vde_connector('option', 'highlightElementSelector')); + assertEquals('.vde_element_title', connector.vde_connector('option', 'highlightElementTitleSelector')); + assertEquals('#vde_highlighting', connector.vde_connector('option', 'highlightCheckboxSelector')); + assertEquals('.vde_history_toolbar', connector.vde_connector('option', 'historyToolbarSelector')); + connector.vde_connector('destroy'); +}; +ConnectorTest.prototype.testInitHistory = function() { + var connector = jQuery(window).vde_connector(); + assertEquals(true, jQuery(window).is(':vde-vde_history')); + connector.vde_connector('destroy'); +}; +ConnectorTest.prototype.testInitHistoryToolbar = function() { + /*:DOC += <div class="vde_history_toolbar"></div> */ + var connector = jQuery(window).vde_connector(); + var container = jQuery('.vde_history_toolbar'); + assertEquals(true, container.is(':vde-vde_historyToolbar')); + assertNotNull(container.data('vde_historyToolbar')._history); + connector.vde_connector('destroy'); +}; +ConnectorTest.prototype.testInitRemoveOperation = function() { + /*:DOC += <div class="vde_element_wrapper vde-vde_removable"></div> */ + var connector = jQuery(window).vde_connector(); + var containers = jQuery('.vde_element_wrapper'); + assertNotNull(containers.data('vde_removable').history); + connector.vde_connector('destroy'); +}; +ConnectorTest.prototype.testSetHistoryForContainers = function() { + var connector = jQuery(window).vde_connector(); + var containers = jQuery('.vde_element_wrapper.vde_container'); + assertNotNull(containers.vde_container('getHistory')); + connector.vde_connector('destroy'); +}; +ConnectorTest.prototype.testDestroy = function() { + /*:DOC += + <div class="vde_history_toolbar"></div> + <div class="vde_element_wrapper vde_container"></div> + */ + + var connector = jQuery(window).vde_connector(); + connector.vde_connector('destroy'); + + //check no garbage is left + assertFalse($('#vde_toolbar').is(':vde-vde_panel')); + assertFalse($('.vde_history_toolbar').is(':vde-vde_historyToolbar')); + assertFalse($(window).is(':vde-vde_history')); + assertFalse($('.vde_element_wrapper').is(':vde-vde_removable')); + assertFalse($('.vde_element_wrapper.vde_container').is(':vde-vde_container')); +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/container-test.js b/dev/tests/js/testsuite/mage/design_editor/container-test.js index 9ecc429ecf331a3f412ad0b5365f90ace61b852c..2939d0f5552275c0bb806c16453dc439e340b799 100644 --- a/dev/tests/js/testsuite/mage/design_editor/container-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/container-test.js @@ -22,7 +22,7 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -ContainerTest = TestCase('ContainerTest'); +ContainerTest = TestCase('DesignEditor_ContainerTest'); ContainerTest.prototype.testInit = function() { /*:DOC += <div class="vde_element_wrapper vde_container" id="container"></div> */ var container = jQuery('#container').vde_container(); @@ -55,14 +55,14 @@ ContainerTest.prototype.testStartCallback = function() { placeholder: jQuery('<div style="height:0px;"></div>'), helper: jQuery('<div style="height:100px;"></div>'), item: container - } + }; var startCallback = container.vde_container('option', 'start'); startCallback('start', uiMock); assertEquals(false, 0 == uiMock.placeholder.outerHeight()); var connectedWithOtherContainers = container.vde_container('option', 'connectWith').size() > 0; assertEquals(true, connectedWithOtherContainers); containers.vde_container('destroy'); -} +}; ContainerTest.prototype.testOverCallback = function() { /*:DOC += <div class="vde_element_wrapper vde_container" id="container" /> */ var container = jQuery("#container").vde_container(); @@ -71,7 +71,7 @@ ContainerTest.prototype.testOverCallback = function() { overCallback('over', {}); assertEquals(true, container.hasClass(hoverClass)); container.vde_container('destroy'); -} +}; ContainerTest.prototype.testOutCallback = function() { /*:DOC += <div class="vde_element_wrapper vde_container" id="container" /> */ var container = jQuery("#container").vde_container(); @@ -80,4 +80,4 @@ ContainerTest.prototype.testOutCallback = function() { outCallback('out', {}); assertEquals(false, container.hasClass(hoverClass)); container.vde_container('destroy'); -} \ No newline at end of file +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/history-test.js b/dev/tests/js/testsuite/mage/design_editor/history-test.js index d64b818c1ffa9a54017d0356e3a4f6bcc0c3396a..b7d10d4bb5c6dc3c53b8eaa005633e9f715ea780 100644 --- a/dev/tests/js/testsuite/mage/design_editor/history-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/history-test.js @@ -22,7 +22,7 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -HistoryTest = TestCase('HistoryTest'); +HistoryTest = TestCase('DesignEditor_HistoryTest'); HistoryTest.prototype.testInit = function() { jQuery(window).vde_history(); assertEquals(true, jQuery(window).is(':vde-vde_history')); diff --git a/dev/tests/js/testsuite/mage/design_editor/history-toolbar-test.js b/dev/tests/js/testsuite/mage/design_editor/history-toolbar-test.js index 762011cbcea008442bc0af198e7b349f40b00788..4329ce557bba335df8bb5ff9a9c854e3468eb5a3 100644 --- a/dev/tests/js/testsuite/mage/design_editor/history-toolbar-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/history-toolbar-test.js @@ -22,7 +22,7 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -HistoryToolbarTest = TestCase('HistoryToolbarTest'); +HistoryToolbarTest = TestCase('DesignEditor_HistoryToolbarTest'); HistoryToolbarTest.prototype.testInit = function() { /*:DOC += <div class="vde_history_toolbar"></div> */ var container = jQuery('.vde_history_toolbar').vde_historyToolbar(); diff --git a/dev/tests/js/testsuite/mage/design_editor/menu-test.js b/dev/tests/js/testsuite/mage/design_editor/menu-test.js index 13d90355916a0819285f2a4751414e2fa7469b24..50423996eb71134770128b9bf422526d704ac322 100644 --- a/dev/tests/js/testsuite/mage/design_editor/menu-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/menu-test.js @@ -22,7 +22,7 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -MenuTest = TestCase('MenuTest'); +MenuTest = TestCase('DesignEditor_MenuTest'); MenuTest.prototype.testInit = function() { /*:DOC += <div id="menu"></div> */ var menu = jQuery('#menu').vde_menu(); @@ -138,4 +138,4 @@ MenuTest.prototype.testHideMenuOnBodyClick = function() { assertEquals(false, menu.hasClass(activeClass)); menu.vde_menu('destroy'); jQuery.fx.off = false; -} \ No newline at end of file +} diff --git a/dev/tests/js/testsuite/mage/design_editor/page-test.js b/dev/tests/js/testsuite/mage/design_editor/page-test.js index 359b4bd37a99a0f02ec4223b9a5911970aa1cdb7..737a8c260bfd6c70c54763576c49a744a93dca81 100644 --- a/dev/tests/js/testsuite/mage/design_editor/page-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/page-test.js @@ -22,213 +22,32 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -PageTest = TestCase('PageTest'); +PageTest = TestCase('DesignEditor_PageTest'); PageTest.prototype.testInit = function() { - var page = jQuery('body').vde_page(); + var page = jQuery(window).vde_page(); assertEquals(true, page.is(':vde-vde_page')); page.vde_page('destroy'); }; PageTest.prototype.testDefaultOptions = function() { - var page = jQuery('body').vde_page(); + var page = jQuery(window).vde_page(); + assertEquals('iframe#vde_container_frame', page.vde_page('option', 'frameSelector')); assertEquals('.vde_element_wrapper.vde_container', page.vde_page('option', 'containerSelector')); - assertEquals('#vde_toolbar', page.vde_page('option', 'panelSelector')); + assertEquals('#vde_toolbar_row', page.vde_page('option', 'panelSelector')); assertEquals('.vde_element_wrapper', page.vde_page('option', 'highlightElementSelector')); assertEquals('.vde_element_title', page.vde_page('option', 'highlightElementTitleSelector')); assertEquals('#vde_highlighting', page.vde_page('option', 'highlightCheckboxSelector')); - assertEquals('vde_highlighting', page.vde_page('option', 'cookieHighlightingName')); page.vde_page('destroy'); }; -PageTest.prototype.testInitContainers = function() { - /*:DOC += <div class="vde_element_wrapper vde_container"></div> */ - var page = jQuery('body').vde_page(); - var containerSelector = page.vde_page('option', 'containerSelector'); - assertEquals(true, jQuery(containerSelector).is(':vde-vde_container')); - page.vde_page('destroy'); -} -PageTest.prototype.testInitPanel = function() { - /*:DOC += <div id="vde_toolbar"></div> */ - var page = jQuery('body').vde_page(); - var panelSelector = page.vde_page('option', 'panelSelector'); - assertEquals(true, jQuery(panelSelector).is(':vde-vde_panel')); - page.vde_page('destroy'); -} PageTest.prototype.testInitHighlighting = function() { - /*:DOC += <div id="vde_toolbar"><div id="vde_highlighting"></div></div> */ - var page = jQuery('body').vde_page(); + /*:DOC += <div id="vde_toolbar_row"><div id="vde_highlighting"></div></div> */ + var page = jQuery(window).vde_page(); var highlightCheckboxSelector = page.vde_page('option', 'highlightCheckboxSelector'); assertEquals(true, jQuery(highlightCheckboxSelector).is(':vde-vde_checkbox')); page.vde_page('destroy'); -} -PageTest.prototype.testProcessMarkers = function() { - /*:DOC += - <div> - <div id="vde_element_1" class="vde_element_wrapper vde_container vde_wrapper_hidden"> - <div class="vde_element_title">Title 1</div> - </div> - <!--start_vde_element_1--> - <div id="vde_element_2" class="vde_element_wrapper vde_draggable vde_wrapper_hidden"> - <div class="vde_element_title">Title 2</div> - </div> - <!--start_vde_element_2--> - <div class="block block-list"> - <div class="block-title"> - <strong><span>Block Title</span></strong> - </div> - <div class="block-content"> - <p class="empty">Block Content</p> - </div> - </div> - <!--end_vde_element_2--> - <!--end_vde_element_1--> - </div> - */ - var page = jQuery('body').vde_page(); - var cookieHighlightingName = page.vde_page('option', 'cookieHighlightingName'); - page.vde_page('destroy'); - $.mage.cookies.set(cookieHighlightingName, 'off'); - page = jQuery('body').vde_page(); - var commentsExist = false; - jQuery('*').contents().each(function () { - if (this.nodeType == Node.COMMENT_NODE) { - if (this.data.substr(0, 9) == 'start_vde') { - commentsExist = true; - } else if (this.data.substr(0, 7) == 'end_vde') { - commentsExist = true; - } - } - }); - assertEquals(false, commentsExist); -} -PageTest.prototype.testHighlight = function() { - /*:DOC += - <div> - <div id="vde_element_1" class="vde_element_wrapper vde_container vde_wrapper_hidden"> - <div class="vde_element_title">Title 1</div> - </div> - <!--start_vde_element_1--> - <div id="vde_element_2" class="vde_element_wrapper vde_draggable vde_wrapper_hidden"> - <div class="vde_element_title">Title 2</div> - </div> - <!--start_vde_element_2--> - <div class="block block-list" id="block"> - <div class="block-title"> - <strong><span>Block Title</span></strong> - </div> - <div class="block-content"> - <p class="empty">Block Content</p> - </div> - </div> - <!--end_vde_element_2--> - <div id="vde_element_3" class="vde_element_wrapper vde_draggable vde_wrapper_hidden"> - <div class="vde_element_title">Title 3</div> - </div> - <!--end_vde_element_1--> - </div> - */ - jQuery.fx.off = true; - var page = jQuery('body').vde_page(); - var cookieHighlightingName = page.vde_page('option', 'cookieHighlightingName'); - page.vde_page('destroy'); - $.mage.cookies.set(cookieHighlightingName, 'off'); - page = jQuery('body').vde_page(); - page.trigger('checked.vde_checkbox'); - var resultHierarchy = { - vde_element_1: ['vde_element_2', 'vde_element_3'], - vde_element_2: ['block'] - } - var hierarchyIsCorrect = true; - jQuery.each(resultHierarchy, function(parentKey, parentVal) { - jQuery.each(parentVal, function(childKey, childVal) { - if (!jQuery('#' + parentKey).has(jQuery('#' + childVal))) { - hierarchyIsCorrect = false; - } - }) - }); - assertEquals(true, hierarchyIsCorrect); - assertEquals(true, jQuery('.vde_wrapper_hidden').is(':visible')); - assertEquals(null, $.mage.cookies.get(cookieHighlightingName)); - var highlightElementTitleSelector = page.vde_page('option', 'highlightElementTitleSelector'); - assertEquals(true, jQuery(highlightElementTitleSelector).is(':visible')); - page.vde_page('destroy'); - jQuery.fx.off = false; -} -PageTest.prototype.testUnhighlight = function() { - /*:DOC += - <div> - <div id="vde_element_1" class="vde_element_wrapper vde_container"> - <div class="vde_element_title">Title 1</div> - <div id="vde_element_2" class="vde_element_wrapper vde_draggable"> - <div class="vde_element_title">Title 2</div> - <div class="block block-list block-compare" id="block"> - <div class="block-title"> - <strong><span>Block Title</span></strong> - </div> - <div class="block-content"> - <p class="empty">Block Content</p> - </div> - </div> - </div> - </div> - </div> - */ - jQuery.fx.off = true; - var page = jQuery('body').vde_page(); - var highlightElementTitleSelector = page.vde_page('option', 'highlightElementTitleSelector'); - var highlightElementSelector = page.vde_page('option', 'highlightElementSelector'); - var hierarchy = {}; - jQuery(highlightElementSelector).each(function() { - var elem = jQuery(this); - hierarchy[elem.attr('id')] = elem.contents(':not(' + highlightElementTitleSelector + ')'); - }) - var cookieHighlightingName = page.vde_page('option', 'cookieHighlightingName'); - page.vde_page('destroy'); - $.mage.cookies.clear(cookieHighlightingName); - page = jQuery('body').vde_page(); - page.trigger('unchecked.vde_checkbox'); - var hierarchyIsCorrect = true; - jQuery.each(hierarchy, function(parentKey, parentVal) { - jQuery.each(parentVal, function() { - if (jQuery(this).parents('#' + parentKey).size()) { - hierarchyIsCorrect = false; - } - }) - }); - assertEquals(true, hierarchyIsCorrect); - assertEquals(false, jQuery('.vde_wrapper_hidden').is(':visible')); - assertEquals('off', $.mage.cookies.get(cookieHighlightingName)); - assertEquals(false, jQuery(highlightElementTitleSelector).is(':visible')); - page.vde_page('destroy'); - jQuery.fx.off = false; -} -PageTest.prototype.testInitHistory = function() { - var page = jQuery('body').vde_page(); - assertEquals(true, jQuery(window).is(':vde-vde_history')); - page.vde_page('destroy'); -} -PageTest.prototype.testInitHistoryToolbar = function() { - /*:DOC += <div class="vde_history_toolbar"></div> */ - jQuery(window).vde_page(); - var container = jQuery('.vde_history_toolbar'); - assertEquals(true, container.is(':vde-vde_historyToolbar')); - assertNotNull(container.data('vde_historyToolbar')._history); - jQuery(window).vde_page('destroy'); -}; -PageTest.prototype.testInitRemoveOperation = function() { - /*:DOC += <div class="vde_element_wrapper"></div> */ - jQuery(window).vde_page(); - var containers = jQuery('.vde_element_wrapper'); - assertEquals(true, containers.is(':vde-vde_removable')); - jQuery(window).vde_page('destroy'); -}; -PageTest.prototype.testSetHistoryForContainers = function() { - jQuery(window).vde_page(); - var containers = jQuery('.vde_element_wrapper.vde_container'); - assertNotNull(containers.vde_container('getHistory')); - jQuery(window).vde_page('destroy'); }; PageTest.prototype.testDestroy = function() { /*:DOC += - <div id="vde_toolbar"></div> + <div id="vde_toolbar_row"></div> <div class="vde_history_toolbar"></div> <div class="vde_element_wrapper vde_container"></div> */ @@ -237,7 +56,7 @@ PageTest.prototype.testDestroy = function() { jQuery(window).vde_page('destroy'); //check no garbage is left - assertFalse($('#vde_toolbar').is(':vde-vde_panel')); + assertFalse($('#vde_toolbar_row').is(':vde-vde_panel')); assertFalse($('.vde_history_toolbar').is(':vde-vde_historyToolbar')); assertFalse($(window).is(':vde-vde_history')); assertFalse($('.vde_element_wrapper').is(':vde-vde_removable')); diff --git a/dev/tests/js/testsuite/mage/design_editor/page-test/highlight-test.js b/dev/tests/js/testsuite/mage/design_editor/page-test/highlight-test.js new file mode 100644 index 0000000000000000000000000000000000000000..0754b2c70aedead7a556b0b54b6997264c39b54c --- /dev/null +++ b/dev/tests/js/testsuite/mage/design_editor/page-test/highlight-test.js @@ -0,0 +1,92 @@ +/** + * 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.design_editor + * @package test + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +PageTestHighlight = TestCase('DesignEditor_PageTest_Highlight'); +PageTestHighlight.prototype.testHighlight = function() { + /*:DOC += + <iframe name="vde_container_frame" id="vde_container_frame" class="vde_container_frame"></iframe> + */ + /*:DOC iframeContent = + <div> + <div id="vde_element_1" class="vde_element_wrapper vde_container"> + <div class="vde_element_title">Title 1</div> + </div> + <!--start_vde_element_1--> + <div id="vde_element_2" class="vde_element_wrapper vde_draggable"> + <div class="vde_element_title">Title 2</div> + </div> + <!--start_vde_element_2--> + <div class="block block-list" id="block"> + <div class="block-title"> + <strong><span>Block Title</span></strong> + </div> + <div class="block-content"> + <p class="empty">Block Content</p> + </div> + </div> + <!--end_vde_element_2--> + <div id="vde_element_3" class="vde_element_wrapper vde_draggable"> + <div class="vde_element_title">Title 3</div> + </div> + <!--end_vde_element_1--> + </div> + */ + + jQuery.fx.off = true; + var page = jQuery(window).vde_page(); + var frameSelector = page.vde_page('option', 'frameSelector'); + + jQuery(frameSelector).triggerHandler('load'); + jQuery(frameSelector).contents().find("body:first").html(this.iframeContent); + page.trigger('checked.vde_checkbox'); + var resultHierarchy = { + vde_element_1: ['vde_element_2', 'vde_element_3'], + vde_element_2: ['block'] + }; + var hierarchyIsCorrect = null; + jQuery.each(resultHierarchy, function(parentKey, parentVal) { + jQuery.each(parentVal, function(childKey, childVal) { + hierarchyIsCorrect = !!jQuery(frameSelector).contents().find('#' + parentKey) + .has(jQuery(frameSelector).contents().find('#' + childVal)); + }) + }); + assertEquals(true, hierarchyIsCorrect); + + var highlightElementSelector = page.vde_page('option', 'highlightElementSelector'); + assertEquals(true, jQuery(frameSelector).contents().find(highlightElementSelector).size() > 0); + jQuery(frameSelector).contents().find(highlightElementSelector).each(function() { + assertEquals(true, $(this).is(':visible')); + }); + + var highlightElementTitleSelector = page.vde_page('option', 'highlightElementTitleSelector'); + assertEquals(true, + jQuery(frameSelector).contents().find(highlightElementTitleSelector).size() > 0 + ); + jQuery(frameSelector).contents().find(highlightElementTitleSelector).each(function() { + assertEquals(true, $(this).is(':visible')); + }); + + page.vde_page('destroy'); + jQuery.fx.off = false; +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/page-test/init-panel-test.js b/dev/tests/js/testsuite/mage/design_editor/page-test/init-panel-test.js new file mode 100644 index 0000000000000000000000000000000000000000..f80e485cab8e57fcb293d95d7f0392cbdaf9f41a --- /dev/null +++ b/dev/tests/js/testsuite/mage/design_editor/page-test/init-panel-test.js @@ -0,0 +1,37 @@ +/** + * 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.design_editor + * @package test + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +PageTestInitPanel = TestCase('DesignEditor_PageTest_InitPanel'); +PageTestInitPanel.prototype.testInitPanel = function() { + /*:DOC += + <div id="vde_toolbar_row"></div> + <iframe name="vde_container_frame" id="vde_container_frame" class="vde_container_frame"></iframe> + */ + var page = jQuery(window).vde_page(); + var frameSelector = page.vde_page('option', 'frameSelector'); + jQuery(frameSelector).triggerHandler('load'); + var panelSelector = page.vde_page('option', 'panelSelector'); + assertEquals(true, jQuery(panelSelector).is(':vde-vde_panel')); + page.vde_page('destroy'); +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/page-test/process-markers-test.js b/dev/tests/js/testsuite/mage/design_editor/page-test/process-markers-test.js new file mode 100644 index 0000000000000000000000000000000000000000..efb1a726348a7c1f807cb41ada94a98f4dcd1753 --- /dev/null +++ b/dev/tests/js/testsuite/mage/design_editor/page-test/process-markers-test.js @@ -0,0 +1,68 @@ +/** + * 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.design_editor + * @package test + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +PageTestProcessMarkers = TestCase('DesignEditor_PageTest_ProcessMarkers'); +PageTestProcessMarkers.prototype.testProcessMarkers = function() { + /*:DOC += <iframe name="vde_container_frame" id="vde_container_frame" class="vde_container_frame"></iframe> */ + /*:DOC iframeContent = + <div> + <div id="vde_element_1" class="vde_element_wrapper vde_container"> + <div class="vde_element_title">Title 1</div> + </div> + <!--start_vde_element_1--> + <div id="vde_element_2" class="vde_element_wrapper vde_draggable"> + <div class="vde_element_title">Title 2</div> + </div> + <!--start_vde_element_2--> + <div class="block block-list"> + <div class="block-title"> + <strong><span>Block Title</span></strong> + </div> + <div class="block-content"> + <p class="empty">Block Content</p> + </div> + </div> + <!--end_vde_element_2--> + <!--end_vde_element_1--> + </div> + */ + var page = jQuery(window).vde_page(); + var frameSelector = page.vde_page('option', 'frameSelector'); + jQuery(frameSelector).triggerHandler('load'); + jQuery(frameSelector).contents().find("body:first").html(this.iframeContent); + page.vde_page('destroy'); + var commentsExist = null; + jQuery(frameSelector).contents().find('*').contents().each(function () { + if (this.nodeType == Node.COMMENT_NODE) { + if (this.data.substr(0, 9) == 'start_vde') { + commentsExist = true; + } else { + commentsExist = this.data.substr(0, 7) == 'end_vde'; + } + } else { + commentsExist = false; + } + }); + assertEquals(false, commentsExist); +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/page-test/unhighlight-test.js b/dev/tests/js/testsuite/mage/design_editor/page-test/unhighlight-test.js new file mode 100644 index 0000000000000000000000000000000000000000..ab08f07eec6955878fbfe5d4b89d29ad2278fe2b --- /dev/null +++ b/dev/tests/js/testsuite/mage/design_editor/page-test/unhighlight-test.js @@ -0,0 +1,89 @@ +/** + * 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.design_editor + * @package test + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +PageTestUnhighlight = TestCase('DesignEditor_PageTest_Unhighlight'); +PageTestUnhighlight.prototype.testUnhighlight = function() { + /*:DOC += <iframe name="vde_container_frame" id="vde_container_frame" class="vde_container_frame"></iframe> */ + /*:DOC iframeContent = + <div> + <div id="vde_element_1" class="vde_element_wrapper vde_container"> + <div class="vde_element_title">Title 1</div> + <div id="vde_element_2" class="vde_element_wrapper vde_draggable"> + <div class="vde_element_title">Title 2</div> + <div class="block block-list block-compare" id="block"> + <div class="block-title"> + <strong><span>Block Title</span></strong> + </div> + <div class="block-content"> + <p class="empty">Block Content</p> + </div> + </div> + </div> + </div> + </div> + */ + + jQuery.fx.off = true; + var page = jQuery(window).vde_page(); + + var frameSelector = page.vde_page('option', 'frameSelector'); + + jQuery(frameSelector).triggerHandler('load'); + jQuery(frameSelector).contents().find("body:first").html(this.iframeContent); + + var highlightElementTitleSelector = page.vde_page('option', 'highlightElementTitleSelector'); + var highlightElementSelector = page.vde_page('option', 'highlightElementSelector'); + assertEquals(true, jQuery(frameSelector).contents().find(highlightElementSelector).size() > 0); + var hierarchy = {}; + jQuery(frameSelector).contents().find(highlightElementSelector).each(function() { + var elem = jQuery(this); + hierarchy[elem.attr('id')] = elem.contents(':not(' + highlightElementTitleSelector + ')'); + }); + page.vde_page('destroy'); + page = jQuery(window).vde_page(); + jQuery(frameSelector).triggerHandler('load'); + page.trigger('unchecked.vde_checkbox'); + var hierarchyIsCorrect = null; + jQuery.each(hierarchy, function(parentKey, parentVal) { + jQuery.each(parentVal, function() { + hierarchyIsCorrect = !jQuery(this).parents('#' + parentKey).size(); + }) + }); + assertEquals(true, hierarchyIsCorrect); + + assertEquals(true, jQuery(frameSelector).contents().find(highlightElementSelector).size() > 0); + jQuery(frameSelector).contents().find(highlightElementSelector).each(function() { + assertEquals(false, $(this).is(':visible')); + }); + + assertEquals(true, + jQuery(frameSelector).contents().find(highlightElementTitleSelector).size() > 0 + ); + jQuery(frameSelector).contents().find(highlightElementTitleSelector).each(function() { + assertEquals(false, $(this).is(':visible')); + }); + + page.vde_page('destroy'); + jQuery.fx.off = false; +}; diff --git a/dev/tests/js/testsuite/mage/design_editor/panel-test.js b/dev/tests/js/testsuite/mage/design_editor/panel-test.js index 01519e070c84eda862cac3b32d7911b66bb725ea..fd20b5dfbd809112fcd2fc29eafac480d3455536 100644 --- a/dev/tests/js/testsuite/mage/design_editor/panel-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/panel-test.js @@ -22,7 +22,7 @@ * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -PanelTest = TestCase('PanelTest'); +PanelTest = TestCase('DesignEditor_PanelTest'); PanelTest.prototype.testInit = function() { /*:DOC += <div id="panel"></div> */ var panel = jQuery('#panel').vde_panel(); diff --git a/dev/tests/js/testsuite/mage/design_editor/tree-test.js b/dev/tests/js/testsuite/mage/design_editor/tree-test.js index cf02c7529eb32880b169b1a63ceb43e356213b38..d6c34aaabd727bc0504f0394433e57dc7979e487 100644 --- a/dev/tests/js/testsuite/mage/design_editor/tree-test.js +++ b/dev/tests/js/testsuite/mage/design_editor/tree-test.js @@ -23,7 +23,7 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ -TreeTest = TestCase('TreeTest'); +TreeTest = TestCase('DesignEditor_TreeTest'); TreeTest.prototype.testInit = function() { /*:DOC += <div id="tree"></div> */ var tree = jQuery('#tree').vde_tree(); @@ -41,7 +41,7 @@ TreeTest.prototype.testDefaultOptions = function() { assertEquals(false, themes.icons); tree.vde_tree('destroy'); }; -var TreeTestAsync = AsyncTestCase('TreeTestAsync'); +var TreeTestAsync = AsyncTestCase('DesignEditor_TreeTestAsync'); TreeTestAsync.prototype.testTreeLoadWithInitialSelect = function(queue) { /*:DOC += <div id="tree"> @@ -117,7 +117,7 @@ TreeTestAsync.prototype.testTreeSelectNodeOnLoad = function(queue) { }) .on('select_node.jstree', function(e, data) { linkSelected(jQuery(data.rslt.obj).find('a:first').attr('href')); - }) + }); tree.vde_tree(); }); queue.call('Step 2: Check if "select_node" event is triggered', function() { @@ -133,24 +133,25 @@ TreeTestAsync.prototype.testTreeSelectNode = function(queue) { <li rel="tree_element"><a href="#link">All Pages</a></li> </ul> </div> + <iframe name="vde_container_frame" id="vde_container_frame" class="vde_container_frame"></iframe> */ var tree = jQuery('#tree'); var linkSelectedEventIsTriggered = false; var locationIsChanged = false; queue.call('Step 1: Bind callback on "link_selected" event and initialize tree widget', function(callbacks) { var nodeSelected = callbacks.add(function(url) { - locationIsChanged = window.location.hash == url; + locationIsChanged = $('.vde_container_frame').attr('src') == url; }); tree .on('loaded.jstree', function() { tree.on('select_node.jstree', function(e, data) { nodeSelected(jQuery(data.rslt.obj).find('a:first').attr('href')); - }) + }); jQuery('li[rel="tree_element"] a').trigger('click'); }) .on('link_selected.vde_tree', function() { linkSelectedEventIsTriggered = true; - }) + }); tree.vde_tree(); }); queue.call('Step 2: Check if "link_selected" event is triggered', function() { diff --git a/dev/tests/js/testsuite/mage/form/form-test.js b/dev/tests/js/testsuite/mage/form/form-test.js index 9c7b631cfd123a6ed65a21a1e30719ed045ee8b1..12555291e86d43fb26d58248aadd66a8193cd26b 100644 --- a/dev/tests/js/testsuite/mage/form/form-test.js +++ b/dev/tests/js/testsuite/mage/form/form-test.js @@ -89,6 +89,7 @@ FormTest.prototype.testBind = function() { form.on('submit', function(e) { submitted = true; e.stopImmediatePropagation(); + e.preventDefault(); }); $.each(handlersData, function(key) { form.trigger(key); @@ -190,6 +191,10 @@ FormTest.prototype.testBeforeSubmit = function() { form.on('beforeSubmit', function(e, data) { jQuery.extend(data, beforeSubmitData); }); + form.on('submit', function(e) { + e.stopImmediatePropagation(); + e.preventDefault(); + }); form.data("form")._beforeSubmit('testHandler', eventData); assertEquals(testForm.prop('action'), form.prop('action')); @@ -210,6 +215,7 @@ FormTest.prototype.testSubmit = function() { form.data("form")._storeAttribute('method'); form .on('submit', function(e) { + e.preventDefault(); e.stopImmediatePropagation(); formSubmitted = true; }) diff --git a/dev/tests/js/testsuite/mage/tabs/tabs-test.js b/dev/tests/js/testsuite/mage/tabs/tabs-test.js new file mode 100644 index 0000000000000000000000000000000000000000..7119bee4060e8c1bf63bf88651463d60aa9da6a7 --- /dev/null +++ b/dev/tests/js/testsuite/mage/tabs/tabs-test.js @@ -0,0 +1,261 @@ +/** + * 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.js + * @package test + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +TabsTest = TestCase('TabsTest'); +TabsTest.prototype.testInit = function() { + /*:DOC += <div id="tabs"></div>*/ + var tabs = jQuery('#tabs').tabs(); + assertTrue(tabs.is(':mage-tabs')); +}; + +TabsTest.prototype.testCreate = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="#tab1_content" id="tab1"></a> + <div id="tab1_content"></div> + </li> + <li> + <a href="#tab2_content" id="tab2"></a> + <div id="tab2_content"></div> + </li> + </ul></div>*/ + var tabs = jQuery('#tabs').tabs({active: 'tab2'}); + assertEquals(tabs.tabs('option', 'active'), tabs.data("tabs").anchors.index(jQuery('#tab2'))); +}; + +TabsTest.prototype.testActiveAnchor = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="#tab1_content" id="tab1"></a> + <div id="tab1_content"></div> + </li> + <li> + <a href="#tab2_content" id="tab2"></a> + <div id="tab2_content"></div> + </li> + </ul></div>*/ + var tabs = jQuery('#tabs').tabs({active: 'tab2'}); + assertTrue(tabs.tabs('activeAnchor').is(tabs.data("tabs").anchors.eq(tabs.tabs('option', 'active')))); +}; + +TabsTest.prototype.testGetTabIndex = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="#tab1_content" id="tab1"></a> + <div id="tab1_content"></div> + </li> + <li> + <a href="#tab2_content" id="tab2"></a> + <div id="tab2_content"></div> + </li> + </ul></div>*/ + var tabs = jQuery('#tabs').tabs(); + assertEquals(0, tabs.data("tabs")._getTabIndex('tab1')); + assertEquals(1, tabs.data("tabs")._getTabIndex('tab2')); +}; + +TabsTest.prototype.testGetPanelForTab = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="#tab1_content" id="tab1"></a> + </li> + </ul></div> + <div id="destination"> + <div id="tab1_content"></div> + </div>*/ + var tabs = jQuery('#tabs').tabs({destination: '#destination'}); + assertTrue(jQuery(tabs.data("tabs")._getPanelForTab(jQuery('#tab1').closest('li'))).is('#tab1_content')); +}; + +TabsTest.prototype.testMovePanelsInDestination = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="#tab1_content" id="tab1"></a> + <div id="tab1_content"></div> + </li> + </ul></div> + <div id="destination"> + </div>*/ + var tabs = jQuery('#tabs').tabs({destination: '#destination'}); + var panel = jQuery('#tab1_content'); + tabs.append(panel); + assertTrue(panel.parents('#tabs').length > 0); + assertEquals(panel.parents(tabs.tabs('option', 'destination')).length, 0); + + tabs.data("tabs")._movePanelsInDestination(panel); + assertEquals(panel.parents('#tabs').length, 0); + assertTrue(panel.parents(tabs.tabs('option', 'destination')).length > 0); + + tabs.tabs('option', 'destination', null); + tabs.append(panel); + assertTrue(panel.parents('#tabs').length > 0); + + tabs.data("tabs")._movePanelsInDestination(panel); + assertTrue(panel.parents('#tabs').length > 0); +}; + +TabsTest.prototype.testAjaxBeforeLoad = function() { + /*:DOC += <div id="tabs"></div>*/ + var tabs = jQuery('#tabs').tabs(), + processStart = false; + + jQuery('body').off().on('processStart', function(){processStart = true;}); + tabs.tabs('option', 'beforeLoad')(); + assertTrue(processStart); +}; + +TabsTest.prototype.testAjaxLoad = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="www.site.com" id="tab1">Tab 1</a> + <div id="tab1_content"></div> + </li> + </ul></div> + */ + var tabs = jQuery('#tabs').tabs(), + processStop = false, + ui = { + tab: jQuery('#tab1'), + panel: jQuery('#tab1_content') + }; + jQuery('body').off().on('processStop', function(){processStop = true;}); + tabs.tabs('option', 'load')({}, ui); + + assertTrue(processStop); + assertEquals(jQuery('#tab1').attr('href'), '#tab1_content'); +}; + +TabsTest.prototype.testOnContentChange = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="www.site.com" id="tab1">Tab 1</a> + <div id="tab1_content"></div> + </li> + </ul></div> + */ + var eventMock = { + data: { + index: 0 + } + }, + tabs = jQuery('#tabs').tabs(); + + tabs.data("tabs")._onContentChange(eventMock); + assertTrue(jQuery('#tab1').hasClass('changed')); +}; + +TabsTest.prototype.testOnInvalid = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="www.site.com" id="tab1">Tab 1<span class="error"> </span></a> + <div id="tab1_content"></div> + </li> + </ul></div> + */ + var eventMock = { + data: { + index: 0 + } + }, + tabs = jQuery('#tabs').tabs(), + errorIcon = jQuery('#tab1').find('.error'); + + errorIcon.hide(); + assertTrue(errorIcon.is(':hidden')); + + tabs.data("tabs")._onInvalid(eventMock); + assertTrue(jQuery('#tab1').hasClass('error')); + assertTrue(errorIcon.is(':visible')); +}; + +TabsTest.prototype.testOnFocus = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="#tab1_content" id="tab1"></a> + <div id="tab1_content"></div> + </li> + <li> + <a href="#tab2_content" id="tab2"></a> + <div id="tab2_content"><input /></div> + </li> + </ul></div> + */ + var eventMock = { + data: { + index: 1 + } + }, + tabs = jQuery('#tabs').tabs(); + + assertNotEquals(tabs.tabs('option', 'active'), eventMock.data.index); + + tabs.data("tabs")._onFocus(eventMock); + assertEquals(tabs.tabs('option', 'active'), eventMock.data.index); +}; + +TabsTest.prototype.testOnBeforeSubmit = function() { + /*:DOC += <div id="tabs"><ul> + <li> + <a href="#tab1_content" id="tab1"></a> + <div id="tab1_content"></div> + </li> + </ul></div> + */ + var tabs = jQuery('#tabs').tabs({active: 'tab1'}), + data= {}, + testData = { + action: { + args: { + tab: 'tab1' + } + } + }, + testDataTabArgument = { + action: { + args: { + testtab: 'tab1' + } + } + }, + tabPrefix = 'test-', + tabIdArgument = 'testtab'; + + tabs.data("tabs")._onBeforeSubmit({}, data); + assertEquals(data, testData); + data = {}; + + jQuery('#tab1').prop('id', 'test-tab1'); + tabs.tabs('option', 'tabsBlockPrefix', tabPrefix); + tabs.data("tabs")._onBeforeSubmit({}, data); + assertEquals(data, testData); + tabs.tabs('option', 'tabsBlockPrefix', null); + jQuery('#test-tab1').prop('id', 'tab1'); + data = {}; + + tabs.tabs('option', 'tabIdArgument', tabIdArgument); + tabs.data("tabs")._onBeforeSubmit({}, data); + assertEquals(data, testDataTabArgument); +}; + + diff --git a/dev/tests/static/testsuite/Legacy/LayoutTest.php b/dev/tests/static/testsuite/Legacy/LayoutTest.php index 8f4435b0db555df6fbf7cfcb2ee2a0592772bb09..37d38438c1d317ed15f5e1b3c06a5bdba418a12e 100644 --- a/dev/tests/static/testsuite/Legacy/LayoutTest.php +++ b/dev/tests/static/testsuite/Legacy/LayoutTest.php @@ -106,7 +106,9 @@ class Legacy_LayoutTest extends PHPUnit_Framework_TestCase $this->_testObsoleteReferences($layoutXml); - $selectorHeadBlock = '(name()="block" or name()="reference") and (@name="head" or @name="convert_root_head")'; + $selectorHeadBlock = ' + (name()="block" or name()="reference") and (@name="head" or @name="convert_root_head" or @name="vde_head") + '; $this->assertSame(array(), $layoutXml->xpath( '//*[' . $selectorHeadBlock . ']/action[@method="addItem"]' diff --git a/dev/tests/static/testsuite/Legacy/_files/obsolete_constants.php b/dev/tests/static/testsuite/Legacy/_files/obsolete_constants.php index ef1601a33c1c7755dec00ca835787452b900370c..be41ef8c0495e02a6b2647d622ed8d0003fdefd8 100644 --- a/dev/tests/static/testsuite/Legacy/_files/obsolete_constants.php +++ b/dev/tests/static/testsuite/Legacy/_files/obsolete_constants.php @@ -63,4 +63,5 @@ return array( $this->_getRule('HASH_ALGO'), $this->_getRule('SEESION_MAX_COOKIE_LIFETIME'), $this->_getRule('URL_TYPE_SKIN'), + $this->_getRule('DEFAULT_THEME_NAME', 'Mage_Core_Model_Design_Package'), ); diff --git a/dev/tests/static/testsuite/Php/_files/whitelist/common.txt b/dev/tests/static/testsuite/Php/_files/whitelist/common.txt index 333c085de974f64cd77ff9166bcdaea86c1ff38b..124d474a7c2f441ce0f76207825e512878c007e8 100644 --- a/dev/tests/static/testsuite/Php/_files/whitelist/common.txt +++ b/dev/tests/static/testsuite/Php/_files/whitelist/common.txt @@ -23,12 +23,17 @@ app/code/core/Mage/Catalog/Model/Resource/Product/Collection app/code/core/Mage/CatalogInventory/Block/Adminhtml/Form/Field/Stock.php app/code/core/Mage/Core/Block/Abstract.php app/code/core/Mage/Core/data +app/code/core/Mage/Core/Model/Config.php app/code/core/Mage/Centinel/Model/State/Jcb.php +app/code/core/Mage/Core/Controller/Varien/ActionAbstract.php +app/code/core/Mage/Core/Controller/Varien/Action/Factory.php +app/code/core/Mage/Core/Controller/Varien/Router/Factory.php app/code/core/Mage/Core/Model/Config/Module.php app/code/core/Mage/Core/Model/Design.php app/code/core/Mage/Core/Model/Design/Source/Design.php app/code/core/Mage/Core/Model/ShellAbstract.php app/code/core/Mage/Core/Model/Layout.php +app/code/core/Mage/Core/Model/Layout/Factory.php app/code/core/Mage/Core/Model/Layout/Update.php app/code/core/Mage/Core/Model/Design/Fallback app/code/core/Mage/Core/Model/Design/Fallback.php @@ -62,9 +67,10 @@ app/code/core/Mage/Theme app/code/core/Mage/User app/code/core/Mage/Core/Controller/Varien/Action/Forward.php app/code/core/Mage/Core/Controller/Varien/DispatchableInterface.php -app/code/core/Mage/Core/Controller/Varien/Router/Standard.php app/code/core/Mage/Core/Controller/Varien/Router/Abstract.php app/code/core/Mage/Cms/Controller/Router.php +app/code/core/Mage/DesignEditor/Controller/Varien/Router/Standard.php +app/code/core/Mage/DesignEditor/Helper/Data.php app/code/core/Mage/Page/Helper/Robots.php app/code/core/Mage/Webapi dev/shell diff --git a/dev/tests/unit/testsuite/Mage/Adminhtml/DashboardControllerTest.php b/dev/tests/unit/testsuite/Mage/Adminhtml/DashboardControllerTest.php index 173315d0390b3e876bbaceeb47994a59400fab7d..7393743aae3fd7acb98d8cb9b5f3e2bb40ece2de 100644 --- a/dev/tests/unit/testsuite/Mage/Adminhtml/DashboardControllerTest.php +++ b/dev/tests/unit/testsuite/Mage/Adminhtml/DashboardControllerTest.php @@ -26,8 +26,8 @@ class Mage_Adminhtml_DashboardControllerTest extends PHPUnit_Framework_TestCase public function testTunnelAction() { $fixture = uniqid(); - /** @var $request Zend_Controller_Request_Abstract|PHPUnit_Framework_MockObject_MockObject */ - $request = $this->getMockForAbstractClass('Zend_Controller_Request_Abstract'); + /** @var $request Mage_Core_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject */ + $request = $this->getMockForAbstractClass('Mage_Core_Controller_Request_Http'); $request->setParam('ga', urlencode(base64_encode(serialize(array(1))))); $request->setParam('h', $fixture); @@ -55,7 +55,7 @@ class Mage_Adminhtml_DashboardControllerTest extends PHPUnit_Framework_TestCase public function testTunnelAction400() { - $controller = $this->_factory($this->getMockForAbstractClass('Zend_Controller_Request_Abstract')); + $controller = $this->_factory($this->getMockForAbstractClass('Mage_Core_Controller_Request_Http')); $controller->tunnelAction(); $this->assertEquals(400, $controller->getResponse()->getHttpResponseCode()); } @@ -63,8 +63,8 @@ class Mage_Adminhtml_DashboardControllerTest extends PHPUnit_Framework_TestCase public function testTunnelAction503() { $fixture = uniqid(); - /** @var $request Zend_Controller_Request_Abstract|PHPUnit_Framework_MockObject_MockObject */ - $request = $this->getMockForAbstractClass('Zend_Controller_Request_Abstract'); + /** @var $request Mage_Core_Controller_Request_Http|PHPUnit_Framework_MockObject_MockObject */ + $request = $this->getMockForAbstractClass('Mage_Core_Controller_Request_Http'); $request->setParam('ga', urlencode(base64_encode(serialize(array(1))))); $request->setParam('h', $fixture); @@ -97,24 +97,31 @@ class Mage_Adminhtml_DashboardControllerTest extends PHPUnit_Framework_TestCase /** * Create the tested object * - * @param Zend_Controller_Request_Abstract $request - * @param Zend_Controller_Response_Abstract|null $response + * @param Mage_Core_Controller_Request_Http $request + * @param Mage_Core_Controller_Response_Http|null $response * @param Magento_ObjectManager_Zend|null $objectManager * @return Mage_Adminhtml_DashboardController|PHPUnit_Framework_MockObject_MockObject */ protected function _factory($request, $response = null, $objectManager = null) { if (!$response) { - /** @var $response Zend_Controller_Response_Abstract|PHPUnit_Framework_MockObject_MockObject */ - $response = $this->getMockForAbstractClass('Zend_Controller_Response_Abstract'); + /** @var $response Mage_Core_Controller_Response_Http|PHPUnit_Framework_MockObject_MockObject */ + $response = $this->getMockForAbstractClass('Mage_Core_Controller_Response_Http'); $response->headersSentThrowsException = false; } if (!$objectManager) { $objectManager = new Magento_ObjectManager_Zend; } + + $routerFactory = $this->getMock('Mage_Core_Controller_Varien_Router_Factory', array(), array(), '', false); + $rewriteFactory = $this->getMock('Mage_Core_Model_Url_RewriteFactory', array(), array(), '', false); + $varienFront = new Mage_Core_Controller_Varien_Front($routerFactory, $rewriteFactory); + $layoutFactory = $this->getMock('Mage_Core_Model_Layout_Factory', array(), array(), '', false); + return $this->getMock('Mage_Adminhtml_DashboardController', array('__'), array( - $request, $response, $objectManager, - new Mage_Core_Controller_Varien_Front, array('helper' => 1, 'session' => 1, 'translator' => 1) + $request, $response, null, $objectManager, + $varienFront, $layoutFactory, + array('helper' => 1, 'session' => 1, 'translator' => 1) )); } } diff --git a/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/SaveControllerTest.php b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/SaveControllerTest.php index eae1203b11f0039215959e1c841ba33be3525285..669dd2849dbfa7e03ca6e1ae91ae98dd9162ddff 100644 --- a/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/SaveControllerTest.php +++ b/dev/tests/unit/testsuite/Mage/Backend/controllers/Adminhtml/System/Config/SaveControllerTest.php @@ -68,6 +68,11 @@ class Mage_Backend_Adminhtml_System_Config_SaveControllerTest extends PHPUnit_Fr */ protected $_authMock; + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_layoutMock; + /** * @var PHPUnit_Framework_MockObject_MockObject */ @@ -82,7 +87,7 @@ class Mage_Backend_Adminhtml_System_Config_SaveControllerTest extends PHPUnit_Fr { $this->_requestMock = $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false, false); $responseMock = $this->getMock('Mage_Core_Controller_Response_Http', array(), array(), '', false, false); - $objectManagerMock = $this->getMock('Magento_ObjectManager', array(), array(), '', false, false); + $objectManagerMock = $this->getMock('Magento_ObjectManager_Zend', array(), array(), '', false, false); $frontControllerMock = $this->getMock('Mage_Core_Controller_Varien_Front', array(), array(), '', false, false); $authorizationMock = $this->getMock('Mage_Core_Model_Authorization', array(), array(), '', false, false); $this->_configMock = $this->getMock('Mage_Core_Model_Config', array(), array(), '', false, false); @@ -103,6 +108,10 @@ class Mage_Backend_Adminhtml_System_Config_SaveControllerTest extends PHPUnit_Fr array('getUser'), array(), '', false, false ); + $this->_layoutMock = $this->getMock('Mage_Core_Model_Layout_Factory', + array(), array(), '', false, false + ); + $this->_sectionMock = $this->getMock( 'Mage_Backend_Model_Config_Structure_Element_Section', array(), array(), '', false ); @@ -116,6 +125,7 @@ class Mage_Backend_Adminhtml_System_Config_SaveControllerTest extends PHPUnit_Fr $this->_controller = new Mage_Backend_Adminhtml_System_Config_SaveController($this->_requestMock, $responseMock, + null, $objectManagerMock, $frontControllerMock, $authorizationMock, @@ -125,6 +135,7 @@ class Mage_Backend_Adminhtml_System_Config_SaveControllerTest extends PHPUnit_Fr $this->_eventManagerMock, $this->_appMock, $this->_authMock, + $this->_layoutMock, array( 'helper' => $helperMock, 'session' => $this->_sessionMock, diff --git a/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b7986757928c41c58a304570cec7945d19e07512 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/FactoryTest.php @@ -0,0 +1,73 @@ +<?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_Core + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class Mage_Core_Controller_Varien_Action_Factory + */ +class Mage_Core_Controller_Varien_Action_FactoryTest extends PHPUnit_Framework_TestCase +{ + /* + * Test controller class name + */ + const CONTROLLER_NAME = 'TestController'; + + /** + * ObjectManager mock for tests + * + * @var Magento_ObjectManager_Zend + */ + protected $_objectManager; + + /** + * Test class instance + * + * @var Mage_Core_Controller_Varien_Action_Factory + */ + protected $_model; + + protected function setUp() + { + $this->_objectManager = $this->getMock('Magento_ObjectManager_Zend', array('create'), array(), '', false); + } + + public function testConstruct() + { + $this->_model = new Mage_Core_Controller_Varien_Action_Factory($this->_objectManager); + $this->assertAttributeInstanceOf('Magento_ObjectManager', '_objectManager', $this->_model); + } + + public function testCreateController() + { + $this->_objectManager->expects($this->once()) + ->method('create') + ->with(self::CONTROLLER_NAME, array()) + ->will($this->returnValue('TestControllerInstance')); + + $this->_model = new Mage_Core_Controller_Varien_Action_Factory($this->_objectManager); + $this->assertEquals('TestControllerInstance', $this->_model->createController(self::CONTROLLER_NAME)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/ForwardTest.php b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/ForwardTest.php index ef8b81cc3d63cee1a7ec7fdffb12b385fefb5af1..89fa7d279b30c6c4ffb277148fb3db17ba0247ce 100644 --- a/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/ForwardTest.php +++ b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/ForwardTest.php @@ -36,24 +36,30 @@ class Mage_Core_Controller_Varien_Action_ForwardTest extends PHPUnit_Framework_T protected $_object = null; /** - * @var Zend_Controller_Request_Http + * @var Mage_Core_Controller_Request_Http */ protected $_request; /** - * @var Zend_Controller_Response_Http + * @var Mage_Core_Controller_Response_Http */ protected $_response; protected function setUp() { - $this->_request = new Zend_Controller_Request_Http(); - - $this->_response = new Zend_Controller_Response_Http(); + $this->_request = new Mage_Core_Controller_Request_Http(); + $this->_response = new Mage_Core_Controller_Response_Http(); $this->_object = new Mage_Core_Controller_Varien_Action_Forward($this->_request, $this->_response); } + protected function tearDown() + { + unset($this->_object); + unset($this->_request); + unset($this->_response); + } + /** * Test that Mage_Core_Controller_Varien_Action_Forward::dispatch() does not change dispatched flag */ diff --git a/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/RedirectTest.php b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/RedirectTest.php index 006adde4bfc4a6eeacee06f04a211e002f69fba2..11db0db03897a09a9dfdfc15dff8c2d2e96d5fd7 100644 --- a/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/RedirectTest.php +++ b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Action/RedirectTest.php @@ -36,24 +36,30 @@ class Mage_Core_Controller_Varien_Action_RedirectTest extends PHPUnit_Framework_ protected $_object = null; /** - * @var Zend_Controller_Request_Http + * @var Mage_Core_Controller_Request_Http */ protected $_request; /** - * @var Zend_Controller_Response_Http + * @var Mage_Core_Controller_Response_Http */ protected $_response; protected function setUp() { - $this->_request = new Zend_Controller_Request_Http(); - - $this->_response = new Zend_Controller_Response_Http(); + $this->_request = new Mage_Core_Controller_Request_Http(); + $this->_response = new Mage_Core_Controller_Response_Http(); $this->_object = new Mage_Core_Controller_Varien_Action_Redirect($this->_request, $this->_response); } + protected function tearDown() + { + unset($this->_object); + unset($this->_request); + unset($this->_response); + } + public function testDispatch() { $this->_request->setDispatched(true); diff --git a/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/ActionAbstractTest.php b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/ActionAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..15ea687e5da92021eb96a3dd152a9e06fb2baa0f --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/ActionAbstractTest.php @@ -0,0 +1,92 @@ +<?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_Core + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class Mage_Core_Controller_Varien_ActionAbstract + */ +class Mage_Core_Controller_Varien_ActionAbstractTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_Core_Controller_Varien_ActionAbstract + */ + protected $_actionAbstract; + + /** + * @var Mage_Core_Controller_Request_Http + */ + protected $_request; + + /** + * @var Mage_Core_Controller_Response_Http + */ + protected $_response; + + public function setUp() + { + $this->_request = $this->getMock('Mage_Core_Controller_Request_Http', + array('getRequestedRouteName', 'getRequestedControllerName', 'getRequestedActionName'), array(), '', false + ); + $this->_response = $this->getMock('Mage_Core_Controller_Response_Http', array(), array(), '', false); + $this->_actionAbstract = new Mage_Core_Controller_Varien_Action_Forward($this->_request, $this->_response, + 'Area' + ); + } + + public function testConstruct() + { + $this->assertAttributeInstanceOf('Mage_Core_Controller_Request_Http', '_request', $this->_actionAbstract); + $this->assertAttributeInstanceOf('Mage_Core_Controller_Response_Http', '_response', $this->_actionAbstract); + $this->assertAttributeEquals('Area', '_currentArea', $this->_actionAbstract); + } + + public function testGetRequest() + { + $this->assertEquals($this->_request, $this->_actionAbstract->getRequest()); + } + + public function testGetResponse() + { + $this->assertEquals($this->_response, $this->_actionAbstract->getResponse()); + } + + public function testGetFullActionName() + { + $this->_request->expects($this->once()) + ->method('getRequestedRouteName') + ->will($this->returnValue('adminhtml')); + + $this->_request->expects($this->once()) + ->method('getRequestedControllerName') + ->will($this->returnValue('index')); + + $this->_request->expects($this->once()) + ->method('getRequestedActionName') + ->will($this->returnValue('index')); + + $this->assertEquals('adminhtml_index_index', $this->_actionAbstract->getFullActionName()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Router/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Router/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8c4776a4d5cdd82c5a3b60a0add0e480ff20f601 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Controller/Varien/Router/FactoryTest.php @@ -0,0 +1,95 @@ +<?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_Core + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class Mage_Core_Controller_Varien_Router_Factory + */ +class Mage_Core_Controller_Varien_Router_FactoryTest extends PHPUnit_Framework_TestCase +{ + /**#@+ + * Test arguments + */ + const CLASS_NAME = 'TestClass'; + const AREA = 'TestArea'; + const BASE_CONTROLLER = 'TestBaseController'; + /**#@-*/ + + /** + * ObjectManager mock for tests + * + * @var Magento_ObjectManager_Zend + */ + protected $_objectManager; + + /** + * Test class instance + * + * @var Mage_Core_Controller_Varien_Router_Factory + */ + protected $_controller; + + protected function setUp() + { + $this->_objectManager = $this->getMock('Magento_ObjectManager_Zend', array('get'), array(), '', false); + $this->_controller = new Mage_Core_Controller_Varien_Router_Factory($this->_objectManager); + } + + public function testConstruct() + { + $this->assertAttributeInstanceOf('Magento_ObjectManager', '_objectManager', $this->_controller); + } + + public function testCreateRouterNoArguments() + { + $this->_objectManager->expects($this->once()) + ->method('get') + ->with(self::CLASS_NAME) + ->will($this->returnValue('TestRouterInstance')); + + $this->assertEquals('TestRouterInstance', $this->_controller->createRouter(self::CLASS_NAME)); + } + + public function testCreateRouterWithArguments() + { + $arguments = array( + 'areaCode' => self::AREA, + 'baseController' => self::BASE_CONTROLLER, + ); + + $routerInfo = array( + 'area' => self::AREA, + 'base_controller' => self::BASE_CONTROLLER, + ); + + $this->_objectManager->expects($this->once()) + ->method('get') + ->with(self::CLASS_NAME, $arguments) + ->will($this->returnValue('TestRouterInstance')); + + $this->assertEquals('TestRouterInstance', $this->_controller->createRouter(self::CLASS_NAME, $routerInfo)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/AppTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/AppTest.php new file mode 100644 index 0000000000000000000000000000000000000000..23987d751a9c8f2d8b165d865b72df0104727667 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Model/AppTest.php @@ -0,0 +1,64 @@ +<?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 unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for Mage_Core_Model_App + */ +class Mage_Core_Model_AppTest extends PHPUnit_Framework_TestCase +{ + /* + * Test layout class instance + */ + const LAYOUT_INSTANCE = 'TestLayoutInstance'; + + /** + * @var Mage_Core_Model_App + */ + protected $_model; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + public function setUp() + { + $frontController = $this->getMock('Mage_Core_Controller_Varien_Front', array(), array(), '', false); + $this->_objectManager = $this->getMock('Magento_ObjectManager_Zend', array('get'), array(), '', false); + $this->_model = new Mage_Core_Model_App($frontController, $this->_objectManager); + } + + public function testGetLayout() + { + $this->_objectManager->expects($this->once()) + ->method('get') + ->with('Mage_Core_Model_Layout') + ->will($this->returnValue(self::LAYOUT_INSTANCE)); + + $this->assertEquals(self::LAYOUT_INSTANCE, $this->_model->getLayout()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/Layout/FactoryTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/Layout/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3ad5078a461fee553cf55e6a2c82c95af5a92e5e --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Model/Layout/FactoryTest.php @@ -0,0 +1,172 @@ +<?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 unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for Mage_Core_Model_Layout_Factory + */ +class Mage_Core_Model_Layout_FactoryTest extends PHPUnit_Framework_TestCase +{ + /* + * Test class name + */ + const CLASS_NAME = 'Mage_Core_Model_Layout'; + + /** + * Test arguments + * + * @var array + */ + protected $_arguments = array(); + + /** + * ObjectManager mock for tests + * + * @var Magento_ObjectManager + */ + protected $_objectManager; + + /** + * Test class instance + * + * @var Mage_Core_Model_Layout_Factory + */ + protected $_model; + + protected function setUp() + { + $this->_objectManager = $this->getMock('Magento_ObjectManager_Zend', + array('hasSharedInstance', 'get', 'removeSharedInstance', 'create', 'addSharedInstance'), + array(), '', false); + $this->_model = new Mage_Core_Model_Layout_Factory($this->_objectManager); + } + + public function testConstruct() + { + $this->assertAttributeInstanceOf('Magento_ObjectManager', '_objectManager', $this->_model); + } + + public function testCreateLayoutRemoveSharedInstance() + { + $this->_arguments = array('area' => 'ArgumentArea'); + + $this->_objectManager->expects($this->once()) + ->method('hasSharedInstance') + ->with(self::CLASS_NAME) + ->will($this->returnValue(true)); + + $modelLayout = $this->getMock(self::CLASS_NAME, array('getArea'), array(), '', false); + + $this->_objectManager->expects($this->at(1)) + ->method('get') + ->with(self::CLASS_NAME) + ->will($this->returnValue($modelLayout)); + + $modelLayout->expects($this->any()) + ->method('getArea') + ->will($this->returnValue('TestArea')); + + $this->_objectManager->expects($this->once()) + ->method('removeSharedInstance') + ->with(self::CLASS_NAME); + + $newModelLayout = $this->getMock(self::CLASS_NAME, array(), array(), '', false); + + $this->_objectManager->expects($this->once()) + ->method('create') + ->with(self::CLASS_NAME, $this->_arguments, false) + ->will($this->returnValue($newModelLayout)); + + $this->_objectManager->expects($this->once()) + ->method('addSharedInstance') + ->with($newModelLayout, self::CLASS_NAME); + + $this->_objectManager->expects($this->at(5)) + ->method('get') + ->with(self::CLASS_NAME) + ->will($this->returnValue($newModelLayout)); + + $this->assertEquals($newModelLayout, $this->_model->createLayout($this->_arguments)); + } + + public function testCreateLayoutNew() + { + $modelLayout = $this->getMock(self::CLASS_NAME, array(), array(), '', false); + + $this->_objectManager->expects($this->once()) + ->method('create') + ->with(self::CLASS_NAME, array(), false) + ->will($this->returnValue($modelLayout)); + + $this->_objectManager->expects($this->once()) + ->method('addSharedInstance') + ->with($modelLayout, self::CLASS_NAME); + + $this->_objectManager->expects($this->at(2)) + ->method('get') + ->with(self::CLASS_NAME) + ->will($this->returnValue($modelLayout)); + + $this->assertEquals($modelLayout, $this->_model->createLayout()); + } + + public function testCreateLayoutGetSharedInstance() + { + $this->_arguments = array('area' => 'TestArea'); + + $this->_objectManager->expects($this->once()) + ->method('hasSharedInstance') + ->with(self::CLASS_NAME) + ->will($this->returnValue(true)); + + $modelLayout = $this->getMock(self::CLASS_NAME, array('getArea'), array(), '', false); + + $this->_objectManager->expects($this->at(1)) + ->method('get') + ->with(self::CLASS_NAME) + ->will($this->returnValue($modelLayout)); + + $modelLayout->expects($this->any()) + ->method('getArea') + ->will($this->returnValue('TestArea')); + + $this->_objectManager->expects($this->never()) + ->method('removeSharedInstance'); + + $this->_objectManager->expects($this->never()) + ->method('create'); + + $this->_objectManager->expects($this->never()) + ->method('addSharedInstance'); + + $this->_objectManager->expects($this->at(2)) + ->method('get') + ->with(self::CLASS_NAME) + ->will($this->returnValue($modelLayout)); + + $this->assertEquals($modelLayout, $this->_model->createLayout($this->_arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/Theme/ServiceTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/Theme/ServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5bbcff3f59d321e80b7aef720a757dbdbf99d212 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Model/Theme/ServiceTest.php @@ -0,0 +1,218 @@ +<?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 unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test theme service model + */ +class Mage_Core_Model_Theme_ServiceTest extends PHPUnit_Framework_TestCase +{ + /** + * @covers Mage_Core_Model_Theme_Service::isPresentCustomizedThemes + * @dataProvider isIsCustomizationsExistDataProvider + * @param array $availableIsVirtual + * @param bool $expectedResult + */ + public function testIsCustomizationsExist($availableIsVirtual, $expectedResult) + { + $themeCollectionMock = array(); + foreach ($availableIsVirtual as $isVirtual) { + /** @var $themeItemMock Mage_Core_Model_Theme */ + $themeItemMock = $this->getMock('Mage_Core_Model_Theme', array('isVirtual'), array(), '', false); + $themeItemMock->expects($this->any()) + ->method('isVirtual') + ->will($this->returnValue($isVirtual)); + $themeCollectionMock[] = $themeItemMock; + } + + /** @var $themeMock Mage_Core_Model_Theme */ + $themeMock = $this->getMock('Mage_Core_Model_Theme', array('getCollection'), array(), '', false); + $themeMock->expects($this->once()) + ->method('getCollection') + ->will($this->returnValue($themeCollectionMock)); + + $themeFactoryMock = $this->getMock('Mage_Core_Model_Theme_Factory', array('create'), array(), '', false); + $themeFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($themeMock)); + + $themeService = new Mage_Core_Model_Theme_Service($themeFactoryMock, + $this->getMock('Mage_Core_Model_Design_Package', array(), array(), '', false), + $this->getMock('Mage_Core_Model_App', array(), array(), '', false), + $this->getMock('Mage_Core_Helper_Data', array(), array(), '', false) + ); + $this->assertEquals($expectedResult, $themeService->isCustomizationsExist()); + } + + /** + * @return array + */ + public function isIsCustomizationsExistDataProvider() + { + return array( + array(array(false, false, false), false), + array(array(false, true, false), true) + ); + } + + /** + * @covers Mage_Core_Model_Theme_Service::assignThemeToStores + * @expectedException UnexpectedValueException + * @expectedExceptionMessage Theme is not recognized. Requested id: -1 + */ + public function testAssignThemeToStoresWrongThemeId() + { + /** @var $themeMock Mage_Core_Model_Theme */ + $themeMock = $this->getMock('Mage_Core_Model_Theme', array('load', 'getId'), array(), '', false); + $themeMock->expects($this->once()) + ->method('load') + ->with($this->equalTo(-1)) + ->will($this->returnValue($themeMock)); + + $themeMock->expects($this->once()) + ->method('getId') + ->will($this->returnValue(false)); + $themeFactoryMock = $this->getMock('Mage_Core_Model_Theme_Factory', array('create'), array(), '', false); + $themeFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($themeMock)); + + $themeService = new Mage_Core_Model_Theme_Service($themeFactoryMock, + $this->getMock('Mage_Core_Model_Design_Package', array(), array(), '', false), + $this->getMock('Mage_Core_Model_App', array(), array(), '', false), + $this->getMock('Mage_Core_Helper_Data', array(), array(), '', false) + ); + $themeService->assignThemeToStores(-1, array()); + } + + /** + * @covers Mage_Core_Model_Theme_Service::getAssignedThemeCustomizations + * @covers Mage_Core_Model_Theme_Service::getUnassignedThemeCustomizations + * @dataProvider getAssignedUnassignedThemesDataProvider + * @param array $stores + * @param array $themes + * @param array $expAssignedThemes + * @param array $expUnassignedThemes + * + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function testGetAssignedAndUnassignedThemes($stores, $themes, $expAssignedThemes, $expUnassignedThemes) + { + $index = 0; + /* Mock assigned themeId to each store */ + $storeConfigMock = $this->getMock('Mage_Core_Model_Store', array('getId'), array(), '', false); + $storeMockCollection = array(); + foreach ($stores as $thisId) { + $storeConfigMock->expects($this->at($index++)) + ->method('getId') + ->will($this->returnValue($thisId)); + + $storeMockCollection[] = $storeConfigMock; + } + + /* Mock list existing stores */ + $appMock = $this->getMock('Mage_Core_Model_App', array('getStores'), array(), '', false); + $appMock->expects($this->once()) + ->method('getStores') + ->will($this->returnValue($storeMockCollection)); + + /* Mock list customized themes */ + $themesMock = array(); + foreach ($themes as $themeId) { + /** @var $theme Mage_Core_Model_Theme */ + $theme = $this->getMock('Mage_Core_Model_Theme', array('getId'), array(), '', false); + $theme->expects($this->any())->method('getId')->will($this->returnValue($themeId)); + $themesMock[] = $theme; + } + + $designMock = $this->getMock('Mage_Core_Model_Design_Package', array('getConfigurationDesignTheme'), + array(), '', false); + $designMock->expects($this->any()) + ->method('getConfigurationDesignTheme') + ->with($this->anything(), $this->arrayHasKey('store')) + ->will($this->returnCallback( + function($area, $params) { + return $params['store']->getId(); + } + )); + $helperMock = $this->getMock('Mage_Core_Helper_Data', array(), array(), '', false); + + $themeFactoryMock = $this->getMock('Mage_Core_Model_Theme_Factory', array('create'), array(), '', false); + $themeFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($this->getMock('Mage_Core_Model_Theme', array(), array(), '', false))); + + /** @var $themeService Mage_Core_Model_Theme_Service */ + $themeService = $this->getMock('Mage_Core_Model_Theme_Service', array('_getThemeCustomizations'), + array($themeFactoryMock, $designMock, $appMock, $helperMock)); + $themeService->expects($this->once()) + ->method('_getThemeCustomizations') + ->will($this->returnValue($themesMock)); + + $assignedThemes = $themeService->getAssignedThemeCustomizations(); + $unassignedThemes = $themeService->getUnassignedThemeCustomizations(); + + $assignedData = array(); + foreach ($assignedThemes as $theme) { + $assignedData[$theme->getId()] = $theme->getAssignedStores(); + } + $this->assertEquals(array_keys($expAssignedThemes), array_keys($assignedData)); + + + $unassignedData = array(); + foreach ($unassignedThemes as $theme) { + $unassignedData[] = $theme->getId(); + } + $this->assertEquals($expUnassignedThemes, $unassignedData); + } + + /** + * @return array() + */ + public function getAssignedUnassignedThemesDataProvider() + { + return array( + array( + 'stores' => array( + 'store_1' => 1, + 'store_2' => 4, + 'store_3' => 3, + 'store_4' => 8, + 'store_5' => 3, + 'store_6' => 10, + ), + 'themes' => array(1, 2, 3, 4, 5, 6, 7, 8, 9), + 'expectedAssignedThemes' => array( + 1 => array('store_1'), + 3 => array('store_3', 'store_5'), + 4 => array('store_2'), + 8 => array('store_4'), + ), + 'expectedUnassignedThemes' => array(2, 5, 6, 7, 9) + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/ThemeTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/ThemeTest.php index bbcc007fca9fcf5702531d34ba323e8635806065..bb1a9b31ea85fede71d562caa84a461950318094 100644 --- a/dev/tests/unit/testsuite/Mage/Core/Model/ThemeTest.php +++ b/dev/tests/unit/testsuite/Mage/Core/Model/ThemeTest.php @@ -40,10 +40,22 @@ class Mage_Core_Model_ThemeTest extends PHPUnit_Framework_TestCase protected function _getThemeModel($designDir, $targetPath) { Mage::getConfig()->getOptions()->setData('design_dir', $designDir); + $objectManager = Mage::getObjectManager(); + /** @var $themeCollection Mage_Core_Model_Resource_Theme_Collection */ + $themeCollection = $this->getMock('Mage_Core_Model_Resource_Theme_Collection', array(), array(), '', false); $objectManagerHelper = new Magento_Test_Helper_ObjectManager($this); + $arguments = $objectManagerHelper->getConstructArguments( + Magento_Test_Helper_ObjectManager::MODEL_ENTITY, 'Mage_Core_Model_Theme', + array( + 'objectManager' => $objectManager, + 'helper' => $objectManager->get('Mage_Core_Helper_Data'), + 'resource' => $objectManager->get('Mage_Core_Model_Resource_Theme'), + 'resourceCollection' => $themeCollection, + 'themeFactory' => $objectManager->get('Mage_Core_Model_Theme_Factory'), + ) + ); /** @var $themeMock Mage_Core_Model_Theme */ - $arguments = $objectManagerHelper->getConstructArguments(Magento_Test_Helper_ObjectManager::MODEL_ENTITY); $themeMock = $this->getMock('Mage_Core_Model_Theme', array('_init'), $arguments, '', true); /** @var $collectionMock Mage_Core_Model_Theme_Collection|PHPUnit_Framework_MockObject_MockObject */ diff --git a/dev/tests/unit/testsuite/Mage/Core/Model/Url/RewriteFactoryTest.php b/dev/tests/unit/testsuite/Mage/Core/Model/Url/RewriteFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5bc4531b459a249bfe2a2abe963297b75a6ba907 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/Core/Model/Url/RewriteFactoryTest.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 Magento + * @package Mage_Core + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_Core_Model_Url_RewriteFactoryTest 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_Core_Model_Url_Rewrite'; + + /** + * @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_Core_Model_Url_RewriteFactory($objectManagerMock); + $this->assertEquals(self::CREATE_RESULT, $factory->createFromArray($this->_arguments)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/ContainerTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/ContainerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f6422bbd16148a6d5d5dd5edb54152f3a24f88ec --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/ContainerTest.php @@ -0,0 +1,128 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Block_Adminhtml_Editor_ContainerTest extends PHPUnit_Framework_TestCase +{ + const FRAME_URL = 'controller/action'; + + /** + * Object manager helper + * + * @var Magento_Test_Helper_ObjectManager + */ + protected $_helper; + + protected function setUp() + { + $this->_helper = new Magento_Test_Helper_ObjectManager($this); + } + + protected function tearDown() + { + unset($this->_helper); + } + + /** + * Retrieve list of arguments for block that will be tested + * + * @param array $params + * @return array + */ + protected function _getBlockArguments(array $params) + { + $helper = $this->getMock('Mage_DesignEditor_Helper_Data', array('__'), array(), '', false); + $helper->expects($this->once()) + ->method('__') + ->with($params['expectedTranslation']) + ->will($this->returnValue($params['expectedTranslation'])); + + $helperFactory = $this->getMock('Mage_Core_Model_Factory_Helper', array('get')); + $helperFactory->expects($this->once()) + ->method('get') + ->will($this->returnValue($helper)); + + return array( + 'urlBuilder' => $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false), + 'helperFactory' => $helperFactory + ); + } + + public function testGetHeaderText() + { + $arguments = $this->_getBlockArguments(array('expectedTranslation' => 'Visual Design Editor')); + /** @var $block Mage_DesignEditor_Block_Adminhtml_Editor_Container */ + $block = $this->_helper->getBlock('Mage_DesignEditor_Block_Adminhtml_Editor_Container', $arguments); + $block->getHeaderText(); + } + + /** + * @covers Mage_DesignEditor_Block_Adminhtml_Editor_Container::setFrameUrl + * @covers Mage_DesignEditor_Block_Adminhtml_Editor_Container::getFrameUrl + */ + public function testGetSetFrameUrl() + { + $arguments = array( + 'urlBuilder' => $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false), + ); + + /** @var $block Mage_DesignEditor_Block_Adminhtml_Editor_Container */ + $block = $this->_helper->getBlock('Mage_DesignEditor_Block_Adminhtml_Editor_Container', $arguments); + $block->setFrameUrl(self::FRAME_URL); + $this->assertAttributeEquals(self::FRAME_URL, '_frameUrl', $block); + $this->assertEquals(self::FRAME_URL, $block->getFrameUrl()); + } + + /** + * @covers Mage_DesignEditor_Block_Adminhtml_Editor_Container::_prepareLayout + */ + public function testPrepareLayout() + { + $buttonTitle = 'Back'; + $eventManager = $this->getMock('Mage_Core_Model_Event_Manager', array('dispatch')); + $arguments = $this->_getBlockArguments(array('expectedTranslation' => $buttonTitle)); + $arguments['eventManager'] = $eventManager; + + /** @var $block Mage_DesignEditor_Block_Adminhtml_Editor_Container */ + $block = $this->_helper->getBlock('Mage_DesignEditor_Block_Adminhtml_Editor_Container', $arguments); + + $layout = $this->getMock('Mage_Core_Model_Layout', array(), array(), '', false); + $block->setLayout($layout); + + $expectedButtonData = array( + 'back_button' => array( + 'label' => $buttonTitle, + 'onclick' => 'setLocation(\'\')', + 'class' => 'back', + 'id' => 'back_button', + 'region' => 'header', + 'sort_order' => 10 + ) + ); + + $this->assertAttributeContains($expectedButtonData, '_buttons', $block); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/BlockAbstractTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/BlockAbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..167bb0a311e74888e7ac2a13111e40865701d05b --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/BlockAbstractTest.php @@ -0,0 +1,73 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstractTest extends PHPUnit_Framework_TestCase +{ + /** + * VDE toolbar buttons block + * + * @var Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstract + */ + protected $_block; + + protected function setUp() + { + $this->_block = $this->getMockForAbstractClass('Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_BlockAbstract', + array(), '', false + ); + } + + public function testGetMode() + { + $this->_block->setMode(Mage_DesignEditor_Model_State::MODE_DESIGN); + $this->assertEquals(Mage_DesignEditor_Model_State::MODE_DESIGN, $this->_block->getMode()); + } + + public function testSetMode() + { + $this->_block->setMode(Mage_DesignEditor_Model_State::MODE_NAVIGATION); + $this->assertAttributeEquals(Mage_DesignEditor_Model_State::MODE_NAVIGATION, '_mode', $this->_block); + } + + public function testIsDesignMode() + { + $this->_block->setMode(Mage_DesignEditor_Model_State::MODE_DESIGN); + $this->assertTrue($this->_block->isDesignMode()); + + $this->_block->setMode(Mage_DesignEditor_Model_State::MODE_NAVIGATION); + $this->assertFalse($this->_block->isDesignMode()); + } + + public function testIsNavigationMode() + { + $this->_block->setMode(Mage_DesignEditor_Model_State::MODE_NAVIGATION); + $this->assertTrue($this->_block->isNavigationMode()); + + $this->_block->setMode(Mage_DesignEditor_Model_State::MODE_DESIGN); + $this->assertFalse($this->_block->isNavigationMode()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/ButtonsTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/ButtonsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c4086850632b3cb33653ddc338f7813630c0cc5f --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/ButtonsTest.php @@ -0,0 +1,108 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_ButtonsTest extends PHPUnit_Framework_TestCase +{ + /** + * VDE toolbar buttons block + * + * @var Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_Buttons + */ + protected $_block; + + /** + * @var Mage_Backend_Model_Url + */ + protected $_urlBuilder; + + protected function setUp() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + + $this->_urlBuilder = $this->getMock('Mage_Backend_Model_Url', array('getUrl'), array(), '', false); + + $arguments = array( + 'urlBuilder' => $this->_urlBuilder + ); + + $this->_block = $helper->getBlock('Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_Buttons', $arguments); + } + + public function testGetThemeId() + { + $this->_block->setThemeId(1); + $this->assertEquals(1, $this->_block->getThemeId()); + } + + public function testSetThemeId() + { + $this->_block->setThemeId(2); + $this->assertAttributeEquals(2, '_themeId', $this->_block); + } + + public function testGetViewLayoutUrl() + { + $this->_urlBuilder->expects($this->once()) + ->method('getUrl') + ->will($this->returnArgument(0)); + $this->assertEquals('*/*/getLayoutUpdate', $this->_block->getViewLayoutUrl()); + } + + public function testGetBackUrl() + { + $this->_urlBuilder->expects($this->once()) + ->method('getUrl') + ->will($this->returnArgument(0)); + $this->assertEquals('*/*/', $this->_block->getBackUrl()); + } + + public function testGetNavigationModeUrl() + { + $this->_block->setThemeId(2); + $mode = Mage_DesignEditor_Model_State::MODE_NAVIGATION; + $this->_urlBuilder->expects($this->once()) + ->method('getUrl') + ->with('*/*/launch', array('mode' => $mode, 'theme_id' => 2)) + ->will($this->returnValue("*/*/launch/mode/{$mode}/theme_id/2/")); + + $this->assertEquals("*/*/launch/mode/{$mode}/theme_id/2/", + $this->_block->getNavigationModeUrl() + ); + } + + public function testGetDesignModeUrl() + { + $this->_block->setThemeId(3); + $mode = Mage_DesignEditor_Model_State::MODE_DESIGN; + $this->_urlBuilder->expects($this->once()) + ->method('getUrl') + ->with('*/*/launch', array('mode' => $mode, 'theme_id' => 3)) + ->will($this->returnValue("*/*/launch/mode/{$mode}/theme_id/3/")); + + $this->assertEquals("*/*/launch/mode/{$mode}/theme_id/3/", $this->_block->getDesignModeUrl()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/HandlesHierarchyTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/HandlesHierarchyTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8a719e704f50cef65c6ae0800b1b5790933a4047 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Editor/Toolbar/HandlesHierarchyTest.php @@ -0,0 +1,223 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy + */ +class Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchyTest extends PHPUnit_Framework_TestCase +{ + + /**#@+ + * Test handle + */ + const HANDLE_NAME = 'test_handle_name'; + const HANDLE_LABEL = 'test_handle_label'; + /**#@-*/ + + /** + * @var Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy + */ + protected $_model; + + /** + * @var string + */ + protected $_modelName = 'Mage_DesignEditor_Block_Adminhtml_Editor_Toolbar_HandlesHierarchy'; + + protected function setUp() + { + $objectManagerHelper = new Magento_Test_Helper_ObjectManager($this); + $helperData = $this->getMock('Mage_Core_Helper_Data', array('escapeHtml'), array(), '', false); + $helperData->expects($this->any()) + ->method('escapeHtml') + ->will($this->returnArgument(0)); + + $layoutMerge = $this->getMock('Mage_Core_Model_Layout_Merge', array('getPageHandleLabel'), array(), '', false); + $layoutMerge->expects($this->any()) + ->method('getPageHandleLabel') + ->with($this::HANDLE_NAME) + ->will($this->returnValue($this::HANDLE_LABEL)); + + $layout = $this->getMock('Mage_Core_Model_Layout', array('helper', 'getUpdate'), array(), '', false); + $layout->expects($this->any()) + ->method('helper') + ->with('Mage_Core_Helper_Data') + ->will($this->returnValue($helperData)); + $layout->expects($this->any()) + ->method('getUpdate') + ->will($this->returnValue($layoutMerge)); + + $vdeUrlBuilder = $this->getMock('Mage_DesignEditor_Model_Url_Handle', array('getUrl'), array(), '', false); + $vdeUrlBuilder->expects($this->any()) + ->method('getUrl') + ->will($this->returnCallback( + function($url, $parameter) { + $key = key($parameter); + return $url . '/' . $key . '/' . $parameter[$key]; + } + )); + $data = array( + 'urlBuilder' => $this->getMock('Mage_Backend_Model_Url', array(), array(), '', false), + 'layout' => $layout, + 'vdeUrlBuilder' => $vdeUrlBuilder + ); + + $this->_model = $objectManagerHelper->getBlock($this->_modelName, $data); + } + + protected function tearDown() + { + unset($this->_model); + } + + /** + * @dataProvider renderHierarchyData + * @param array $hierarchy + * @param string $expectedResult + */ + public function testRenderHierarchy($hierarchy, $expectedResult) + { + $this->_model->setHierarchy($hierarchy); + $this->assertEquals($expectedResult, $this->_model->renderHierarchy()); + } + + public function testSetSelectedHandle() + { + $this->_model->setSelectedHandle($this::HANDLE_NAME); + $this->assertAttributeEquals($this::HANDLE_NAME, '_selectedHandle', $this->_model); + } + + /** + * @dataProvider getSelectedHandleData + * @param string $selectedHandle + * @param array $hierarchy + * @param string $expectedResult + */ + public function testGetSelectedHandle($selectedHandle, $hierarchy, $expectedResult) + { + if ($selectedHandle) { + $this->_model->setSelectedHandle($this::HANDLE_NAME); + } + if (!is_null($hierarchy)) { + $this->_model->setHierarchy($hierarchy); + } + + $this->assertEquals($expectedResult, $this->_model->getSelectedHandle()); + } + + public function testGetSelectedHandleLabel() + { + $this->_model->setSelectedHandle($this::HANDLE_NAME); + $this->assertEquals(self::HANDLE_LABEL, $this->_model->getSelectedHandleLabel()); + } + + /** + * Data provider for getSelectedHandle method + * + * @return array + */ + public function getSelectedHandleData() + { + return array( + 'already selected' => array( + 'selected handle' => $this::HANDLE_NAME, + 'hierarchy' => null, + 'expected result' => $this::HANDLE_NAME + ), + 'first from hierarchy' => array( + 'selected handle' => null, + 'hierarchy' => array( + 'first_page_test' => array( + 'name' => 'first_page_name', + ), + 'second_page_test' => array( + 'name' => 'second_page_name', + ), + ), + 'expected result' => 'first_page_name' + ), + 'empty hierarchy' => array( + 'selected handle' => null, + 'hierarchy' => array(), + 'expected result' => null + ) + ); + } + + /** + * Data provider for renderHierarchy method + * + * @return array + */ + public function renderHierarchyData() + { + $expectedResults = array( + 'empty hierarchy' => '', + 'simple hierarchy' => '<ul><li rel="page_test"><a href="design/page/type/handle/page_test">' + . 'page_label</a></li></ul>', + 'nested hierarchy' => '<ul><li rel="page_test"><a href="design/page/type/handle/page_test">page_label' + . '</a><ul><li rel="nested_page_test"><a href="design/page/type/handle/nested_page_test">' + . 'nested_page_label</a></li></ul></li></ul>' + ); + + return array( + 'empty hierarchy' => array( + 'hierarchy' => array(), + 'expected result' => $expectedResults['empty hierarchy'] + ), + 'simple hierarchy' => array( + 'hierarchy' => array( + 'page_test' => array( + 'name' => 'page_name', + 'label' => 'page_label', + 'type' => 'page_type', + 'children' => array() + ) + ), + 'expected result' => $expectedResults['simple hierarchy'] + ), + 'nested hierarchy' => array( + 'hierarchy' => array( + 'page_test' => array( + 'name' => 'page_name', + 'label' => 'page_label', + 'type' => 'page_type', + 'children' => array( + 'nested_page_test' => array( + 'name' => 'nested_page_name', + 'label' => 'nested_page_label', + 'type' => 'nested_page_type', + 'children' => array() + ) + ) + ) + ), + 'expected result' => $expectedResults['nested hierarchy'] + ), + ); + } + +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/AbstractTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/AbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8cc45832547e38fec9b0d82ab9c2a048462660a4 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/Theme/Selector/List/AbstractTest.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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_AbstractTest + extends PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getSampleCollection + */ + public function testGetListItems($collection) + { + /** @var $listAbstractBlock Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract */ + $listAbstractBlock = $this->getMockForAbstractClass( + 'Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract', array(), '', false, false, true, + array('getChildBlock') + ); + + $themeMock = $this->getMock('Mage_DesignEditor_Block_Adminhtml_Theme', array(), array(), '', false); + + $listAbstractBlock->setCollection($collection); + + $listAbstractBlock->expects($this->atLeastOnce()) + ->method('getChildBlock') + ->will($this->returnValue($themeMock)); + + $this->assertEquals(2, count($listAbstractBlock->getListItems())); + } + + /** + * @return array + */ + public function getSampleCollection() + { + return array(array(array( + array('first_item'), + array('second_item') + ))); + } + + public function testAddAssignButtonHtml() + { + /** @var $listAbstractBlock Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract */ + $listAbstractBlock = $this->getMockForAbstractClass( + 'Mage_DesignEditor_Block_Adminhtml_Theme_Selector_List_Abstract', array(), '', false, false, true, + array('getChildBlock', 'getLayout', '__') + ); + /** @var $themeMock Mage_Core_Model_Theme */ + $themeMock = $this->getMock('Mage_Core_Model_Theme', array(), array(), '', false); + /** @var $themeBlockMock Mage_DesignEditor_Block_Adminhtml_Theme */ + $themeBlockMock = $this->getMock( + 'Mage_DesignEditor_Block_Adminhtml_Theme', array('getTheme'), array(), '', false + ); + /** @var $layoutMock Mage_Core_Model_Layout */ + $layoutMock = $this->getMock('Mage_Core_Model_Layout', array('createBlock'), array(), '', false); + /** @var $buttonMock Mage_Backend_Block_Widget_Button */ + $buttonMock = $this->getMock('Mage_Backend_Block_Widget_Button', array(), array(), '', false); + + $layoutMock->expects($this->once()) + ->method('createBlock') + ->will($this->returnValue($buttonMock)); + + $themeBlockMock->expects($this->once()) + ->method('getTheme') + ->will($this->returnValue($themeMock)); + + $listAbstractBlock->expects($this->once()) + ->method('getLayout') + ->will($this->returnValue($layoutMock)); + + $themeMock->expects($this->once()) + ->method('getId') + ->will($this->returnValue(1)); + + $method = new ReflectionMethod($listAbstractBlock, '_addAssignButtonHtml'); + $method->setAccessible(true); + $method->invoke($listAbstractBlock, $themeBlockMock); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/ThemeTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/ThemeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b148cfc1967f69a5b5ffe501e9fefb19d39e4bd5 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Adminhtml/ThemeTest.php @@ -0,0 +1,49 @@ +<?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_DesignEditor + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Block_Adminhtml_ThemeTest extends PHPUnit_Framework_TestCase +{ + /** + * @cover Mage_DesignEditor_Block_Adminhtml_Theme::addButton + * @cover Mage_DesignEditor_Block_Adminhtml_Theme::clearButtons + * @cover Mage_DesignEditor_Block_Adminhtml_Theme::getButtonsHtml + */ + public function testButtons() + { + $themeMock = $this->getMock('Mage_DesignEditor_Block_Adminhtml_Theme', null, array(), '', false); + $buttonMock = $this->getMock('StdClass', array('toHtml')); + + $buttonMock->expects($this->once()) + ->method('toHtml') + ->will($this->returnValue('Block html data')); + + $themeMock->addButton($buttonMock); + $this->assertEquals('Block html data', $themeMock->getButtonsHtml()); + + $themeMock->clearButtons(); + $this->assertEquals('', $themeMock->getButtonsHtml()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Page/Html/Head/VdeTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Page/Html/Head/VdeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7e89a2e8f879eb5852c5cd80fdde7d12d96d08cb --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Page/Html/Head/VdeTest.php @@ -0,0 +1,38 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Block_Page_Html_Head_VdeTest extends PHPUnit_Framework_TestCase +{ + public function testGetTemplate() + { + $helper = new Magento_Test_Helper_ObjectManager($this); + /** @var $block Mage_DesignEditor_Block_Page_Html_Head_Vde */ + $block = $helper->getBlock('Mage_DesignEditor_Block_Page_Html_Head_Vde'); + + $this->assertNull($block->getTemplate()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Page/Html/HeadTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Page/Html/HeadTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b6aba60d751d7b4a455feb2b0c6598b348d0f40f --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Block/Page/Html/HeadTest.php @@ -0,0 +1,112 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Block_Page_Html_HeadTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_DesignEditor_Block_Page_Html_Head + */ + protected $_model; + + protected function tearDown() + { + unset($this->_model); + } + + /** + * @param array $sourceItems + * @param array $vdeItems + * @param array $expectedItems + * + * @dataProvider getCssJsHtmlDataProvider + */ + public function testGetCssJsHtml(array $sourceItems, array $vdeItems = null, array $expectedItems = null) + { + $helper = new Magento_Test_Helper_ObjectManager($this); + if ($vdeItems !== null) { + /** @var $vdeHead Mage_DesignEditor_Block_Page_Html_Head_Vde */ + $vdeHead = $helper->getBlock('Mage_DesignEditor_Block_Page_Html_Head_Vde'); + $vdeHead->setData('items', $vdeItems); + + $layoutMock = $this->getMock('Mage_Core_Model_Layout', array('getBlock'), array(), '', false); + $layoutMock->expects($this->once()) + ->method('getBlock') + ->will($this->returnValue($vdeHead)); + + $this->_model = $helper->getBlock( + 'Mage_DesignEditor_Block_Page_Html_Head', + array('layout' => $layoutMock) + ); + } else { + $this->_model = $helper->getBlock('Mage_DesignEditor_Block_Page_Html_Head'); + } + $this->_model->setData('items', $sourceItems); + + $this->assertInternalType('string', $this->_model->getCssJsHtml()); + $this->assertEquals($expectedItems, $this->_model->getData('items')); + } + + /** + * Data provider for testGetCssJsHtml + * + * @return array + */ + public function getCssJsHtmlDataProvider() + { + $jsSourceItems = array( + 'js/first' => 'js first', + 'js/second' => 'js second' + ); + $cssSourceItems = array( + 'css/first' => 'css first' + ); + $sourceItems = array_merge($jsSourceItems, $cssSourceItems); + + $vdeItems = array( + 'js/first' => 'js first vde', + 'css/second' => 'css second', + ); + + return array( + 'no block' => array( + '$sourceItems' => $sourceItems, + '$vdeItems' => null, + '$expectedItems' => $sourceItems, + ), + 'no vde data' => array( + '$sourceItems' => $sourceItems, + '$vdeItems' => array(), + '$expectedItems' => $cssSourceItems, + ), + 'item merge' => array( + '$sourceItems' => $sourceItems, + '$vdeItems' => $vdeItems, + '$expectedItems' => array_merge($cssSourceItems, $vdeItems), + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Controller/Varien/Router/StandardTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Controller/Varien/Router/StandardTest.php new file mode 100644 index 0000000000000000000000000000000000000000..26f4b6563ce6d625383f24065121f7cf7b779fb9 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Controller/Varien/Router/StandardTest.php @@ -0,0 +1,256 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Controller_Varien_Router_StandardTest extends PHPUnit_Framework_TestCase +{ + /** + * Test area code + */ + const AREA_CODE = 'frontend'; + + /** + * Test VDE front name prefix + */ + const VDE_FRONT_NAME = 'test_front_name'; + + /** + * Test VDE configuration data + */ + const VDE_CONFIGURATION_DATA = 'vde_config_data'; + + /**#@+ + * Test path and host + */ + const TEST_PATH = '/customer/account'; + const TEST_HOST = 'http://test.domain'; + /**#@-*/ + + /** + * @var Mage_DesignEditor_Controller_Varien_Router_Standard + */ + protected $_model; + + public function tearDown() + { + unset($this->_model); + } + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param bool $isVde + * @param bool $isLoggedIn + * @param bool $isConfiguration + * @param array $routers + * @param string|null $matchedValue + * + * @dataProvider matchDataProvider + */ + public function testMatch( + Mage_Core_Controller_Request_Http $request, + $isVde, + $isLoggedIn, + $isConfiguration, + array $routers = array(), + $matchedValue = null + ) { + $this->_model = $this->_prepareMocksForTestMatch($request, $isVde, $isLoggedIn, $isConfiguration, $routers); + + $this->assertEquals($matchedValue, $this->_model->match($request)); + if ($isVde && $isLoggedIn) { + $this->assertEquals(self::TEST_PATH, $request->getPathInfo()); + } + } + + /** + * Data provider for testMatch + * + * @return array + */ + public function matchDataProvider() + { + $vdeUrl = self::TEST_HOST . '/' . self::VDE_FRONT_NAME . self::TEST_PATH; + $notVdeUrl = self::TEST_HOST . self::TEST_PATH; + + $silencedMethods = array('_canBeStoreCodeInUrl'); + $excludedRouters = array( + 'admin' => 'admin router', + 'vde' => 'vde router', + ); + + // test data to verify routers match logic + $matchedRequest = $this->getMock('Mage_Core_Controller_Request_Http', $silencedMethods, array($vdeUrl)); + $routerMockedMethods = array('match'); + + $matchedController = $this->getMockForAbstractClass('Mage_Core_Controller_Varien_ActionAbstract', array(), '', + false + ); + + // method "match" will be invoked for this router because it's first in the list + $matchedRouter = $this->getMock( + 'Mage_Core_Controller_Varien_Router_Base', $routerMockedMethods, array(), '', false + ); + $matchedRouter->expects($this->once()) + ->method('match') + ->with($matchedRequest) + ->will($this->returnValue($matchedController)); + + // method "match" will not be invoked for this router because controller will be found by first router + $notMatchedRouter = $this->getMock( + 'Mage_Core_Controller_Varien_Router_Base', $routerMockedMethods, array(), '', false + ); + $notMatchedRouter->expects($this->never()) + ->method('match'); + + $matchedRouters = array_merge($excludedRouters, + array('matched' => $matchedRouter, 'not_matched' => $notMatchedRouter) + ); + + return array( + 'not vde request' => array( + '$request' => $this->getMock( + 'Mage_Core_Controller_Request_Http', $silencedMethods, array($notVdeUrl) + ), + '$isVde' => false, + '$isLoggedIn' => true, + '$isConfiguration' => false, + ), + 'not logged as admin' => array( + '$request' => $this->getMock( + 'Mage_Core_Controller_Request_Http', $silencedMethods, array($vdeUrl) + ), + '$isVde' => true, + '$isLoggedIn' => false, + '$isConfiguration' => false, + ), + 'no matched routers' => array( + '$request' => $this->getMock( + 'Mage_Core_Controller_Request_Http', $silencedMethods, array($vdeUrl) + ), + '$isVde' => true, + '$isLoggedIn' => true, + '$isConfiguration' => false, + '$routers' => $excludedRouters + ), + 'matched routers' => array( + '$request' => $matchedRequest, + '$isVde' => true, + '$isLoggedIn' => true, + '$isConfiguration' => true, + '$routers' => $matchedRouters, + '$matchedValue' => $matchedController, + ), + ); + } + + /** + * @param Mage_Core_Controller_Request_Http $request + * @param bool $isVde + * @param bool $isLoggedIn + * @param bool $isConfiguration + * @param array $routers + * @return Mage_DesignEditor_Controller_Varien_Router_Standard + */ + protected function _prepareMocksForTestMatch( + Mage_Core_Controller_Request_Http $request, + $isVde, + $isLoggedIn, + $isConfiguration, + array $routers + ) { + // default mocks - not affected on method functionality + $controllerFactory = $this->getMock('Mage_Core_Controller_Varien_Action_Factory', array(), array(), '', false); + $objectManager = $this->getMock('Magento_ObjectManager', array(), array(), '', false); + $testArea = 'frontend'; + $testBaseController = 'Mage_Core_Controller_Varien_Action'; + + $helper = $this->getMock('Mage_DesignEditor_Helper_Data', array('getFrontName'), array(), '', false); + $helper->expects($this->atLeastOnce()) + ->method('getFrontName') + ->will($this->returnValue(self::VDE_FRONT_NAME)); + + $backendSession = $this->getMock('Mage_Backend_Model_Auth_Session', array('isLoggedIn'), array(), '', false); + $backendSession->expects($isVde ? $this->once() : $this->never()) + ->method('isLoggedIn') + ->will($this->returnValue($isLoggedIn)); + + $frontController = $this->getMock('Mage_Core_Controller_Varien_Front', + array('applyRewrites', 'getRouters'), array(), '', false + ); + if ($isVde && $isLoggedIn) { + $frontController->expects($this->once()) + ->method('applyRewrites') + ->with($request); + $frontController->expects($this->once()) + ->method('getRouters') + ->will($this->returnValue($routers)); + } + + $stateModel = $this->getMock('Mage_DesignEditor_Model_State', array('update'), array(), '', false); + if (array_key_exists('matched', $routers)) { + $stateModel->expects($this->once()) + ->method('update') + ->with(self::AREA_CODE); + } + + $configuration = $this->getMock('Mage_Core_Model_Config', array('getNode'), array(), '', false); + if ($isVde && $isLoggedIn) { + $configurationData = null; + if ($isConfiguration) { + $configurationData = self::VDE_CONFIGURATION_DATA; + } + $configuration->expects($this->at(0)) + ->method('getNode') + ->with(Mage_DesignEditor_Model_Area::AREA_VDE) + ->will($this->returnValue($configurationData)); + + if ($isConfiguration) { + $elementMock = $this->getMock('stdClass', array('extend'), array(), '', false); + $elementMock->expects($this->once()) + ->method('extend') + ->with(self::VDE_CONFIGURATION_DATA, true); + + $configuration->expects($this->at(1)) + ->method('getNode') + ->with(Mage_Core_Model_App_Area::AREA_FRONTEND) + ->will($this->returnValue($elementMock)); + } + } + + $router = new Mage_DesignEditor_Controller_Varien_Router_Standard( + $controllerFactory, + $objectManager, + $testArea, + $testBaseController, + $backendSession, + $helper, + $stateModel, + $configuration + ); + $router->setFront($frontController); + return $router; + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Helper/DataTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Helper/DataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6561e89758f248e9aa1748d070a05858f90955e3 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Helper/DataTest.php @@ -0,0 +1,140 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Helper_DataTest extends PHPUnit_Framework_TestCase +{ + /** + * Test front name prefix + */ + const TEST_FRONT_NAME = 'test_front_name'; + + /** + * Test disabled cache types + */ + const TEST_DISABLED_CACHE_TYPES = 'type1, type2 '; + + /** + * Test data for blocks and containers + */ + const TEST_ELEMENT_DATA = '<node_1>value_1</node_1><node_2>value_2</node_2><node_3>value_3</node_3>'; + + /** + * @var array + */ + protected $_disabledCacheTypes = array('type1', 'type2'); + + /** + * @var string + */ + protected $_elementData = array('value_1', 'value_2', 'value_3',); + + /** + * @var Mage_DesignEditor_Helper_Data + */ + protected $_model; + + protected function tearDown() + { + unset($this->_model); + } + + public function testGetFrontName() + { + $frontNameNode = new Mage_Core_Model_Config_Element('<test>' . self::TEST_FRONT_NAME . '</test>'); + + $configurationMock = $this->getMock('Mage_Core_Model_Config', array('getNode'), array(), '', false); + $configurationMock->expects($this->once()) + ->method('getNode') + ->with(Mage_DesignEditor_Helper_Data::XML_PATH_FRONT_NAME) + ->will($this->returnValue($frontNameNode)); + + $this->_model = new Mage_DesignEditor_Helper_Data($configurationMock); + $this->assertEquals(self::TEST_FRONT_NAME, $this->_model->getFrontName()); + } + + public function testGetDisabledCacheTypes() + { + $cacheTypesNode = new Mage_Core_Model_Config_Element('<test>' . self::TEST_DISABLED_CACHE_TYPES . '</test>'); + + $configurationMock = $this->getMock('Mage_Core_Model_Config', array('getNode'), array(), '', false); + $configurationMock->expects($this->once()) + ->method('getNode') + ->with(Mage_DesignEditor_Helper_Data::XML_PATH_DISABLED_CACHE_TYPES) + ->will($this->returnValue($cacheTypesNode)); + + $this->_model = new Mage_DesignEditor_Helper_Data($configurationMock); + $this->assertEquals($this->_disabledCacheTypes, $this->_model->getDisabledCacheTypes()); + } + + /** + * Test for three similar methods - getBlockWhiteList, getBlockBlackList, getContainerWhiteList + * + * @param string $method + * @param string $xmlPath + * + * @dataProvider getElementsListDataProvider + * @covers Mage_DesignEditor_Helper_Data::getBlockWhiteList + * @covers Mage_DesignEditor_Helper_Data::getBlockBlackList + * @covers Mage_DesignEditor_Helper_Data::getContainerWhiteList + */ + public function testGetElementsList($method, $xmlPath) + { + $blockDataNode = new Mage_Core_Model_Config_Element('<test>' . self::TEST_ELEMENT_DATA . '</test>'); + + $configurationMock = $this->getMock('Mage_Core_Model_Config', array('getNode'), array(), '', false); + $configurationMock->expects($this->once()) + ->method('getNode') + ->with($xmlPath) + ->will($this->returnValue($blockDataNode)); + + $this->_model = new Mage_DesignEditor_Helper_Data($configurationMock); + $this->assertEquals($this->_elementData, $this->_model->$method()); + } + + /** + * Data provider for getElementsListDataProvider + * + * @return array + */ + public function getElementsListDataProvider() + { + return array( + 'getBlockWhiteList' => array( + '$method' => 'getBlockWhiteList', + '$xmlPath' => Mage_DesignEditor_Helper_Data::XML_PATH_BLOCK_WHITE_LIST, + ), + 'getBlockBlackList' => array( + '$method' => 'getBlockBlackList', + '$xmlPath' => Mage_DesignEditor_Helper_Data::XML_PATH_BLOCK_BLACK_LIST, + ), + 'getContainerWhiteList' => array( + '$method' => 'getContainerWhiteList', + '$xmlPath' => Mage_DesignEditor_Helper_Data::XML_PATH_CONTAINER_WHITE_LIST, + ), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Model/LayoutTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/LayoutTest.php index e405fec15f6080e1fe3ddcd54d3b7b53c072358d..b256df9f040abfa7c0cb0f66c014a242933cff8d 100644 --- a/dev/tests/unit/testsuite/Mage/DesignEditor/Model/LayoutTest.php +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/LayoutTest.php @@ -27,11 +27,137 @@ class Mage_DesignEditor_Model_LayoutTest extends PHPUnit_Framework_TestCase { + /**#@+ + * Layout property names + */ + const PROPERTY_SANITIZING = '_sanitationEnabled'; + const PROPERTY_WRAPPING = '_wrappingEnabled'; + /**#@-*/ + + /** + * @var Mage_DesignEditor_Model_Layout + */ + protected $_model; + + /** + * Block and container restriction data + * + * @var array + */ + protected $_restrictionData = array( + 'block' => array( + 'white_list' => array('Mage_Page_Block_'), + 'black_list' => array(), + ), + 'container' => array( + 'white_list' => array('root'), + ), + ); + + protected function setUp() + { + $this->_model = $this->_prepareLayoutObject(); + } + + protected function tearDown() + { + unset($this->_model); + } + public function testSanitizeLayout() { $data = file_get_contents(__DIR__ . '/_files/sanitize.xml'); $xml = new Varien_Simplexml_Element($data); - Mage_DesignEditor_Model_Layout::sanitizeLayout($xml); + $this->_model->sanitizeLayout($xml); $this->assertStringMatchesFormatFile(__DIR__ . '/_files/sanitize_expected.txt', $xml->asNiceXml()); } + + /** + * Create test layout with mocked arguments + * + * @return Mage_DesignEditor_Model_Layout + */ + protected function _prepareLayoutObject() + { + $helper = $this->getMock( + 'Mage_DesignEditor_Helper_Data', + array('getBlockWhiteList', 'getBlockBlackList', 'getContainerWhiteList'), + array(), '', false + ); + $helper->expects($this->any()) + ->method('getBlockWhiteList') + ->will($this->returnValue($this->_restrictionData['block']['white_list'])); + $helper->expects($this->any()) + ->method('getBlockBlackList') + ->will($this->returnValue($this->_restrictionData['block']['black_list'])); + $helper->expects($this->any()) + ->method('getContainerWhiteList') + ->will($this->returnValue($this->_restrictionData['container']['white_list'])); + + return new Mage_DesignEditor_Model_Layout( + $this->getMock('Mage_Core_Model_BlockFactory', array(), array(), '', false), + $this->getMock('Magento_Data_Structure', array(), array(), '', false), + $this->getMock('Mage_Core_Model_Layout_Argument_Processor', array(), array(), '', false), + $this->getMock('Mage_Core_Model_Layout_Translator', array(), array(), '', false), + $this->getMock('Mage_Core_Model_Layout_ScheduledStructure', array(), array(), '', false), + $this->getMock('Mage_DesignEditor_Block_Template', array(), array(), '', false), + $helper + ); + } + + /** + * Test covers both setSanitizing and setWrapping methods in one test because of similar method logic + * + * @param string $property + * @param bool $value + * @throws InvalidArgumentException + * + * @dataProvider flagsDataProvider + */ + public function testFlags($property, $value) + { + $this->_model = $this->_prepareLayoutObject(); + + switch ($property) { + case self::PROPERTY_SANITIZING: + $this->_model->setSanitizing($value); + break; + + case self::PROPERTY_WRAPPING: + $this->_model->setWrapping($value); + break; + + default: + throw new InvalidArgumentException('Unknown property.'); + } + + $this->assertAttributeSame($value, $property, $this->_model); + } + + /** + * Data provider for testFlags + * + * @return array + */ + public function flagsDataProvider() + { + return array( + 'sanitizing_true' => array( + '$property' => self::PROPERTY_SANITIZING, + '$value' => true, + ), + 'sanitizing_false' => array( + '$property' => self::PROPERTY_SANITIZING, + '$value' => false, + ), + 'wrapping_true' => array( + '$property' => self::PROPERTY_WRAPPING, + '$value' => true, + ), + 'wrapping_false' => array( + '$property' => self::PROPERTY_WRAPPING, + '$value' => false, + ), + ); + } } diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Model/ObserverTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/ObserverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..315e6a234e76ee892fb79cde1b10bfeb650b00be --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/ObserverTest.php @@ -0,0 +1,74 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Model_ObserverTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_DesignEditor_Model_Observer + */ + protected $_model; + + protected function tearDown() + { + unset($this->_model); + } + + /** + * @param int $themeId + * @dataProvider setThemeDataProvider + */ + public function testSetTheme($themeId) + { + /** @var $session Mage_Backend_Model_Session */ + $session = $this->getMock('Mage_Backend_Model_Session', null, array(), '', false); + $session->setData('theme_id', $themeId); + + $design = $this->getMock('Mage_Core_Model_Design_Package', array('setDesignTheme'), array(), '', false); + if ($themeId !== null) { + $design->expects($this->once()) + ->method('setDesignTheme') + ->with($themeId); + } else { + $design->expects($this->never()) + ->method('setDesignTheme'); + } + + $this->_model = new Mage_DesignEditor_Model_Observer($session, $design); + $this->_model->setTheme(); + } + + /** + * @return array + */ + public function setThemeDataProvider() + { + return array( + 'no theme id' => array('$themeId' => null), + 'correct theme id' => array('$themeId' => 1), + ); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Model/StateTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/StateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dbb1172e2fbf61ebc007f70ea9ad440272a89358 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/StateTest.php @@ -0,0 +1,205 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_DesignEditor_Model_StateTest extends PHPUnit_Framework_TestCase +{ + /* + * Test area code + */ + const AREA_CODE = 'front'; + + /** + * @var Mage_DesignEditor_Model_State + */ + protected $_model; + + /** + * @var Mage_Backend_Model_Session + */ + protected $_backendSession; + + /** + * @var Mage_Core_Model_Layout_Factory + */ + protected $_layoutFactory; + + /** + * @var Mage_DesignEditor_Model_Url_Factory + */ + protected $_urlModelFactory; + + /** + * @var Mage_Core_Model_Cache + */ + protected $_cacheManager; + + /** + * @var Mage_DesignEditor_Helper_Data + */ + protected $_dataHelper; + + /** + * @var array + */ + protected $_cacheTypes = array('type1', 'type2'); + + public function setUp() + { + $this->_backendSession = $this->getMock('Mage_Backend_Model_Session', array('setData'), + array(), '', false + ); + $this->_layoutFactory = $this->getMock('Mage_Core_Model_Layout_Factory', array('createLayout'), + array(), '', false + ); + $this->_urlModelFactory = $this->getMock('Mage_DesignEditor_Model_Url_Factory', array('replaceClassName'), + array(), '', false + ); + $this->_cacheManager = $this->getMock('Mage_Core_Model_Cache', array('banUse', 'cleanType'), + array(), '', false + ); + $this->_dataHelper = $this->getMock('Mage_DesignEditor_Helper_Data', array('getDisabledCacheTypes'), + array(), '', false + ); + $this->_model = new Mage_DesignEditor_Model_State( + $this->_backendSession, + $this->_layoutFactory, + $this->_urlModelFactory, + $this->_cacheManager, + $this->_dataHelper + ); + } + + public function testConstruct() + { + $this->assertAttributeEquals($this->_backendSession, '_backendSession', $this->_model); + $this->assertAttributeEquals($this->_layoutFactory, '_layoutFactory', $this->_model); + $this->assertAttributeEquals($this->_urlModelFactory, '_urlModelFactory', $this->_model); + $this->assertAttributeEquals($this->_cacheManager, '_cacheManager', $this->_model); + $this->assertAttributeEquals($this->_dataHelper, '_dataHelper', $this->_model); + } + + protected function _setAdditionalExpectations() + { + $this->_dataHelper->expects($this->once()) + ->method('getDisabledCacheTypes') + ->will($this->returnValue($this->_cacheTypes)); + + $this->_cacheManager->expects($this->at(0)) + ->method('banUse') + ->with('type1') + ->will($this->returnSelf()); + $this->_cacheManager->expects($this->at(1)) + ->method('cleanType') + ->with('type1') + ->will($this->returnSelf()); + $this->_cacheManager->expects($this->at(2)) + ->method('banUse') + ->with('type2') + ->will($this->returnSelf()); + $this->_cacheManager->expects($this->at(3)) + ->method('cleanType') + ->with('type2') + ->will($this->returnSelf()); + } + + public function testUpdateDesignMode() + { + $this->_setAdditionalExpectations(); + $request = $this->getMock('Mage_Core_Controller_Request_Http', array('getParam'), + array(), '', false); + + $controller = $this->getMock('Mage_Adminhtml_Controller_Action', array('getFullActionName'), array(), + '', false); + + $request->expects($this->once()) + ->method('getParam') + ->with('handle', '') + ->will($this->returnValue('default')); + + $this->_backendSession->expects($this->once()) + ->method('setData') + ->with('vde_current_mode', Mage_DesignEditor_Model_State::MODE_DESIGN); + + $this->_urlModelFactory->expects($this->once()) + ->method('replaceClassName') + ->with('Mage_DesignEditor_Model_Url_DesignMode'); + + $this->_layoutFactory->expects($this->once()) + ->method('createLayout') + ->with(array('area' => self::AREA_CODE), 'Mage_DesignEditor_Model_Layout'); + + $this->_model->update(self::AREA_CODE, $request, $controller); + } + + public function testUpdateNavigationMode() + { + $this->_setAdditionalExpectations(); + $request = $this->getMock('Mage_Core_Controller_Request_Http', array('getParam', 'isAjax', 'getPathInfo'), + array(), '', false); + + $controller = $this->getMock('Mage_Adminhtml_Controller_Action', array('getFullActionName'), array(), + '', false); + + $request->expects($this->once()) + ->method('getParam') + ->with('handle', '') + ->will($this->returnValue('')); + + $request->expects($this->once()) + ->method('isAjax') + ->will($this->returnValue(false)); + + $controller->expects($this->once()) + ->method('getFullActionName') + ->will($this->returnValue('index')); + + $this->_backendSession->expects($this->at(0)) + ->method('setData') + ->with('vde_current_handle', 'index'); + + $request->expects($this->once()) + ->method('getPathInfo') + ->will($this->returnValue('/')); + + $this->_backendSession->expects($this->at(1)) + ->method('setData') + ->with('vde_current_url', '/'); + + $this->_backendSession->expects($this->at(2)) + ->method('setData') + ->with('vde_current_mode', Mage_DesignEditor_Model_State::MODE_NAVIGATION); + + $this->_urlModelFactory->expects($this->once()) + ->method('replaceClassName') + ->with('Mage_DesignEditor_Model_Url_NavigationMode'); + + $this->_layoutFactory->expects($this->once()) + ->method('createLayout') + ->with(array('area' => self::AREA_CODE), 'Mage_Core_Model_Layout'); + + $this->_model->update(self::AREA_CODE, $request, $controller); + } +} diff --git a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/ExitTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/DesignModeTest.php similarity index 57% rename from dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/ExitTest.php rename to dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/DesignModeTest.php index 3d1f74c975827e469630f42330ecac381120b104..10ddc48bc630e6e445caf7fec7dcd88133d20a6d 100644 --- a/dev/tests/integration/testsuite/Mage/DesignEditor/Block/Toolbar/ExitTest.php +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/DesignModeTest.php @@ -19,36 +19,40 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Magento - * @package Mage_DesignEditor - * @subpackage integration_tests + * @package Mage_Core + * @subpackage unit_tests * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ - -class Mage_DesignEditor_Block_Toolbar_ExitTest extends PHPUnit_Framework_TestCase +class Mage_DesignEditor_Model_Url_DesignModeTest extends PHPUnit_Framework_TestCase { /** - * @var Mage_DesignEditor_Block_Toolbar_Buttons + * @var Mage_DesignEditor_Model_Url_DesignMode + */ + protected $_model; + + /** + * @var array */ - protected $_block; + protected $_testData = array(1,'test'); + + public function setUp() + { + $this->_model = new Mage_DesignEditor_Model_Url_DesignMode($this->_testData); + } - protected function setUp() + public function testGetRoutePath() { - $this->_block = Mage::app()->getLayout()->createBlock( - 'Mage_DesignEditor_Block_Toolbar_Buttons', - '', - array('data' => array('template' => 'toolbar/exit.phtml')) - ); + $this->assertEquals('#', $this->_model->getRoutePath()); } - protected function tearDown() + public function testGetRouteUrl() { - $this->_block = null; + $this->assertEquals('#', $this->_model->getRouteUrl()); } - public function testGetExitUrl() + public function testGetUrl() { - $expected = 'http://localhost/index.php/backend/admin/system_design_editor/exit/'; - $this->assertContains($expected, $this->_block->getExitUrl()); + $this->assertEquals('#', $this->_model->getUrl()); } } diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/FactoryTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/FactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3f7409bf9ebbf02eaa957b3336b5ba9237c7b1f4 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/FactoryTest.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_Core + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_DesignEditor_Model_Url_FactoryTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_DesignEditor_Model_Url_Factory + */ + protected $_model; + + /** + * @var Magento_ObjectManager + */ + protected $_objectManager; + + public function setUp() + { + $this->_objectManager = $this->getMock('Magento_ObjectManager_Zend', array('addAlias', 'create'), + array(), '', false); + $this->_model = new Mage_DesignEditor_Model_Url_Factory($this->_objectManager); + } + + public function testConstruct() + { + $this->assertAttributeInstanceOf('Magento_ObjectManager', '_objectManager', $this->_model); + } + + public function testReplaceClassName() + { + $this->_objectManager->expects($this->once()) + ->method('addAlias') + ->with('Mage_Core_Model_Url', 'TestClass'); + + $this->assertEquals($this->_model, $this->_model->replaceClassName('TestClass')); + } + + public function testCreateFromArray() + { + $this->_objectManager->expects($this->once()) + ->method('create') + ->with('Mage_Core_Model_Url', array(), false) + ->will($this->returnValue('ModelInstance')); + + $this->assertEquals('ModelInstance', $this->_model->createFromArray()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/HandleTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/HandleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..83954bde2e0998274d465b0a79f43370502e16c8 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/HandleTest.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 Mage_Core + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class Mage_DesignEditor_Model_Url_HandleTest extends PHPUnit_Framework_TestCase +{ + /**#@+ + * Test route params + */ + const FRONT_NAME = 'vde'; + const ROUTE_PATH = 'design'; + /**#@-*/ + + /** + * @var Mage_DesignEditor_Model_Url_Handle + */ + protected $_model; + + /** + * @var Mage_DesignEditor_Helper_Data + */ + protected $_helper; + + /** + * @var array + */ + protected $_testData = array(1,'test'); + + public function setUp() + { + $this->_helper = $this->getMock('Mage_DesignEditor_Helper_Data', array('getFrontName'), array(), '', false); + $this->_model = new Mage_DesignEditor_Model_Url_Handle($this->_helper, $this->_testData); + } + + public function testConstruct() + { + $this->assertAttributeEquals($this->_helper, '_helper', $this->_model); + $this->assertAttributeEquals($this->_testData, '_data', $this->_model); + } + + public function testGetRoutePath() + { + $this->_helper->expects($this->once()) + ->method('getFrontName') + ->will($this->returnValue(self::FRONT_NAME)); + + $this->_model->setData('route_path', self::ROUTE_PATH); + $this->assertEquals(self::FRONT_NAME . '/' . self::ROUTE_PATH, $this->_model->getRoutePath()); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/NavigationModeTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/NavigationModeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7dfd16c7acb7107957be6cc4e97b020d7d1d8f41 --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/Model/Url/NavigationModeTest.php @@ -0,0 +1,79 @@ +<?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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +class Mage_DesignEditor_Model_Url_NavigationModeTest extends PHPUnit_Framework_TestCase +{ + /**#@+ + * Test route params + */ + const FRONT_NAME = 'vde'; + const ROUTE_PATH = 'design'; + const VALID_URL = 'http://test.com'; + /**#@-*/ + + /** + * @var Mage_DesignEditor_Model_Url_NavigationMode + */ + protected $_model; + + /** + * @var Mage_DesignEditor_Helper_Data + */ + protected $_helper; + + /** + * @var array + */ + protected $_testData = array(1,'test'); + + public function setUp() + { + $this->_helper = $this->getMock('Mage_DesignEditor_Helper_Data', array('getFrontName'), array(), '', false); + $this->_model = new Mage_DesignEditor_Model_Url_NavigationMode($this->_helper, $this->_testData); + } + + public function testConstruct() + { + $this->assertAttributeEquals($this->_helper, '_helper', $this->_model); + $this->assertAttributeEquals($this->_testData, '_data', $this->_model); + } + + public function testGetRoutePath() + { + $this->_helper->expects($this->once()) + ->method('getFrontName') + ->will($this->returnValue(self::FRONT_NAME)); + + $this->_model->setData('route_path', self::ROUTE_PATH); + $this->assertEquals(self::FRONT_NAME . '/' . self::ROUTE_PATH, $this->_model->getRoutePath()); + } + + public function testGetRouteUrl() + { + $this->assertEquals(self::VALID_URL, $this->_model->getRouteUrl(self::VALID_URL)); + } +} diff --git a/dev/tests/unit/testsuite/Mage/DesignEditor/controllers/Adminhtml/EditorControllerTest.php b/dev/tests/unit/testsuite/Mage/DesignEditor/controllers/Adminhtml/EditorControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bdd71553e603677b5f3ca01a8e6e91fc13c335df --- /dev/null +++ b/dev/tests/unit/testsuite/Mage/DesignEditor/controllers/Adminhtml/EditorControllerTest.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_DesignEditor + * @subpackage unit_tests + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +require 'Mage/DesignEditor/controllers/Adminhtml/System/Design/EditorController.php'; +/** + * Test backend controller for the design editor + */ +class Mage_Core_Model_Theme_EditorControllerTest extends PHPUnit_Framework_TestCase +{ + /** + * @var Mage_DesignEditor_Adminhtml_System_Design_EditorController + */ + protected $_model; + + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + protected $_objectManagerMock; + + protected function setUp() + { + $this->_objectManagerMock = $this->getMock('Magento_ObjectManager_Zend', + array('create', 'get'), array(), '', false); + + $this->_model = $this->getMock('Mage_DesignEditor_Adminhtml_System_Design_EditorController', + array('_forward', '_title', '__', 'loadLayout', '_setActiveMenu', 'renderLayout'), + array( + $this->getMock('Mage_Core_Controller_Request_Http', array(), array(), '', false), + $this->getMock('Mage_Core_Controller_Response_Http', array(), array(), '', false), + null, + $this->_objectManagerMock, + $this->getMock('Mage_Core_Controller_Varien_Front', array(), array(), '', false), + $this->getMock('Mage_Core_Model_Layout_Factory', array(), array(), '', false), + array( + 'translator' => 'translator', + 'helper' => 'helper', + 'session' => 'session' + ) + )); + $this->_model->expects($this->any())->method('_title')->will($this->returnValue($this->_model)); + $this->_model->expects($this->any())->method('loadLayout'); + $this->_model->expects($this->any())->method('renderLayout'); + $this->_model->expects($this->any())->method('_setActiveMenu'); + $this->_model->expects($this->any())->method('__'); + } + + /** + * Return mocked theme service model + * + * @param bool $hasCustomizedThemes + * @return Mage_Core_Model_Theme_Service + */ + protected function _getThemeService($hasCustomizedThemes) + { + $themeService = $this->getMock('Mage_Core_Model_Theme_Service', + array('isCustomizationsExist'), array(), '', false); + $themeService + ->expects($this->at(0)) + ->method('isCustomizationsExist') + ->will($this->returnValue($hasCustomizedThemes)); + + $themeService + ->expects($this->any()) + ->method('isCustomizationsExist') + ->will($this->returnValue(false)); + return $themeService; + } + + /** + * @covers Mage_DesignEditor_Adminhtml_System_Design_EditorController::indexAction + * @dataProvider indexActionDataProvider + */ + public function testIndexAction($hasCustomizedThemes, $forwardCalls) + { + $this->_objectManagerMock + ->expects($this->any()) + ->method('get') + ->with('Mage_Core_Model_Theme_Service') + ->will($this->returnValue($this->_getThemeService($hasCustomizedThemes))); + + $this->_model + ->expects($this->any()) + ->method('_doSelectionTheme') + ->with('firstEntrance'); + + $this->_model + ->expects($this->exactly($forwardCalls)) + ->method('_forward'); + + $this->_model->indexAction(); + } + + /** + * @return array + */ + public function indexActionDataProvider() + { + return array( + array(true, 0), + array(false, 1) + ); + } + + /** + * @covers Mage_DesignEditor_Adminhtml_System_Design_EditorController::firstEntranceAction + * @dataProvider firstEntranceActionDataProvider + */ + public function testFirstEntranceAction($hasCustomizedThemes, $forwardCalls) + { + $this->_objectManagerMock + ->expects($this->any()) + ->method('get') + ->with('Mage_Core_Model_Theme_Service') + ->will($this->returnValue($this->_getThemeService($hasCustomizedThemes))); + + $this->_model + ->expects($this->any()) + ->method('_doSelectionTheme') + ->with('index'); + + $this->_model + ->expects($this->exactly($forwardCalls)) + ->method('_forward'); + + $this->_model->firstEntranceAction(); + } + + /** + * @return array + */ + public function firstEntranceActionDataProvider() + { + return array( + array(true, 1), + array(false, 0) + ); + } + +} diff --git a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Di/InstanceManagerTest.php b/dev/tests/unit/testsuite/Magento/Di/InstanceManager/ZendTest.php similarity index 90% rename from dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Di/InstanceManagerTest.php rename to dev/tests/unit/testsuite/Magento/Di/InstanceManager/ZendTest.php index c763067b33ff03d2c1475255539dfc2d2c0d3d5e..5bf42fc62a13e9610333c8fc8cdfc51faf4ab74d 100644 --- a/dev/tests/integration/framework/tests/unit/testsuite/Magento/Test/Di/InstanceManagerTest.php +++ b/dev/tests/unit/testsuite/Magento/Di/InstanceManager/ZendTest.php @@ -26,9 +26,9 @@ */ /** - * Test class for Magento_Test_Di_InstanceManager + * Test class for Magento_Di_InstanceManager_Zend */ -class Magento_Test_Di_InstanceManagerTest extends PHPUnit_Framework_TestCase +class Magento_Di_InstanceManager_ZendTest extends PHPUnit_Framework_TestCase { /** * Test object alias @@ -42,7 +42,7 @@ class Magento_Test_Di_InstanceManagerTest extends PHPUnit_Framework_TestCase public function testRemoveSharedInstance() { - $instanceManager = new Magento_Test_Di_InstanceManager(); + $instanceManager = new Magento_Di_InstanceManager_Zend(); $this->assertAttributeEmpty(self::SHARED_ATTRIBUTE, $instanceManager); $testObject = new Varien_Object(); diff --git a/dev/tests/unit/testsuite/Magento/DiTest.php b/dev/tests/unit/testsuite/Magento/Di/ZendTest.php similarity index 96% rename from dev/tests/unit/testsuite/Magento/DiTest.php rename to dev/tests/unit/testsuite/Magento/Di/ZendTest.php index ed365d39dcccd6446c5e526a4fe243064ef8c942..0d9d7779c99d7ca4fbc22d197e3abdb45898422e 100644 --- a/dev/tests/unit/testsuite/Magento/DiTest.php +++ b/dev/tests/unit/testsuite/Magento/Di/ZendTest.php @@ -26,9 +26,9 @@ */ /** - * Test case for Magento_Di + * Test case for Magento_Di_Zend */ -class Magento_DiTest extends PHPUnit_Framework_TestCase +class Magento_Di_ZendTest extends PHPUnit_Framework_TestCase { /**#@+ * Parent classes for test classes @@ -53,7 +53,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase /** * Model under test * - * @var Magento_Di + * @var Magento_Di_Zend */ protected $_model; @@ -260,7 +260,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase ->will($this->returnValue(false)); $instanceManager = $this->getMock( - 'Zend\Di\InstanceManager', + 'Magento_Di_InstanceManager_Zend', array('hasSharedInstance', 'getSharedInstance', 'addSharedInstanceWithParameters', 'addSharedInstance') ); $instanceManager->expects($this->any()) @@ -291,7 +291,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase ->method('addSharedInstance'); } - $this->_model = new Magento_Di($definitions, $instanceManager); + $this->_model = new Magento_Di_Zend($definitions, $instanceManager); } /** @@ -395,7 +395,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase ->will($this->returnValue($invalidInstantiator)); } - $instanceManager = $this->getMock('Zend\Di\InstanceManager', array('hasAlias', 'getClassFromAlias')); + $instanceManager = $this->getMock('Magento_Di_InstanceManager_Zend', array('hasAlias', 'getClassFromAlias')); $instanceManager->expects($this->once()) ->method('hasAlias') ->will($this->returnValue($noDefinition)); @@ -405,7 +405,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase ->will($this->returnValue(self::TEST_CLASS_MODEL . '_Other')); } - $this->_model = new Magento_Di($definitions, $instanceManager); + $this->_model = new Magento_Di_Zend($definitions, $instanceManager); } /** @@ -510,7 +510,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase } $instanceManager = $this->getMock( - 'Zend\Di\InstanceManager', array('hasAlias', 'addSharedInstanceWithParameters', 'addSharedInstance') + 'Magento_Di_InstanceManager_Zend', array('hasAlias', 'addSharedInstanceWithParameters', 'addSharedInstance') ); $instanceManager->expects($this->any()) ->method('hasAlias') @@ -537,7 +537,7 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase ->method('addSharedInstance'); } - $this->_model = new Magento_Di($definitions, $instanceManager); + $this->_model = new Magento_Di_Zend($definitions, $instanceManager); } /** @@ -616,7 +616,9 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase ->will($this->returnValue($constructParameters)); $instanceManager = $this->getMock( - 'Zend\Di\InstanceManager', array('hasAlias', 'getClassFromAlias', 'hasSharedInstance', 'getSharedInstance') + 'Magento_Di_InstanceManager_Zend', array('hasAlias', 'getClassFromAlias', 'hasSharedInstance', + 'getSharedInstance' + ) ); $instanceManager->expects($this->any()) ->method('hasAlias') @@ -631,6 +633,6 @@ class Magento_DiTest extends PHPUnit_Framework_TestCase ->method('getSharedInstance') ->will($this->returnCallback(array($this, 'callbackGetSharedInstance'))); - $this->_model = new Magento_Di($definitions, $instanceManager); + $this->_model = new Magento_Di_Zend($definitions, $instanceManager); } } diff --git a/dev/tests/unit/testsuite/Magento/ObjectManager/ZendTest.php b/dev/tests/unit/testsuite/Magento/ObjectManager/ZendTest.php index 0183978f1fe9458c3979fed1be9871cebcac7ea1..07872af1461186c60438b71b1c24d0b498e56cbd 100644 --- a/dev/tests/unit/testsuite/Magento/ObjectManager/ZendTest.php +++ b/dev/tests/unit/testsuite/Magento/ObjectManager/ZendTest.php @@ -85,7 +85,7 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase protected $_instanceManager; /** - * @var Zend\Di\Di|PHPUnit_Framework_MockObject_MockObject + * @var Magento_Di_Zend|PHPUnit_Framework_MockObject_MockObject */ protected $_diInstance; @@ -97,14 +97,22 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase unset($this->_diInstance); } - /** - * @dataProvider constructDataProvider - * @param string $definitionsFile - * @param Zend\Di\Di $diInstance - */ - public function testConstructWithDiObject($definitionsFile, $diInstance) + public function testConstructWithDiObject() { - $model = new Magento_ObjectManager_Zend($definitionsFile, $diInstance); + $diInstance = $this->getMock('Magento_Di_Zend', + array('instanceManager') + ); + $instanceManager = $this->getMock('Magento_Di_InstanceManager_Zend', array('addSharedInstance'), + array(), '', false + ); + $diInstance->expects($this->once()) + ->method('instanceManager') + ->will($this->returnValue($instanceManager)); + $instanceManager->expects($this->once()) + ->method('addSharedInstance') + ->will($this->returnCallback(array($this, 'verifyAddSharedInstanceCallback'))); + + $model = new Magento_ObjectManager_Zend(null, $diInstance); $this->assertAttributeInstanceOf(get_class($diInstance), '_di', $model); } @@ -162,13 +170,12 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase ->will($this->returnValue($nodeMock)); /** @var $instanceManagerMock Zend\Di\InstanceManager */ - $this->_instanceManager = $this->getMock('Zend\Di\InstanceManager', + $this->_instanceManager = $this->getMock('Magento_Di_InstanceManager_Zend', array('addSharedInstance', 'addAlias'), array(), '', false); $this->_instanceManager->expects($this->once()) ->method('addAlias'); - /** @var $diMock Zend\Di\Di */ - $this->_diInstance = $this->getMock('Zend\Di\Di', + $this->_diInstance = $this->getMock('Magento_Di_Zend', array('instanceManager', 'get'), array(), '', false); $this->_diInstance->expects($this->exactly(2)) ->method('instanceManager') @@ -193,10 +200,10 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase ->method('loadBase') ->will($this->returnSelf()); - $this->_instanceManager = $this->getMock('Zend\Di\InstanceManager', array('addSharedInstance'), + $this->_instanceManager = $this->getMock('Magento_Di_InstanceManager_Zend', array('addSharedInstance'), array(), '', false ); - $this->_diInstance = $this->getMock('Zend\Di\Di', + $this->_diInstance = $this->getMock('Magento_Di_Zend', array('instanceManager', 'newInstance', 'get', 'setDefinitionList') ); $this->_diInstance->expects($this->any()) @@ -215,49 +222,6 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase $this->_objectManager = new Magento_ObjectManager_Zend(null, $this->_diInstance); } - /** - * Data Provider for method __construct($definitionsFile, $diInstance) - * - * @return array - */ - public function constructDataProvider() - { - $this->_diInstance = $this->getMock('Zend\Di\Di', - array('get', 'setDefinitionList', 'instanceManager') - ); - $this->_magentoConfig = $this->getMock('Mage_Core_Model_Config', array('loadBase'), - array(), '', false - ); - $this->_instanceManager = $this->getMock('Zend\Di\InstanceManager', array('addSharedInstance'), - array(), '', false - ); - $this->_diInstance->expects($this->exactly(3)) - ->method('instanceManager') - ->will($this->returnValue($this->_instanceManager)); - $this->_diInstance->expects($this->exactly(6)) - ->method('get') - ->with('Mage_Core_Model_Config') - ->will($this->returnCallback(array($this, 'getCallback'))); - $this->_diInstance->expects($this->exactly(4)) - ->method('setDefinitionList') - ->will($this->returnCallback(array($this, 'verifySetDefinitionListCallback'))); - $this->_instanceManager->expects($this->exactly(3)) - ->method('addSharedInstance') - ->will($this->returnCallback(array($this, 'verifyAddSharedInstanceCallback'))); - - return array( - 'without definition file and with specific Di instance' => array( - null, $this->_diInstance - ), - 'with definition file and with specific Di instance' => array( - __DIR__ . '/_files/test_definition_file', $this->_diInstance - ), - 'with missing definition file and with specific Di instance' => array( - 'test_definition_file', $this->_diInstance - ) - ); - } - /** * Data provider for testLoadAreaConfiguration * @@ -277,16 +241,6 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase ); } - /** - * Callback to use instead Di::setDefinitionList - * - * @param Zend\Di\DefinitionList $definitions - */ - public function verifySetDefinitionListCallback(Zend\Di\DefinitionList $definitions) - { - $this->assertInstanceOf('Zend\Di\DefinitionList', $definitions); - } - /** * Callback to use instead InstanceManager::addSharedInstance * @@ -314,7 +268,7 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase } /** - * Callback method for Zend\Di\Di::newInstance + * Callback method for Magento_Di_Zend::newInstance * * @param string $className * @param array $arguments @@ -329,7 +283,7 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase } /** - * Callback method for Zend\Di\Di::get + * Callback method for Magento_Di_Zend::get * * @param string $className * @param array $arguments @@ -346,4 +300,154 @@ class Magento_ObjectManager_ZendTest extends PHPUnit_Framework_TestCase return self::OBJECT_GET; } + + public function testAddSharedInstance() + { + $object = new Varien_Object(); + $alias = 'Varien_Object_Alias'; + + $this->_prepareObjectManagerForAddSharedInstance($object, $alias); + $this->_objectManager->addSharedInstance($object, $alias); + } + + /** + * Prepare all required mocks for addSharedInstance + * + * @param object $instance + * @param string $classOrAlias + */ + protected function _prepareObjectManagerForAddSharedInstance($instance, $classOrAlias) + { + $diInstance = $this->getMock('Magento_Di_Zend', array('instanceManager')); + $instanceManager = $this->getMock( + 'Magento_Di_InstanceManager_Zend', array('addSharedInstance'), array(), '', false + ); + + $instanceManager->expects($this->exactly(2)) + ->method('addSharedInstance'); + $instanceManager->expects($this->at(1)) + ->method('addSharedInstance') + ->with($instance, $classOrAlias); + $diInstance->expects($this->exactly(2)) + ->method('instanceManager') + ->will($this->returnValue($instanceManager)); + + $this->_objectManager = new Magento_ObjectManager_Zend(null, $diInstance); + } + + public function testRemoveSharedInstance() + { + $alias = 'Varien_Object_Alias'; + + $this->_prepareObjectManagerForRemoveSharedInstance($alias); + $this->_objectManager->removeSharedInstance($alias); + } + + /** + * Prepare all required mocks for removeSharedInstance + * + * @param string $classOrAlias + */ + protected function _prepareObjectManagerForRemoveSharedInstance($classOrAlias) + { + $diInstance = $this->getMock('Magento_Di_Zend', array('instanceManager')); + $instanceManager = $this->getMock( + 'Magento_Di_InstanceManager_Zend', array('addSharedInstance', 'removeSharedInstance'), array(), '', + false + ); + + $instanceManager->expects($this->any()) + ->method('addSharedInstance') + ->will($this->returnSelf()); + $instanceManager->expects($this->once()) + ->method('removeSharedInstance') + ->with($classOrAlias); + $diInstance->expects($this->exactly(2)) + ->method('instanceManager') + ->will($this->returnValue($instanceManager)); + + $this->_objectManager = new Magento_ObjectManager_Zend(null, $diInstance); + } + + public function testHasSharedInstance() + { + $alias = 'Varien_Object_Alias'; + + $this->_prepareObjectManagerForHasSharedInstance($alias); + $this->_objectManager->hasSharedInstance($alias); + } + + /** + * Prepare all required mocks for hasSharedInstance + * + * @param string $classOrAlias + */ + protected function _prepareObjectManagerForHasSharedInstance($classOrAlias) + { + $diInstance = $this->getMock('Magento_Di_Zend', array('instanceManager')); + $instanceManager = $this->getMock( + 'Magento_Di_InstanceManager_Zend', array('hasSharedInstance'), array(), '', + false + ); + $instanceManager->expects($this->once()) + ->method('hasSharedInstance') + ->with($classOrAlias); + $diInstance->expects($this->exactly(2)) + ->method('instanceManager') + ->will($this->returnValue($instanceManager)); + + $this->_objectManager = new Magento_ObjectManager_Zend(null, $diInstance); + } + + public function testAddAlias() + { + $alias = 'Varien_Object_Alias'; + + $diInstance = $this->getMock('Magento_Di_Zend', array('instanceManager')); + $instanceManager = $this->getMock( + 'Magento_Di_InstanceManager_Zend', array('addSharedInstance', 'removeSharedInstance', 'addAlias'), + array(), '', false + ); + + $diInstance->expects($this->any()) + ->method('instanceManager') + ->will($this->returnValue($instanceManager)); + $instanceManager->expects($this->any()) + ->method('addSharedInstance') + ->will($this->returnSelf()); + + $this->_objectManager = new Magento_ObjectManager_Zend(null, $diInstance); + + $instanceManager->expects($this->once()) + ->method('addAlias') + ->with($alias, self::CLASS_NAME, array()); + + $this->_objectManager->addAlias($alias, self::CLASS_NAME); + } + + public function testGetClassFromAlias() + { + $alias = 'Varien_Object_Alias'; + + $diInstance = $this->getMock('Magento_Di_Zend', array('instanceManager')); + $instanceManager = $this->getMock( + 'Magento_Di_InstanceManager_Zend', array('addSharedInstance', 'removeSharedInstance', 'getClassFromAlias'), + array(), '', false + ); + + $diInstance->expects($this->any()) + ->method('instanceManager') + ->will($this->returnValue($instanceManager)); + $instanceManager->expects($this->any()) + ->method('addSharedInstance') + ->will($this->returnSelf()); + + $this->_objectManager = new Magento_ObjectManager_Zend(null, $diInstance); + + $instanceManager->expects($this->once()) + ->method('getClassFromAlias') + ->with($alias); + + $this->_objectManager->getClassFromAlias($alias); + } } diff --git a/dev/tests/unit/testsuite/Magento/_files/empty_definition_file b/dev/tests/unit/testsuite/Magento/_files/empty_definition_file new file mode 100644 index 0000000000000000000000000000000000000000..67d0259b7226423dcae69ae592d5ccca224315a7 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/_files/empty_definition_file @@ -0,0 +1 @@ +a:0:{} diff --git a/lib/Magento/Di.php b/lib/Magento/Di.php index 7bc07731a1c20ed951983988e06ecd51bde5f42c..b10d0893556933ea601494c44a5325309bda0817 100644 --- a/lib/Magento/Di.php +++ b/lib/Magento/Di.php @@ -24,528 +24,22 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -use Zend\Di\Exception; -/** - * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) - * @todo Need decrease ExcessiveClassComplexity of this class, it will be implemented in MAGETWO-3861 - */ -class Magento_Di extends Zend\Di\Di +interface Magento_Di extends Zend\Di\LocatorInterface { /** - * @var array - */ - protected $_cachedInstances = array(); - - /** - * @var array + * Get instance manager object + * + * @return Magento_Di_InstanceManager */ - protected $_baseDefinitions = array(); + public function instanceManager(); /** * Retrieve a new instance of a class * - * Forces retrieval of a discrete instance of the given class, using the - * constructor parameters provided. - * * @param mixed $name * @param array $parameters * @param bool $isShared * @return null|object - * @throws Zend\Di\Exception\RuntimeException - * @throws Zend\Di\Exception\ClassNotFoundException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @todo Need to refactor this method - */ - public function newInstance($name, array $parameters = array(), $isShared = true) - { - // localize dependencies - $definitions = $this->definitions; - - if (!$this->definitions()->hasClass($name)) { - array_push($this->instanceContext, array('NEW', $name, $name)); - - if ($this->_isArrayHasDataKey($parameters)) { - $parameters = reset($parameters); - } - - if (preg_match('/\w*_\w*\_Model/', $name)) { - $instance = new $name( - $this->_getCachedDependency('Mage_Core_Model_Event_Manager'), - $this->_getCachedDependency('Mage_Core_Model_Cache'), - null, - null, - $parameters - ); - } else if (preg_match('/\w*_\w*\_Block/', $name)) { - $instance = new $name( - $this->_getCachedDependency('Mage_Core_Controller_Request_Http'), - $this->_getCachedDependency('Mage_Core_Model_Layout'), - $this->_getCachedDependency('Mage_Core_Model_Event_Manager'), - $this->_getCachedDependency('Mage_Core_Model_Url'), - $this->_getCachedDependency('Mage_Core_Model_Translate'), - $this->_getCachedDependency('Mage_Core_Model_Cache'), - $this->_getCachedDependency('Mage_Core_Model_Design_Package'), - $this->_getCachedDependency('Mage_Core_Model_Session'), - $this->_getCachedDependency('Mage_Core_Model_Store_Config'), - $this->_getCachedDependency('Mage_Core_Controller_Varien_Front'), - $this->_getCachedDependency('Mage_Core_Model_Factory_Helper'), - $parameters - ); - } else { - $instance = new $name(); - } - if ($isShared) { - $this->_addSharedInstance($instance, $name, $parameters); - } - array_pop($this->instanceContext); - return $instance; - } - - $instanceManager = $this->instanceManager(); - - if ($instanceManager->hasAlias($name)) { - $class = $instanceManager->getClassFromAlias($name); - $alias = $name; - } else { - $class = $name; - $alias = null; - } - - array_push($this->instanceContext, array('NEW', $class, $alias)); - - if (!$definitions->hasClass($class)) { - $aliasMsg = ($alias) ? '(specified by alias ' . $alias . ') ' : ''; - throw new Exception\ClassNotFoundException( - 'Class ' . $aliasMsg . $class . ' could not be located in provided definitions.' - ); - } - - $instantiator = $definitions->getInstantiator($class); - - if ($instantiator === '__construct') { - $instance = $this->createInstanceViaConstructor($class, $parameters, $alias); - } elseif (is_callable($instantiator, false)) { - $instance = $this->createInstanceViaCallback($instantiator, $parameters, $alias); - } else { - if (is_array($instantiator)) { - $msg = sprintf( - 'Invalid instantiator: %s::%s() is not callable.', - isset($instantiator[0]) ? $instantiator[0] : 'NoClassGiven', - isset($instantiator[1]) ? $instantiator[1] : 'NoMethodGiven' - ); - } else { - $msg = sprintf( - 'Invalid instantiator of type "%s" for "%s".', - gettype($instantiator), - $name - ); - } - throw new Exception\RuntimeException($msg); - } - - if ($isShared) { - $this->_addSharedInstance($instance, $name, $parameters); - } - - array_pop($this->instanceContext); - return $instance; - } - - /** - * Check is array has 'data' key - * Function used to provide possibility to use old and new format of params array, when new model instantiated - * - * @param $array - * @return bool - */ - protected function _isArrayHasDataKey($array) - { - return (count($array) == 1) && array_key_exists('data', $array); - } - - /** - * Add shared instance to instance manager - * - * @param object $instance - * @param string $name - * @param array $parameters - * @return Magento_Di - */ - protected function _addSharedInstance($instance, $name, array $parameters = array()) - { - if ($parameters) { - $this->instanceManager->addSharedInstanceWithParameters($instance, $name, $parameters); - } else { - $this->instanceManager->addSharedInstance($instance, $name); - } - - return $this; - } - - /** - * Retrieve cached object - * - * @param string $className - * @return mixed - */ - protected function _getCachedDependency($className) - { - if (!isset($this->_cachedInstances[$className])) { - $this->_cachedInstances[$className] = $this->get($className); - } - - return $this->_cachedInstances[$className]; - } - - /** - * Retrieve a class instance based on class name - * - * Any parameters provided will be used as constructor arguments. If any - * given parameter is a DependencyReference object, it will be fetched - * from the container so that the instance may be injected. - * - * @param string $class - * @param array $params - * @param string|null $alias - * @return object - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @todo Need to refactor this method - */ - protected function createInstanceViaConstructor($class, $params, $alias = null) - { - $callParameters = array(); - if ($this->definitions->hasMethodParameters($class, '__construct')) { - $callParameters = $this->resolveMethodParameters($class, '__construct', $params, $alias, true, true); - } - - // Hack to avoid Reflection in most common use cases - switch (count($callParameters)) { - case 0: - return new $class(); - case 1: - return new $class($callParameters[0]); - case 2: - return new $class($callParameters[0], $callParameters[1]); - case 3: - return new $class($callParameters[0], $callParameters[1], $callParameters[2]); - case 4: - return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3]); - case 5: - return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], - $callParameters[4] - ); - case 6: - return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], - $callParameters[4], $callParameters[5] - ); - case 7: - return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], - $callParameters[4], $callParameters[5], $callParameters[6] - ); - case 8: - return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], - $callParameters[4], $callParameters[5], $callParameters[6], $callParameters[7] - ); - case 9: - return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], - $callParameters[4], $callParameters[5], $callParameters[6], $callParameters[7], $callParameters[8] - ); - case 10: - return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], - $callParameters[4], $callParameters[5], $callParameters[6], $callParameters[7], $callParameters[8], - $callParameters[9] - ); - - default: - $reflection = new \ReflectionClass($class); - return $reflection->newInstanceArgs($callParameters); - } - } - - /** - * Resolve parameters referencing other services - * - * @param string $class - * @param string $method - * @param array $callTimeUserParams - * @param string $alias - * @param bool $methodIsRequired - * @param bool $isInstantiator - * @return array|bool - * @throws Zend\Di\Exception\MissingPropertyException - * @throws Zend\Di\Exception\CircularDependencyException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @todo Need to refactor this method */ - protected function resolveMethodParameters($class, $method, array $callTimeUserParams, $alias, $methodIsRequired, - $isInstantiator = false - ) { - // parameters for this method, in proper order, to be returned - $resolvedParams = array(); - - // parameter requirements from the definition - $methodParameters = $this->definitions->getMethodParameters($class, $method); - - /** Magento */ - $callTimeParamNames = array_keys($callTimeUserParams); - $isPositional = false; - $parameterNames = array(); - - foreach ($methodParameters as $param) { - $parameterNames[] = $param[0]; - } - - foreach ($callTimeParamNames as $name) { - if (is_numeric($name)) { - $isPositional = true; - $callTimeUserParams[$parameterNames[$name]] = $callTimeUserParams[$name]; - } - } - - if (!$isPositional) { - if (count($callTimeUserParams) - && !isset($callTimeUserParams['data']) - ) { - if (in_array('data', $parameterNames)) { - $intersection = array_intersect($callTimeParamNames, $parameterNames); - if (!$intersection) { - $callTimeUserParams = array('data' => $callTimeUserParams); - } - } - } - } - - // computed parameters array - $computedParams = array( - 'value' => array(), - 'required' => array(), - 'optional' => array() - ); - - // retrieve instance configurations for all contexts - $iConfig = array(); - $aliases = $this->instanceManager->getAliases(); - - // for the alias in the dependency tree - if ($alias && $this->instanceManager->hasConfig($alias)) { - $iConfig['thisAlias'] = $this->instanceManager->getConfig($alias); - } - - // for the current class in the dependency tree - if ($this->instanceManager->hasConfig($class)) { - $iConfig['thisClass'] = $this->instanceManager->getConfig($class); - } - - // for the parent class, provided we are deeper than one node - if (isset($this->instanceContext[0])) { - list($requestedClass, $requestedAlias) = ($this->instanceContext[0][0] == 'NEW') - ? array($this->instanceContext[0][1], $this->instanceContext[0][2]) - : array($this->instanceContext[1][1], $this->instanceContext[1][2]); - } else { - $requestedClass = $requestedAlias = null; - } - - if ($requestedClass != $class && $this->instanceManager->hasConfig($requestedClass)) { - $iConfig['requestedClass'] = $this->instanceManager->getConfig($requestedClass); - if ($requestedAlias) { - $iConfig['requestedAlias'] = $this->instanceManager->getConfig($requestedAlias); - } - } - - // This is a 2 pass system for resolving parameters - // first pass will find the sources, the second pass will order them and resolve lookups if they exist - // MOST methods will only have a single parameters to resolve, so this should be fast - - foreach ($methodParameters as $fqParamPos => $info) { - list($name, $type, $isRequired) = $info; - - $fqParamName = substr_replace($fqParamPos, ':' . $info[0], strrpos($fqParamPos, ':')); - - // PRIORITY 1 - consult user provided parameters - if (isset($callTimeUserParams[$fqParamPos]) || isset($callTimeUserParams[$name])) { - - if (isset($callTimeUserParams[$fqParamPos])) { - $callTimeCurValue =& $callTimeUserParams[$fqParamPos]; - } elseif (isset($callTimeUserParams[$fqParamName])) { - $callTimeCurValue =& $callTimeUserParams[$fqParamName]; - } else { - $callTimeCurValue =& $callTimeUserParams[$name]; - } - - if ($type && is_string($callTimeCurValue)) { - if ($this->instanceManager->hasAlias($callTimeCurValue)) { - // was an alias provided? - $computedParams['required'][$fqParamPos] = array( - $callTimeUserParams[$name], - $this->instanceManager->getClassFromAlias($callTimeCurValue) - ); - } elseif ($this->definitions->hasClass($callTimeUserParams[$name])) { - // was a known class provided? - $computedParams['required'][$fqParamPos] = array( - $callTimeCurValue, - $callTimeCurValue - ); - } else { - // must be a value - $computedParams['value'][$fqParamPos] = $callTimeCurValue; - } - } else { - // int, float, null, object, etc - $computedParams['value'][$fqParamPos] = $callTimeCurValue; - } - unset($callTimeCurValue); - continue; - } - - // PRIORITY 2 -specific instance configuration (thisAlias) - this alias - // PRIORITY 3 -THEN specific instance configuration (thisClass) - this class - // PRIORITY 4 -THEN specific instance configuration (requestedAlias) - requested alias - // PRIORITY 5 -THEN specific instance configuration (requestedClass) - requested class - - foreach (array('thisAlias', 'thisClass', 'requestedAlias', 'requestedClass') as $thisIndex) { - // check the provided parameters config - if (isset($iConfig[$thisIndex]['parameters'][$fqParamPos]) - || isset($iConfig[$thisIndex]['parameters'][$fqParamName]) - || isset($iConfig[$thisIndex]['parameters'][$name])) { - - if (isset($iConfig[$thisIndex]['parameters'][$fqParamPos])) { - $iConfigCurValue =& $iConfig[$thisIndex]['parameters'][$fqParamPos]; - } elseif (isset($iConfig[$thisIndex]['parameters'][$fqParamName])) { - $iConfigCurValue =& $iConfig[$thisIndex]['parameters'][$fqParamName]; - } else { - $iConfigCurValue =& $iConfig[$thisIndex]['parameters'][$name]; - } - - if ($type === false && is_string($iConfigCurValue)) { - $computedParams['value'][$fqParamPos] = $iConfigCurValue; - } elseif (is_string($iConfigCurValue) - && isset($aliases[$iConfigCurValue])) { - $computedParams['required'][$fqParamPos] = array( - $iConfig[$thisIndex]['parameters'][$name], - $this->instanceManager->getClassFromAlias($iConfigCurValue) - ); - } elseif (is_string($iConfigCurValue) - && $this->definitions->hasClass($iConfigCurValue)) { - $computedParams['required'][$fqParamPos] = array( - $iConfigCurValue, - $iConfigCurValue - ); - } elseif (is_object($iConfigCurValue) - && $iConfigCurValue instanceof Closure - && $type !== 'Closure') { - $computedParams['value'][$fqParamPos] = $iConfigCurValue(); - } else { - $computedParams['value'][$fqParamPos] = $iConfigCurValue; - } - unset($iConfigCurValue); - continue 2; - } - - } - - // PRIORITY 6 - globally preferred implementations - - // next consult alias level preferred instances - if ($alias && $this->instanceManager->hasTypePreferences($alias)) { - $pInstances = $this->instanceManager->getTypePreferences($alias); - foreach ($pInstances as $pInstance) { - if (is_object($pInstance)) { - $computedParams['value'][$fqParamPos] = $pInstance; - continue 2; - } - $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? - $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; - if ($pInstanceClass === $type || $this->isSubclassOf($pInstanceClass, $type)) { - $computedParams['required'][$fqParamPos] = array($pInstance, $pInstanceClass); - continue 2; - } - } - } - - // next consult class level preferred instances - if ($type && $this->instanceManager->hasTypePreferences($type)) { - $pInstances = $this->instanceManager->getTypePreferences($type); - foreach ($pInstances as $pInstance) { - if (is_object($pInstance)) { - $computedParams['value'][$fqParamPos] = $pInstance; - continue 2; - } - $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? - $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; - if ($pInstanceClass === $type || $this->isSubclassOf($pInstanceClass, $type)) { - $computedParams['required'][$fqParamPos] = array($pInstance, $pInstanceClass); - continue 2; - } - } - } - - if (!$isRequired) { - $computedParams['optional'][$fqParamPos] = true; - } - - if ($type && $isRequired && $methodIsRequired) { - $computedParams['required'][$fqParamPos] = array($type, $type); - } - - } - - $index = 0; - foreach ($methodParameters as $fqParamPos => $value) { - $name = $value[0]; - $defaultValue = $value[3]; - - if (isset($computedParams['value'][$fqParamPos])) { - - // if there is a value supplied, use it - $resolvedParams[$index] = $computedParams['value'][$fqParamPos]; - - } elseif (isset($computedParams['required'][$fqParamPos])) { - - // detect circular dependencies! (they can only happen in instantiators) - if ($isInstantiator - && in_array($computedParams['required'][$fqParamPos][1], $this->currentDependencies)) { - throw new Exception\CircularDependencyException( - "Circular dependency detected: $class depends on {$value[1]} and vice versa" - ); - } - array_push($this->currentDependencies, $class); - $dConfig = $this->instanceManager->getConfig($computedParams['required'][$fqParamPos][0]); - if ($dConfig['shared'] === false) { - $resolvedParams[$index] - = $this->newInstance($computedParams['required'][$fqParamPos][0], $callTimeUserParams, false); - } else { - $resolvedParams[$index] = $this->get($computedParams['required'][$fqParamPos][0]); - } - - array_pop($this->currentDependencies); - - } elseif (!array_key_exists($fqParamPos, $computedParams['optional'])) { - - if ($methodIsRequired) { - // if this item was not marked as optional, - // plus it cannot be resolve, and no value exist, bail out - throw new Exception\MissingPropertyException(sprintf( - 'Missing %s for parameter ' . $name . ' for ' . $class . '::' . $method, - (($value[0] === null) ? 'value' : 'instance/object' ) - )); - } else { - return false; - } - - } else { - $resolvedParams[$index] = $defaultValue; - } - - $index++; - } - - return $resolvedParams; // return ordered list of parameters - } + public function newInstance($name, array $parameters = array(), $isShared = true); } diff --git a/lib/Magento/Di/DefinitionList/Zend.php b/lib/Magento/Di/DefinitionList/Zend.php index 3bddfb7258480c9053533478726d8244d59ad42a..10c16555f4b8fe454fb9d644cedce93c01bef5a0 100644 --- a/lib/Magento/Di/DefinitionList/Zend.php +++ b/lib/Magento/Di/DefinitionList/Zend.php @@ -43,4 +43,27 @@ class Magento_Di_DefinitionList_Zend extends Zend\Di\DefinitionList } return array(); } + + /** + * Fix bug for in ZF2: https://github.com/zendframework/zf2/commit/26c8899ddfc4fe2672b2efa9ff3cf3cac600bec3 + * @todo Delete this method after ZF2 library update + * {@inheritDoc} + */ + public function hasMethod($class, $method) + { + /** @var $definition Zend\Di\Definition\DefinitionInterface */ + foreach ($this as $definition) { + if ($definition->hasClass($class)) { + if ($definition->hasMethods($class) === false + && $definition instanceof Zend\Di\Definition\PartialMarker + ) { + continue; + } else { + return $definition->hasMethod($class, $method); + } + } + } + + return false; + } } diff --git a/lib/Magento/Di/InstanceManager.php b/lib/Magento/Di/InstanceManager.php new file mode 100644 index 0000000000000000000000000000000000000000..bb56e4280fb8c99a0e72ca16c1d627047d9f5894 --- /dev/null +++ b/lib/Magento/Di/InstanceManager.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 Magento_Di + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +interface Magento_Di_InstanceManager +{ + /** + * Add shared instance + * + * @param object $instance + * @param string $classOrAlias + * @return Magento_Di_InstanceManager + */ + public function addSharedInstance($instance, $classOrAlias); + + /** + * Check whether instance manager has shared instance of given class (alias) + * + * @param string $classOrAlias + * @return bool + */ + public function hasSharedInstance($classOrAlias); + + /** + * Remove shared instance + * + * @param string $classOrAlias + * @return Magento_Di_InstanceManager + */ + public function removeSharedInstance($classOrAlias); +} diff --git a/dev/tests/integration/framework/Magento/Test/Di/InstanceManager.php b/lib/Magento/Di/InstanceManager/Zend.php similarity index 85% rename from dev/tests/integration/framework/Magento/Test/Di/InstanceManager.php rename to lib/Magento/Di/InstanceManager/Zend.php index 9e715c0db3715d3046625c07a6f470a39c8ed093..189bd76d2ad3ab4a5fea5cf7f23149f3edfa1c2c 100644 --- a/dev/tests/integration/framework/Magento/Test/Di/InstanceManager.php +++ b/lib/Magento/Di/InstanceManager/Zend.php @@ -19,23 +19,25 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Magento - * @package Magento - * @subpackage integration_tests + * @package Magento_Di * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ use Zend\Di\InstanceManager; -class Magento_Test_Di_InstanceManager extends InstanceManager +class Magento_Di_InstanceManager_Zend extends InstanceManager implements Magento_Di_InstanceManager { /** * Remove shared instance * * @param string $classOrAlias + * @return Magento_Di_InstanceManager_Zend */ public function removeSharedInstance($classOrAlias) { unset($this->sharedInstances[$classOrAlias]); + + return $this; } } diff --git a/lib/Magento/Di/Zend.php b/lib/Magento/Di/Zend.php new file mode 100644 index 0000000000000000000000000000000000000000..3d49d95faedcb62157104fcab45c36a47e2bdb92 --- /dev/null +++ b/lib/Magento/Di/Zend.php @@ -0,0 +1,578 @@ +<?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_Di + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +use Zend\Di\Exception; +/** + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @todo Need decrease ExcessiveClassComplexity and CouplingBetweenObjects of this class, + * @todo it will be implemented in MAGETWO-3861 + */ +class Magento_Di_Zend extends Zend\Di\Di implements Magento_Di +{ + /** + * @var array + */ + protected $_cachedInstances = array(); + + /** + * @param Zend\Di\DefinitionList|null $definitions + * @param Magento_Di_InstanceManager|null $instanceManager + * @param Zend\Di\Config|null $config + * @param string|null $definitionsFile + * @return Magento_Di_Zend + */ + public function __construct( + Zend\Di\DefinitionList $definitions = null, + Magento_Di_InstanceManager $instanceManager = null, + Zend\Di\Config $config = null, + $definitionsFile = null + ) { + if (is_null($definitions)) { + if (is_string($definitionsFile) && is_file($definitionsFile) && is_readable($definitionsFile)) { + $definitionProvider = new Magento_Di_Definition_ArrayDefinition_Zend( + unserialize(file_get_contents($definitionsFile)) + ); + } else { + $definitionProvider = new Magento_Di_Definition_RuntimeDefinition_Zend(); + } + $definitions = new Magento_Di_DefinitionList_Zend($definitionProvider); + } + + $instanceManager = $instanceManager ?: new Magento_Di_InstanceManager_Zend(); + + parent::__construct($definitions, $instanceManager, $config); + $this->setInstanceManager($instanceManager); + } + + /** + * Retrieve a new instance of a class + * + * Forces retrieval of a discrete instance of the given class, using the + * constructor parameters provided. + * + * @param mixed $name + * @param array $parameters + * @param bool $isShared + * @return null|object + * @throws Zend\Di\Exception\RuntimeException + * @throws Zend\Di\Exception\ClassNotFoundException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @todo Need to refactor this method + */ + public function newInstance($name, array $parameters = array(), $isShared = true) + { + // localize dependencies + $definitions = $this->definitions; + + if (!$this->definitions()->hasClass($name)) { + array_push($this->instanceContext, array('NEW', $name, $name)); + + if ($this->_isArrayHasDataKey($parameters)) { + $parameters = reset($parameters); + } + + if (preg_match('/\w*_\w*\_Model/', $name)) { + $instance = new $name( + $this->_getCachedDependency('Mage_Core_Model_Event_Manager'), + $this->_getCachedDependency('Mage_Core_Model_Cache'), + null, + null, + $parameters + ); + } else if (preg_match('/\w*_\w*\_Block/', $name)) { + $instance = new $name( + $this->_getCachedDependency('Mage_Core_Controller_Request_Http'), + $this->_getCachedDependency('Mage_Core_Model_Layout'), + $this->_getCachedDependency('Mage_Core_Model_Event_Manager'), + $this->_getCachedDependency('Mage_Core_Model_Url'), + $this->_getCachedDependency('Mage_Core_Model_Translate'), + $this->_getCachedDependency('Mage_Core_Model_Cache'), + $this->_getCachedDependency('Mage_Core_Model_Design_Package'), + $this->_getCachedDependency('Mage_Core_Model_Session'), + $this->_getCachedDependency('Mage_Core_Model_Store_Config'), + $this->_getCachedDependency('Mage_Core_Controller_Varien_Front'), + $this->_getCachedDependency('Mage_Core_Model_Factory_Helper'), + $parameters + ); + } else { + $instance = new $name(); + } + if ($isShared) { + $this->_addSharedInstance($instance, $name, $parameters); + } + array_pop($this->instanceContext); + return $instance; + } + + $instanceManager = $this->instanceManager(); + + if ($instanceManager->hasAlias($name)) { + $class = $instanceManager->getClassFromAlias($name); + $alias = $name; + } else { + $class = $name; + $alias = null; + } + + array_push($this->instanceContext, array('NEW', $class, $alias)); + + if (!$definitions->hasClass($class)) { + $aliasMsg = ($alias) ? '(specified by alias ' . $alias . ') ' : ''; + throw new Exception\ClassNotFoundException( + 'Class ' . $aliasMsg . $class . ' could not be located in provided definitions.' + ); + } + + $instantiator = $definitions->getInstantiator($class); + + if ($instantiator === '__construct') { + $instance = $this->createInstanceViaConstructor($class, $parameters, $alias); + } elseif (is_callable($instantiator, false)) { + $instance = $this->createInstanceViaCallback($instantiator, $parameters, $alias); + } else { + if (is_array($instantiator)) { + $msg = sprintf( + 'Invalid instantiator: %s::%s() is not callable.', + isset($instantiator[0]) ? $instantiator[0] : 'NoClassGiven', + isset($instantiator[1]) ? $instantiator[1] : 'NoMethodGiven' + ); + } else { + $msg = sprintf( + 'Invalid instantiator of type "%s" for "%s".', + gettype($instantiator), + $name + ); + } + throw new Exception\RuntimeException($msg); + } + + if ($isShared) { + $this->_addSharedInstance($instance, $name, $parameters); + } + + array_pop($this->instanceContext); + return $instance; + } + + /** + * Check is array has 'data' key + * Function used to provide possibility to use old and new format of params array, when new model instantiated + * + * @param $array + * @return bool + */ + protected function _isArrayHasDataKey($array) + { + return (count($array) == 1) && array_key_exists('data', $array); + } + + /** + * Add shared instance to instance manager + * + * @param object $instance + * @param string $name + * @param array $parameters + * @return Magento_Di + */ + protected function _addSharedInstance($instance, $name, array $parameters = array()) + { + if ($parameters) { + $this->instanceManager->addSharedInstanceWithParameters($instance, $name, $parameters); + } else { + $this->instanceManager->addSharedInstance($instance, $name); + } + + return $this; + } + + /** + * Retrieve cached object + * + * @param string $className + * @return mixed + */ + protected function _getCachedDependency($className) + { + if (!isset($this->_cachedInstances[$className])) { + $this->_cachedInstances[$className] = $this->get($className); + } + + return $this->_cachedInstances[$className]; + } + + /** + * Retrieve a class instance based on class name + * + * Any parameters provided will be used as constructor arguments. If any + * given parameter is a DependencyReference object, it will be fetched + * from the container so that the instance may be injected. + * + * @param string $class + * @param array $params + * @param string|null $alias + * @return object + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @todo Need to refactor this method + */ + protected function createInstanceViaConstructor($class, $params, $alias = null) + { + $callParameters = array(); + if ($this->definitions->hasMethodParameters($class, '__construct')) { + $callParameters = $this->resolveMethodParameters($class, '__construct', $params, $alias, true, true); + } + + // Hack to avoid Reflection in most common use cases + switch (count($callParameters)) { + case 0: + return new $class(); + case 1: + return new $class($callParameters[0]); + case 2: + return new $class($callParameters[0], $callParameters[1]); + case 3: + return new $class($callParameters[0], $callParameters[1], $callParameters[2]); + case 4: + return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3]); + case 5: + return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], + $callParameters[4] + ); + case 6: + return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], + $callParameters[4], $callParameters[5] + ); + case 7: + return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], + $callParameters[4], $callParameters[5], $callParameters[6] + ); + case 8: + return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], + $callParameters[4], $callParameters[5], $callParameters[6], $callParameters[7] + ); + case 9: + return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], + $callParameters[4], $callParameters[5], $callParameters[6], $callParameters[7], $callParameters[8] + ); + case 10: + return new $class($callParameters[0], $callParameters[1], $callParameters[2], $callParameters[3], + $callParameters[4], $callParameters[5], $callParameters[6], $callParameters[7], $callParameters[8], + $callParameters[9] + ); + + default: + $reflection = new \ReflectionClass($class); + return $reflection->newInstanceArgs($callParameters); + } + } + + /** + * Resolve parameters referencing other services + * + * @param string $class + * @param string $method + * @param array $callTimeUserParams + * @param string $alias + * @param bool $methodIsRequired + * @param bool $isInstantiator + * @return array|bool + * @throws Zend\Di\Exception\MissingPropertyException + * @throws Zend\Di\Exception\CircularDependencyException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @todo Need to refactor this method + */ + protected function resolveMethodParameters($class, $method, array $callTimeUserParams, $alias, $methodIsRequired, + $isInstantiator = false + ) { + // parameters for this method, in proper order, to be returned + $resolvedParams = array(); + + // parameter requirements from the definition + $methodParameters = $this->definitions->getMethodParameters($class, $method); + + /** Magento */ + $callTimeParamNames = array_keys($callTimeUserParams); + $isPositional = false; + $parameterNames = array(); + + foreach ($methodParameters as $param) { + $parameterNames[] = $param[0]; + } + + foreach ($callTimeParamNames as $name) { + if (is_numeric($name)) { + $isPositional = true; + $callTimeUserParams[$parameterNames[$name]] = $callTimeUserParams[$name]; + } + } + + if (!$isPositional) { + if (count($callTimeUserParams) + && !isset($callTimeUserParams['data']) + ) { + if (in_array('data', $parameterNames)) { + $intersection = array_intersect($callTimeParamNames, $parameterNames); + if (!$intersection) { + $callTimeUserParams = array('data' => $callTimeUserParams); + } + } + } + } + + // computed parameters array + $computedParams = array( + 'value' => array(), + 'required' => array(), + 'optional' => array() + ); + + // retrieve instance configurations for all contexts + $iConfig = array(); + $aliases = $this->instanceManager->getAliases(); + + // for the alias in the dependency tree + if ($alias && $this->instanceManager->hasConfig($alias)) { + $iConfig['thisAlias'] = $this->instanceManager->getConfig($alias); + } + + // for the current class in the dependency tree + if ($this->instanceManager->hasConfig($class)) { + $iConfig['thisClass'] = $this->instanceManager->getConfig($class); + } + + // for the parent class, provided we are deeper than one node + if (isset($this->instanceContext[0])) { + list($requestedClass, $requestedAlias) = ($this->instanceContext[0][0] == 'NEW') + ? array($this->instanceContext[0][1], $this->instanceContext[0][2]) + : array($this->instanceContext[1][1], $this->instanceContext[1][2]); + } else { + $requestedClass = $requestedAlias = null; + } + + if ($requestedClass != $class && $this->instanceManager->hasConfig($requestedClass)) { + $iConfig['requestedClass'] = $this->instanceManager->getConfig($requestedClass); + if ($requestedAlias) { + $iConfig['requestedAlias'] = $this->instanceManager->getConfig($requestedAlias); + } + } + + // This is a 2 pass system for resolving parameters + // first pass will find the sources, the second pass will order them and resolve lookups if they exist + // MOST methods will only have a single parameters to resolve, so this should be fast + + foreach ($methodParameters as $fqParamPos => $info) { + list($name, $type, $isRequired) = $info; + + $fqParamName = substr_replace($fqParamPos, ':' . $info[0], strrpos($fqParamPos, ':')); + + // PRIORITY 1 - consult user provided parameters + if (isset($callTimeUserParams[$fqParamPos]) || isset($callTimeUserParams[$name])) { + + if (isset($callTimeUserParams[$fqParamPos])) { + $callTimeCurValue =& $callTimeUserParams[$fqParamPos]; + } elseif (isset($callTimeUserParams[$fqParamName])) { + $callTimeCurValue =& $callTimeUserParams[$fqParamName]; + } else { + $callTimeCurValue =& $callTimeUserParams[$name]; + } + + if ($type && is_string($callTimeCurValue)) { + if ($this->instanceManager->hasAlias($callTimeCurValue)) { + // was an alias provided? + $computedParams['required'][$fqParamPos] = array( + $callTimeUserParams[$name], + $this->instanceManager->getClassFromAlias($callTimeCurValue) + ); + } elseif ($this->definitions->hasClass($callTimeUserParams[$name])) { + // was a known class provided? + $computedParams['required'][$fqParamPos] = array( + $callTimeCurValue, + $callTimeCurValue + ); + } else { + // must be a value + $computedParams['value'][$fqParamPos] = $callTimeCurValue; + } + } else { + // int, float, null, object, etc + $computedParams['value'][$fqParamPos] = $callTimeCurValue; + } + unset($callTimeCurValue); + continue; + } + + // PRIORITY 2 -specific instance configuration (thisAlias) - this alias + // PRIORITY 3 -THEN specific instance configuration (thisClass) - this class + // PRIORITY 4 -THEN specific instance configuration (requestedAlias) - requested alias + // PRIORITY 5 -THEN specific instance configuration (requestedClass) - requested class + + foreach (array('thisAlias', 'thisClass', 'requestedAlias', 'requestedClass') as $thisIndex) { + // check the provided parameters config + if (isset($iConfig[$thisIndex]['parameters'][$fqParamPos]) + || isset($iConfig[$thisIndex]['parameters'][$fqParamName]) + || isset($iConfig[$thisIndex]['parameters'][$name])) { + + if (isset($iConfig[$thisIndex]['parameters'][$fqParamPos])) { + $iConfigCurValue =& $iConfig[$thisIndex]['parameters'][$fqParamPos]; + } elseif (isset($iConfig[$thisIndex]['parameters'][$fqParamName])) { + $iConfigCurValue =& $iConfig[$thisIndex]['parameters'][$fqParamName]; + } else { + $iConfigCurValue =& $iConfig[$thisIndex]['parameters'][$name]; + } + + if ($type === false && is_string($iConfigCurValue)) { + $computedParams['value'][$fqParamPos] = $iConfigCurValue; + } elseif (is_string($iConfigCurValue) + && isset($aliases[$iConfigCurValue])) { + $computedParams['required'][$fqParamPos] = array( + $iConfig[$thisIndex]['parameters'][$name], + $this->instanceManager->getClassFromAlias($iConfigCurValue) + ); + } elseif (is_string($iConfigCurValue) + && $this->definitions->hasClass($iConfigCurValue)) { + $computedParams['required'][$fqParamPos] = array( + $iConfigCurValue, + $iConfigCurValue + ); + } elseif (is_object($iConfigCurValue) + && $iConfigCurValue instanceof Closure + && $type !== 'Closure') { + $computedParams['value'][$fqParamPos] = $iConfigCurValue(); + } else { + $computedParams['value'][$fqParamPos] = $iConfigCurValue; + } + unset($iConfigCurValue); + continue 2; + } + + } + + // PRIORITY 6 - globally preferred implementations + + // next consult alias level preferred instances + if ($alias && $this->instanceManager->hasTypePreferences($alias)) { + $pInstances = $this->instanceManager->getTypePreferences($alias); + foreach ($pInstances as $pInstance) { + if (is_object($pInstance)) { + $computedParams['value'][$fqParamPos] = $pInstance; + continue 2; + } + $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? + $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; + if ($pInstanceClass === $type || $this->isSubclassOf($pInstanceClass, $type)) { + $computedParams['required'][$fqParamPos] = array($pInstance, $pInstanceClass); + continue 2; + } + } + } + + // next consult class level preferred instances + if ($type && $this->instanceManager->hasTypePreferences($type)) { + $pInstances = $this->instanceManager->getTypePreferences($type); + foreach ($pInstances as $pInstance) { + if (is_object($pInstance)) { + $computedParams['value'][$fqParamPos] = $pInstance; + continue 2; + } + $pInstanceClass = ($this->instanceManager->hasAlias($pInstance)) ? + $this->instanceManager->getClassFromAlias($pInstance) : $pInstance; + if ($pInstanceClass === $type || $this->isSubclassOf($pInstanceClass, $type)) { + $computedParams['required'][$fqParamPos] = array($pInstance, $pInstanceClass); + continue 2; + } + } + } + + if (!$isRequired) { + $computedParams['optional'][$fqParamPos] = true; + } + + if ($type && $isRequired && $methodIsRequired) { + $computedParams['required'][$fqParamPos] = array($type, $type); + } + + } + + $index = 0; + foreach ($methodParameters as $fqParamPos => $value) { + $name = $value[0]; + $defaultValue = $value[3]; + + if (isset($computedParams['value'][$fqParamPos])) { + + // if there is a value supplied, use it + $resolvedParams[$index] = $computedParams['value'][$fqParamPos]; + + } elseif (isset($computedParams['required'][$fqParamPos])) { + + // detect circular dependencies! (they can only happen in instantiators) + if ($isInstantiator + && in_array($computedParams['required'][$fqParamPos][1], $this->currentDependencies)) { + throw new Exception\CircularDependencyException( + "Circular dependency detected: $class depends on {$value[1]} and vice versa" + ); + } + array_push($this->currentDependencies, $class); + $dConfig = $this->instanceManager->getConfig($computedParams['required'][$fqParamPos][0]); + if ($dConfig['shared'] === false) { + $resolvedParams[$index] + = $this->newInstance($computedParams['required'][$fqParamPos][0], $callTimeUserParams, false); + } else { + $resolvedParams[$index] = $this->get($computedParams['required'][$fqParamPos][0]); + } + + array_pop($this->currentDependencies); + + } elseif (!array_key_exists($fqParamPos, $computedParams['optional'])) { + + if ($methodIsRequired) { + // if this item was not marked as optional, + // plus it cannot be resolve, and no value exist, bail out + throw new Exception\MissingPropertyException(sprintf( + 'Missing %s for parameter ' . $name . ' for ' . $class . '::' . $method, + (($value[0] === null) ? 'value' : 'instance/object' ) + )); + } else { + return false; + } + + } else { + $resolvedParams[$index] = $defaultValue; + } + + $index++; + } + + return $resolvedParams; // return ordered list of parameters + } +} diff --git a/lib/Magento/ObjectManager.php b/lib/Magento/ObjectManager.php index a5bc9bba473f23e28af47764ef8fdeed20b19cc8..9c92119acf5866a8e035dc020fde2defa073a61f 100644 --- a/lib/Magento/ObjectManager.php +++ b/lib/Magento/ObjectManager.php @@ -52,7 +52,51 @@ interface Magento_ObjectManager * * @abstract * @param string $areaCode - * @return mixed + * @return Magento_ObjectManager */ public function loadAreaConfiguration($areaCode = null); + + /** + * Add shared instance + * + * @param object $instance + * @param string $classOrAlias + * @return Magento_ObjectManager + */ + public function addSharedInstance($instance, $classOrAlias); + + /** + * Remove shared instance + * + * @param string $classOrAlias + * @return Magento_ObjectManager + */ + public function removeSharedInstance($classOrAlias); + + /** + * Check whether object manager has shared instance of given class (alias) + * + * @param string $classOrAlias + * @return bool + */ + public function hasSharedInstance($classOrAlias); + + /** + * Add alias + * + * @param string $alias + * @param string $class + * @param array $parameters + * @return Magento_ObjectManager + * @throws Zend\Di\Exception\InvalidArgumentException + */ + public function addAlias($alias, $class, array $parameters = array()); + + /** + * Get class name by alias + * + * @param string + * @return string|bool + */ + public function getClassFromAlias($alias); } diff --git a/lib/Magento/ObjectManager/Zend.php b/lib/Magento/ObjectManager/Zend.php index c7890092bba73249fac0d975a3e10b383c60192c..dac5cf332b1201c7c241a806953349d6749ae794 100644 --- a/lib/Magento/ObjectManager/Zend.php +++ b/lib/Magento/ObjectManager/Zend.php @@ -46,28 +46,23 @@ class Magento_ObjectManager_Zend implements Magento_ObjectManager /** * Dependency injection instance * - * @var Zend\Di\Di + * @var Magento_Di_Zend */ protected $_di; /** * @param string $definitionsFile - * @param Zend\Di\Di $diInstance + * @param Magento_Di $diInstance + * @param Magento_Di_InstanceManager $instanceManager */ - public function __construct($definitionsFile = null, Zend\Di\Di $diInstance = null) - { + public function __construct( + $definitionsFile = null, + Magento_Di $diInstance = null, + Magento_Di_InstanceManager $instanceManager = null + ) { Magento_Profiler::start('di'); - if (is_file($definitionsFile) && is_readable($definitionsFile)) { - $definition = new Magento_Di_Definition_ArrayDefinition_Zend( - unserialize(file_get_contents($definitionsFile)) - ); - } else { - $definition = new Magento_Di_Definition_RuntimeDefinition_Zend(); - } - - $this->_di = $diInstance ? $diInstance : new Magento_Di(); - $this->_di->setDefinitionList(new Magento_Di_DefinitionList_Zend($definition)); + $this->_di = $diInstance ?: new Magento_Di_Zend(null, $instanceManager, null, $definitionsFile); $this->_di->instanceManager()->addSharedInstance($this, 'Magento_ObjectManager'); Magento_Profiler::stop('di'); @@ -84,6 +79,7 @@ class Magento_ObjectManager_Zend implements Magento_ObjectManager public function create($className, array $arguments = array(), $isShared = true) { $object = $this->_di->newInstance($className, $arguments, $isShared); + return $object; } @@ -97,6 +93,7 @@ class Magento_ObjectManager_Zend implements Magento_ObjectManager public function get($className, array $arguments = array()) { $object = $this->_di->get($className, $arguments); + return $object; } @@ -114,11 +111,82 @@ class Magento_ObjectManager_Zend implements Magento_ObjectManager /** @var $magentoConfiguration Mage_Core_Model_Config */ $magentoConfiguration = $this->get('Mage_Core_Model_Config'); - $node = $magentoConfiguration->getNode($areaCode . '/' . self::CONFIGURATION_DI_NODE); + $node = $magentoConfiguration->getNode($areaCode . '/' . self::CONFIGURATION_DI_NODE); if ($node) { $diConfiguration = new Config(array('instance' => $node->asArray())); $diConfiguration->configure($this->_di); } + return $this; } + + /** + * Add shared instance + * + * @param object $instance + * @param string $classOrAlias + * @return Magento_ObjectManager_Zend + */ + public function addSharedInstance($instance, $classOrAlias) + { + $this->_di->instanceManager()->addSharedInstance($instance, $classOrAlias); + + return $this; + } + + /** + * Remove shared instance + * + * @param string $classOrAlias + * @return Magento_ObjectManager_Zend + */ + public function removeSharedInstance($classOrAlias) + { + /** @var $instanceManager Magento_Di_InstanceManager_Zend */ + $instanceManager = $this->_di->instanceManager(); + $instanceManager->removeSharedInstance($classOrAlias); + + return $this; + } + + /** + * Check whether instance manager has shared instance of given class (alias) + * + * @param string $classOrAlias + * @return bool + */ + public function hasSharedInstance($classOrAlias) + { + /** @var $instanceManager Magento_Di_InstanceManager_Zend */ + $instanceManager = $this->_di->instanceManager(); + return $instanceManager->hasSharedInstance($classOrAlias); + } + + /** + * Add alias + * + * @param string $alias + * @param string $class + * @param array $parameters + * @return Magento_ObjectManager_Zend + * @throws Zend\Di\Exception\InvalidArgumentException + */ + public function addAlias($alias, $class, array $parameters = array()) + { + $this->_di->instanceManager()->addAlias($alias, $class, $parameters); + + return $this; + } + + /** + * Get class name by alias + * + * @param string + * @return string|bool + * @throws Zend\Di\Exception\RuntimeException + */ + public function getClassFromAlias($alias) + { + return $this->_di->instanceManager()->getClassFromAlias($alias); + } } diff --git a/lib/Varien/File/Uploader.php b/lib/Varien/File/Uploader.php index 1fb95f236c924a2014672550534d72cc73ac9378..17119d9fbcb26bfd845a8531224f3ebaf81c966a 100644 --- a/lib/Varien/File/Uploader.php +++ b/lib/Varien/File/Uploader.php @@ -79,8 +79,8 @@ class Varien_File_Uploader protected $_uploadedFileDir; /** - * If this variable is set to TRUE, our library will be able to automaticaly create - * non-existant directories. + * If this variable is set to TRUE, our library will be able to automatically create + * non-existent directories. * * @var bool * @access protected @@ -97,7 +97,7 @@ class Varien_File_Uploader protected $_allowRenameFiles = false; /** - * If this variable is set to TRUE, files despersion will be supported. + * If this variable is set to TRUE, files dispertion will be supported. * * @var bool * @access protected @@ -120,8 +120,14 @@ class Varien_File_Uploader */ protected $_dispretionPath = null; + /** + * @var bool + */ protected $_fileExists = false; + /** + * @var null|array + */ protected $_allowedExtensions = null; /** @@ -132,8 +138,16 @@ class Varien_File_Uploader */ protected $_validateCallbacks = array(); + /**#@+ + * File upload type (multiple or single) + */ const SINGLE_STYLE = 0; const MULTIPLE_STYLE = 1; + /**#@-*/ + + /** + * Temp file name empty code + */ const TMP_NAME_EMPTY = 666; /** @@ -154,10 +168,16 @@ class Varien_File_Uploader */ protected $_result; - function __construct($fileId) + /** + * Init upload + * + * @param string $fileId + * @throws Exception + */ + public function __construct($fileId) { $this->_setUploadFileId($fileId); - if(!file_exists($this->_file['tmp_name'])) { + if (!file_exists($this->_file['tmp_name'])) { $code = empty($this->_file['tmp_name']) ? self::TMP_NAME_EMPTY : 0; throw new Exception('File was not uploaded.', $code); } else { @@ -182,8 +202,8 @@ class Varien_File_Uploader * * @param string $destinationFolder * @param string $newFileName - * @access public - * @return void|bool + * @return bool + * @throws Exception */ public function save($destinationFolder, $newFileName = null) { @@ -251,7 +271,7 @@ class Varien_File_Uploader /** * Validate file before save * - * @access public + * @throws Exception */ protected function _validateFile() { @@ -345,10 +365,16 @@ class Varien_File_Uploader return $fileName; } + /** + * Add directory separator + * + * @param string $dir + * @return string + */ static protected function _addDirSeparator($dir) { - if (substr($dir,-1) != DIRECTORY_SEPARATOR) { - $dir.= DIRECTORY_SEPARATOR; + if (substr($dir, -1) != DIRECTORY_SEPARATOR) { + $dir .= DIRECTORY_SEPARATOR; } return $dir; } @@ -360,7 +386,7 @@ class Varien_File_Uploader * @access public * @return bool */ - public function checkMimeType($validTypes=Array()) + public function checkMimeType($validTypes = array()) { if (count($validTypes) > 0) { if (!in_array($this->_getMimeType(), $validTypes)) { @@ -421,7 +447,7 @@ class Varien_File_Uploader } /** - * Filenames Case-sensitivity setter + * File names Case-sensitivity setter * * @param mixed $flag * @return Varien_File_Uploader @@ -432,6 +458,12 @@ class Varien_File_Uploader return $this; } + /** + * Set allowed extensions + * + * @param array $extensions + * @return Varien_File_Uploader + */ public function setAllowedExtensions($extensions = array()) { foreach ((array)$extensions as $extension) { @@ -460,6 +492,12 @@ class Varien_File_Uploader return $this->_file['type']; } + /** + * Set upload field id + * + * @param string $fileId + * @throws Exception + */ private function _setUploadFileId($fileId) { if (empty($_FILES)) { @@ -477,23 +515,30 @@ class Varien_File_Uploader $this->_uploadType = self::MULTIPLE_STYLE; $fileAttributes = $_FILES[$file[0]]; - $tmp_var = array(); + $tmpVar = array(); foreach ($fileAttributes as $attributeName => $attributeValue) { - $tmp_var[$attributeName] = $attributeValue[$file[1]]; + $tmpVar[$attributeName] = $attributeValue[$file[1]]; } - $fileAttributes = $tmp_var; + $fileAttributes = $tmpVar; $this->_file = $fileAttributes; - } elseif( count($fileId) > 0 && isset($_FILES[$fileId])) { + } elseif (count($fileId) > 0 && isset($_FILES[$fileId])) { $this->_uploadType = self::SINGLE_STYLE; $this->_file = $_FILES[$fileId]; - } elseif( $fileId == '' ) { + } elseif ($fileId == '') { throw new Exception('Invalid parameter given. A valid $_FILES[] identifier is expected.'); } } } + /** + * Create destination folder + * + * @param string $destinationFolder + * @return Varien_File_Uploader + * @throws Exception + */ private function _createDestinationFolder($destinationFolder) { if (!$destinationFolder) { @@ -510,15 +555,21 @@ class Varien_File_Uploader return $this; } - static public function getNewFileName($destFile) + /** + * Get new file name if the same is already exists + * + * @param string $destinationFile + * @return string + */ + static public function getNewFileName($destinationFile) { - $fileInfo = pathinfo($destFile); - if (file_exists($destFile)) { + $fileInfo = pathinfo($destinationFile); + if (file_exists($destinationFile)) { $index = 1; $baseName = $fileInfo['filename'] . '.' . $fileInfo['extension']; - while( file_exists($fileInfo['dirname'] . DIRECTORY_SEPARATOR . $baseName) ) { - $baseName = $fileInfo['filename']. '_' . $index . '.' . $fileInfo['extension']; - $index ++; + while (file_exists($fileInfo['dirname'] . DIRECTORY_SEPARATOR . $baseName)) { + $baseName = $fileInfo['filename'] . '_' . $index . '.' . $fileInfo['extension']; + $index++; } $destFileName = $baseName; } else { @@ -528,20 +579,26 @@ class Varien_File_Uploader return $destFileName; } + /** + * Get dispertion path + * + * @param string $fileName + * @return string + */ static public function getDispretionPath($fileName) { $char = 0; - $dispretionPath = ''; + $dispertionPath = ''; while (($char < 2) && ($char < strlen($fileName))) { - if (empty($dispretionPath)) { - $dispretionPath = DIRECTORY_SEPARATOR + if (empty($dispertionPath)) { + $dispertionPath = DIRECTORY_SEPARATOR . ('.' == $fileName[$char] ? '_' : $fileName[$char]); } else { - $dispretionPath = self::_addDirSeparator($dispretionPath) + $dispertionPath = self::_addDirSeparator($dispertionPath) . ('.' == $fileName[$char] ? '_' : $fileName[$char]); } $char ++; } - return $dispretionPath; + return $dispertionPath; } } diff --git a/lib/Varien/Io/File.php b/lib/Varien/Io/File.php index 635b316e19d4707ba742672874faa1e515bce71d..d911dc23560255eebf4dd385ceac2f21252e168c 100644 --- a/lib/Varien/Io/File.php +++ b/lib/Varien/Io/File.php @@ -61,8 +61,8 @@ class Varien_Io_File extends Varien_Io_Abstract const GREP_DIRS = 'dirs_only'; /** - * If this variable is set to TRUE, our library will be able to automaticaly create - * non-existant directories. + * If this variable is set to TRUE, our library will be able to automatically create + * non-existent directories. * * @var bool * @access protected @@ -113,7 +113,9 @@ class Varien_Io_File extends Varien_Io_Abstract * * @param string $fileName * @param string $mode + * @param int $chmod * @return bool + * @throws Exception */ public function streamOpen($fileName, $mode = 'w+', $chmod = 0666) { @@ -141,6 +143,7 @@ class Varien_Io_File extends Varien_Io_Abstract /** * Lock file * + * @param bool $exclusive * @return bool */ public function streamLock($exclusive = true) @@ -187,6 +190,8 @@ class Varien_Io_File extends Varien_Io_Abstract /** * Gets line from file pointer and parse for CSV fields * + * @param string $delimiter + * @param string $enclosure * @return string */ public function streamReadCsv($delimiter = ',', $enclosure = '"') @@ -285,11 +290,11 @@ class Varien_Io_File extends Varien_Io_Abstract * @param array $args * @return boolean */ - public function open(array $args=array()) + public function open(array $args = array()) { if (!empty($args['path'])) { if ($args['path']) { - if($this->_allowCreateFolders ) { + if ($this->_allowCreateFolders) { $this->_createDestinationFolder($args['path']); } } @@ -331,7 +336,7 @@ class Varien_Io_File extends Varien_Io_Abstract * @param boolean $recursive * @return boolean */ - public function mkdir($dir, $mode=0777, $recursive=true) + public function mkdir($dir, $mode = 0777, $recursive = true) { $this->_cwd(); $result = @mkdir($dir, $mode, $recursive); @@ -343,6 +348,7 @@ class Varien_Io_File extends Varien_Io_Abstract * Delete a directory * * @param string $dir + * @param bool $recursive * @return boolean */ public function rmdir($dir, $recursive = false) @@ -434,7 +440,7 @@ class Varien_Io_File extends Varien_Io_Abstract */ public function cd($dir) { - if(is_dir($dir)) { + if (is_dir($dir)) { $this->_iwd(); $this->_cwd = realpath($dir); return true; @@ -453,7 +459,7 @@ class Varien_Io_File extends Varien_Io_Abstract * @param string|resource $dest * @return boolean|string */ - public function read($filename, $dest=null) + public function read($filename, $dest = null) { $this->_cwd(); if (!is_null($dest)) { @@ -474,7 +480,7 @@ class Varien_Io_File extends Varien_Io_Abstract * @param int $mode * @return int|boolean */ - public function write($filename, $src, $mode=null) + public function write($filename, $src, $mode = null) { if (is_string($src) && is_readable($src)) { $src = realpath($src); @@ -509,6 +515,13 @@ class Varien_Io_File extends Varien_Io_Abstract return $result; } + /** + * Is file exists + * + * @param string $file + * @param bool $onlyFile + * @return bool + */ public function fileExists($file, $onlyFile = true) { $this->_cwd(); @@ -520,6 +533,12 @@ class Varien_Io_File extends Varien_Io_Abstract return $result; } + /** + * Tells whether the filename is writable + * + * @param string $path + * @return bool + */ public function isWriteable($path) { $this->_cwd(); @@ -528,11 +547,17 @@ class Varien_Io_File extends Varien_Io_Abstract return $result; } - public function getDestinationFolder($filepath) + /** + * Get destination folder + * + * @param string $filePath + * @return bool + */ + public function getDestinationFolder($filePath) { - preg_match('/^(.*[!\/])/', $filepath, $mathces); - if (isset($mathces[0])) { - return $mathces[0]; + preg_match('/^(.*[!\/])/', $filePath, $matches); + if (isset($matches[0])) { + return $matches[0]; } return false; } @@ -557,6 +582,7 @@ class Varien_Io_File extends Varien_Io_Abstract * @param string $folder * @param int $mode * @return bool + * @throws Exception */ public function checkAndCreateFolder($folder, $mode = 0777) { @@ -572,10 +598,17 @@ class Varien_Io_File extends Varien_Io_Abstract return true; } + /** + * Create destination folder + * + * @param string $destinationFolder + * @return bool + */ private function _createDestinationFolder($destinationFolder) { return $this->checkAndCreateFolder($destinationFolder); } + /** * Delete a file * @@ -594,13 +627,13 @@ class Varien_Io_File extends Varien_Io_Abstract * Rename or move a directory or a file * * @param string $src - * @param string $dest + * @param string $destination * @return boolean */ - public function mv($src, $dest) + public function mv($src, $destination) { $this->_cwd(); - $result = @rename($src, $dest); + $result = @rename($src, $destination); $this->_iwd(); return $result; } @@ -609,13 +642,13 @@ class Varien_Io_File extends Varien_Io_Abstract * Copy a file * * @param string $src - * @param string $dest + * @param string $destination * @return boolean */ - public function cp($src, $dest) + public function cp($src, $destination) { $this->_cwd(); - $result = @copy($src, $dest); + $result = @copy($src, $destination); $this->_iwd(); return $result; } @@ -664,16 +697,16 @@ class Varien_Io_File extends Varien_Io_Abstract * - LS_ALL = 3 * * @param Varien_Io_File const - * @access public * @return array + * @throws Exception */ - public function ls($grep=null) + public function ls($grep = null) { $ignoredDirectories = Array('.', '..'); - if( is_dir($this->_cwd) ) { + if ( is_dir($this->_cwd)) { $dir = $this->_cwd; - } elseif( is_dir($this->_iwd) ) { + } elseif (is_dir($this->_iwd)) { $dir = $this->_iwd; } else { throw new Exception('Unable to list current working directory.'); @@ -681,50 +714,54 @@ class Varien_Io_File extends Varien_Io_Abstract $list = Array(); - if ($dh = opendir($dir)) { - while (($entry = readdir($dh)) !== false) { - $list_item = Array(); + $dirHandler = opendir($dir); + if ($dirHandler) { + while (($entry = readdir($dirHandler)) !== false) { + $listItem = Array(); - $fullpath = $dir . DIRECTORY_SEPARATOR . $entry; + $fullPath = $dir . DIRECTORY_SEPARATOR . $entry; - if( ($grep == self::GREP_DIRS) && (!is_dir($fullpath)) ) { + if (($grep == self::GREP_DIRS) && (!is_dir($fullPath))) { continue; - } elseif( ($grep == self::GREP_FILES) && (!is_file($fullpath)) ) { + } elseif (($grep == self::GREP_FILES) && (!is_file($fullPath))) { continue; - } elseif( in_array($entry, $ignoredDirectories) ) { + } elseif (in_array($entry, $ignoredDirectories)) { continue; } - $list_item['text'] = $entry; - $list_item['mod_date'] = date ('Y-m-d H:i:s', filectime($fullpath)); - $list_item['permissions'] = $this->_parsePermissions(fileperms($fullpath)); - $list_item['owner'] = $this->_getFileOwner($fullpath); - - if( is_file($fullpath) ) { - $pathinfo = pathinfo($fullpath); - $list_item['size'] = filesize($fullpath); - $list_item['leaf'] = true; - if( isset($pathinfo['extension']) && in_array(strtolower($pathinfo['extension']), Array('jpg', 'jpeg', 'gif', 'bmp', 'png')) && $list_item['size'] > 0 ) { - $list_item['is_image'] = true; - $list_item['filetype'] = $pathinfo['extension']; - } elseif( $list_item['size'] == 0 ) { - $list_item['is_image'] = false; - $list_item['filetype'] = 'unknown'; - } elseif( isset($pathinfo['extension']) ) { - $list_item['is_image'] = false; - $list_item['filetype'] = $pathinfo['extension']; + $listItem['text'] = $entry; + $listItem['mod_date'] = date ('Y-m-d H:i:s', filectime($fullPath)); + $listItem['permissions'] = $this->_parsePermissions(fileperms($fullPath)); + $listItem['owner'] = $this->_getFileOwner($fullPath); + + if (is_file($fullPath)) { + $pathInfo = pathinfo($fullPath); + $listItem['size'] = filesize($fullPath); + $listItem['leaf'] = true; + if (isset($pathInfo['extension']) + && in_array(strtolower($pathInfo['extension']), array('jpg', 'jpeg', 'gif', 'bmp', 'png')) + && $listItem['size'] > 0 + ) { + $listItem['is_image'] = true; + $listItem['filetype'] = $pathInfo['extension']; + } elseif ($listItem['size'] == 0) { + $listItem['is_image'] = false; + $listItem['filetype'] = 'unknown'; + } elseif (isset($pathInfo['extension'])) { + $listItem['is_image'] = false; + $listItem['filetype'] = $pathInfo['extension']; } else { - $list_item['is_image'] = false; - $list_item['filetype'] = 'unknown'; + $listItem['is_image'] = false; + $listItem['filetype'] = 'unknown'; } } else { - $list_item['leaf'] = false; - $list_item['id'] = $fullpath; + $listItem['leaf'] = false; + $listItem['id'] = $fullPath; } - $list[] = $list_item; + $list[] = $listItem; } - closedir($dh); + closedir($dirHandler); } else { throw new Exception('Unable to list current working directory. Access forbidden.'); } @@ -761,22 +798,23 @@ class Varien_Io_File extends Varien_Io_Abstract */ protected function _parsePermissions($mode) { - if( $mode & 0x1000 ) - $type='p'; /* FIFO pipe */ - else if( $mode & 0x2000 ) - $type='c'; /* Character special */ - else if( $mode & 0x4000 ) - $type='d'; /* Directory */ - else if( $mode & 0x6000 ) - $type='b'; /* Block special */ - else if( $mode & 0x8000 ) - $type='-'; /* Regular */ - else if( $mode & 0xA000 ) - $type='l'; /* Symbolic Link */ - else if( $mode & 0xC000 ) - $type='s'; /* Socket */ - else - $type='u'; /* UNKNOWN */ + if ($mode & 0x1000) { + $type = 'p'; /* FIFO pipe */ + } elseif ($mode & 0x2000) { + $type = 'c'; /* Character special */ + } elseif ($mode & 0x4000) { + $type = 'd'; /* Directory */ + } elseif ($mode & 0x6000) { + $type = 'b'; /* Block special */ + } elseif ($mode & 0x8000) { + $type = '-'; /* Regular */ + } elseif ($mode & 0xA000) { + $type = 'l'; /* Symbolic Link */ + } elseif ($mode & 0xC000) { + $type = 's'; /* Socket */ + } else { + $type = 'u'; /* UNKNOWN */ + } /* Determine permissions */ $owner['read'] = ($mode & 00400) ? 'r' : '-'; @@ -790,17 +828,20 @@ class Varien_Io_File extends Varien_Io_Abstract $world['execute'] = ($mode & 00001) ? 'x' : '-'; /* Adjust for SUID, SGID and sticky bit */ - if( $mode & 0x800 ) - $owner["execute"] = ($owner['execute']=='x') ? 's' : 'S'; - if( $mode & 0x400 ) - $group["execute"] = ($group['execute']=='x') ? 's' : 'S'; - if( $mode & 0x200 ) - $world["execute"] = ($world['execute']=='x') ? 't' : 'T'; - - $s=sprintf('%1s', $type); - $s.=sprintf('%1s%1s%1s', $owner['read'], $owner['write'], $owner['execute']); - $s.=sprintf('%1s%1s%1s', $group['read'], $group['write'], $group['execute']); - $s.=sprintf('%1s%1s%1s', $world['read'], $world['write'], $world['execute']); + if ($mode & 0x800) { + $owner["execute"] = ($owner['execute'] == 'x') ? 's' : 'S'; + } + if ($mode & 0x400) { + $group["execute"] = ($group['execute'] == 'x') ? 's' : 'S'; + } + if ($mode & 0x200) { + $world["execute"] = ($world['execute'] == 'x') ? 't' : 'T'; + } + + $s = sprintf('%1s', $type); + $s .= sprintf('%1s%1s%1s', $owner['read'], $owner['write'], $owner['execute']); + $s .= sprintf('%1s%1s%1s', $group['read'], $group['write'], $group['execute']); + $s .= sprintf('%1s%1s%1s', $world['read'], $world['write'], $world['execute']); return trim($s); } @@ -808,26 +849,36 @@ class Varien_Io_File extends Varien_Io_Abstract * Get file owner * * @param string $filename - * @access protected * @return string */ protected function _getFileOwner($filename) { - if( !function_exists('posix_getpwuid') ) { + if (!function_exists('posix_getpwuid')) { return 'n/a'; } $owner = posix_getpwuid(fileowner($filename)); - $groupinfo = posix_getgrnam(filegroup($filename)); + $groupInfo = posix_getgrnam(filegroup($filename)); - return $owner['name'] . ' / ' . $groupinfo; + return $owner['name'] . ' / ' . $groupInfo; } + /** + * Get directory separator + * + * @return string + */ public function dirsep() { return DIRECTORY_SEPARATOR; } + /** + * Get directory name + * + * @param string $file + * @return string + */ public function dirname($file) { return $this->getCleanPath(dirname($file)); diff --git a/pub/lib/jquery/jquery-ui-1.9.2.custom.min.js b/pub/lib/jquery/jquery-ui-1.9.2.custom.min.js new file mode 100644 index 0000000000000000000000000000000000000000..9ec6b4b94018d1dca133f806b4480453f9ddadba --- /dev/null +++ b/pub/lib/jquery/jquery-ui-1.9.2.custom.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.9.2 - 2012-11-26 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.sortable.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.slider.js, jquery.ui.tabs.js, jquery.ui.effect.js +* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.9.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),function(){var t=/msie ([\w.]+)/.exec(navigator.userAgent.toLowerCase())||[];e.ui.ie=t.length?!0:!1,e.ui.ie6=parseFloat(t[1],10)===6}(),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r<i.length;r++)e.options[i[r][0]]&&i[r][1].apply(e.element,n)}},contains:e.contains,hasScroll:function(t,n){if(e(t).css("overflow")==="hidden")return!1;var r=n&&n==="left"?"scrollLeft":"scrollTop",i=!1;return t[r]>0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e<t+n},isOver:function(t,n,r,i,s,o){return e.ui.isOverAxis(t,r,s)&&e.ui.isOverAxis(n,i,o)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a=t.split(".")[0];t=t.split(".")[1],i=a+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[a]=e[a]||{},s=e[a][t],o=e[a][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,i){e.isFunction(i)&&(r[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},r=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=r,s=i.apply(this,arguments),this._super=t,this._superApply=n,s}}())}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},r,{constructor:o,namespace:a,widgetName:t,widgetBaseClass:i,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s<o;s++)for(u in i[s])a=i[s][u],i[s].hasOwnProperty(u)&&a!==t&&(e.isPlainObject(a)?n[u]=e.isPlainObject(n[u])?e.widget.extend({},n[u],a):e.widget.extend({},a):n[u]=a);return n},e.widget.bridge=function(n,i){var s=i.prototype.widgetFullName||n;e.fn[n]=function(o){var u=typeof o=="string",a=r.call(arguments,1),f=this;return o=!u&&a.length?e.widget.extend.apply(null,[o].concat(a)):o,u?this.each(function(){var r,i=e.data(this,s);if(!i)return e.error("cannot call methods on "+n+" prior to initialization; "+"attempted to call method '"+o+"'");if(!e.isFunction(i[o])||o.charAt(0)==="_")return e.error("no such method '"+o+"' for "+n+" widget instance");r=i[o].apply(i,a);if(r!==i&&r!==t)return f=r&&r.jquery?f.pushStack(r.get()):r,!1}):this.each(function(){var t=e.data(this,s);t?t.option(o||{})._init():e.data(this,s,new i(o,this))}),f}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u<s.length-1;u++)o[s[u]]=o[s[u]]||{},o=o[s[u]];n=s.pop();if(r===t)return o[n]===t?null:o[n];o[n]=r}else{if(r===t)return this.options[n]===t?null:this.options[n];i[n]=r}}return this._setOptions(i),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,e==="disabled"&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(t,n,r){var i,s=this;typeof t!="boolean"&&(r=n,n=t,t=!1),r?(n=i=e(n),this.bindings=this.bindings.add(n)):(r=n,n=this.element,i=this.widget()),e.each(r,function(r,o){function u(){if(!t&&(s.options.disabled===!0||e(this).hasClass("ui-state-disabled")))return;return(typeof o=="string"?s[o]:o).apply(s,arguments)}typeof o!="string"&&(u.guid=o.guid=o.guid||u.guid||e.guid++);var a=r.match(/^(\w+)\s*(.*)$/),f=a[1]+s.eventNamespace,l=a[2];l?i.delegate(l,f,u):n.bind(f,u)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function n(){return(typeof e=="string"?r[e]:e).apply(r,arguments)}var r=this;return setTimeout(n,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,n,r){var i,s,o=this.options[t];r=r||{},n=e.Event(n),n.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),n.target=this.element[0],s=n.originalEvent;if(s)for(i in s)i in n||(n[i]=s[i]);return this.element.trigger(n,r),!(e.isFunction(o)&&o.apply(this.element[0],[n].concat(r))===!1||n.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,n){e.Widget.prototype["_"+t]=function(r,i,s){typeof i=="string"&&(i={effect:i});var o,u=i?i===!0||typeof i=="number"?n:i.effect||n:t;i=i||{},typeof i=="number"&&(i={duration:i}),o=!e.isEmptyObject(i),i.complete=s,i.delay&&r.delay(i.delay),o&&e.effects&&(e.effects.effect[u]||e.uiBackCompat!==!1&&e.effects[u])?r[t](i):u!==t&&r[u]?r[u](i.duration,i.easing,s):r.queue(function(n){e(this)[t](),s&&s.call(r[0]),n()})}}),e.uiBackCompat!==!1&&(e.Widget.prototype._getCreateOptions=function(){return e.metadata&&e.metadata.get(this.element[0])[this.widgetName]})})(jQuery);(function(e,t){var n=!1;e(document).mouseup(function(e){n=!1}),e.widget("ui.mouse",{version:"1.9.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(n){if(!0===e.data(n.target,t.widgetName+".preventClickEvent"))return e.removeData(n.target,t.widgetName+".preventClickEvent"),n.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(n)return;this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var r=this,i=t.which===1,s=typeof this.options.cancel=="string"&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;if(!i||s||!this._mouseCapture(t))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){r.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)){this._mouseStarted=this._mouseStart(t)!==!1;if(!this._mouseStarted)return t.preventDefault(),!0}return!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return r._mouseMove(e)},this._mouseUpDelegate=function(e){return r._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0},_mouseMove:function(t){return!e.ui.ie||document.documentMode>=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width<t.element[0].scrollWidth,s=r==="scroll"||r==="auto"&&t.height<t.element[0].scrollHeight;return{width:i?e.position.scrollbarWidth():0,height:s?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var n=e(t||window),r=e.isWindow(n[0]);return{element:n,isWindow:r,offset:n.offset()||{left:0,top:0},scrollLeft:n.scrollLeft(),scrollTop:n.scrollTop(),width:r?n.width():n.outerWidth(),height:r?n.height():n.outerHeight()}}},e.fn.position=function(t){if(!t||!t.of)return c.apply(this,arguments);t=e.extend({},t);var n,l,d,v,m,g=e(t.of),y=e.position.getWithinInfo(t.within),b=e.position.getScrollInfo(y),w=g[0],E=(t.collision||"flip").split(" "),S={};return w.nodeType===9?(l=g.width(),d=g.height(),v={top:0,left:0}):e.isWindow(w)?(l=g.width(),d=g.height(),v={top:g.scrollTop(),left:g.scrollLeft()}):w.preventDefault?(t.at="left top",l=d=0,v={top:w.pageY,left:w.pageX}):(l=g.outerWidth(),d=g.outerHeight(),v=g.offset()),m=e.extend({},v),e.each(["my","at"],function(){var e=(t[this]||"").split(" "),n,r;e.length===1&&(e=o.test(e[0])?e.concat(["center"]):u.test(e[0])?["center"].concat(e):["center","center"]),e[0]=o.test(e[0])?e[0]:"center",e[1]=u.test(e[1])?e[1]:"center",n=a.exec(e[0]),r=a.exec(e[1]),S[this]=[n?n[0]:0,r?r[0]:0],t[this]=[f.exec(e[0])[0],f.exec(e[1])[0]]}),E.length===1&&(E[1]=E[0]),t.at[0]==="right"?m.left+=l:t.at[0]==="center"&&(m.left+=l/2),t.at[1]==="bottom"?m.top+=d:t.at[1]==="center"&&(m.top+=d/2),n=h(S.at,l,d),m.left+=n[0],m.top+=n[1],this.each(function(){var o,u,a=e(this),f=a.outerWidth(),c=a.outerHeight(),w=p(this,"marginLeft"),x=p(this,"marginTop"),T=f+w+p(this,"marginRight")+b.width,N=c+x+p(this,"marginBottom")+b.height,C=e.extend({},m),k=h(S.my,a.outerWidth(),a.outerHeight());t.my[0]==="right"?C.left-=f:t.my[0]==="center"&&(C.left-=f/2),t.my[1]==="bottom"?C.top-=c:t.my[1]==="center"&&(C.top-=c/2),C.left+=k[0],C.top+=k[1],e.support.offsetFractions||(C.left=s(C.left),C.top=s(C.top)),o={marginLeft:w,marginTop:x},e.each(["left","top"],function(r,i){e.ui.position[E[r]]&&e.ui.position[E[r]][i](C,{targetWidth:l,targetHeight:d,elemWidth:f,elemHeight:c,collisionPosition:o,collisionWidth:T,collisionHeight:N,offset:[n[0]+k[0],n[1]+k[1]],my:t.my,at:t.at,within:y,elem:a})}),e.fn.bgiframe&&a.bgiframe(),t.using&&(u=function(e){var n=v.left-C.left,s=n+l-f,o=v.top-C.top,u=o+d-c,h={target:{element:g,left:v.left,top:v.top,width:l,height:d},element:{element:a,left:C.left,top:C.top,width:f,height:c},horizontal:s<0?"left":n>0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};l<f&&i(n+s)<l&&(h.horizontal="center"),d<c&&i(o+u)<d&&(h.vertical="middle"),r(i(n),i(s))>r(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p<i(a))e.left+=l+c+h}else if(f>0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)<f)e.left+=l+c+h}},top:function(e,t){var n=t.within,r=n.offset.top+n.scrollTop,s=n.height,o=n.isWindow?n.scrollTop:n.offset.top,u=e.top-t.collisionPosition.marginTop,a=u-o,f=u+t.collisionHeight-s-o,l=t.my[1]==="top",c=l?-t.elemHeight:t.my[1]==="bottom"?t.elemHeight:0,h=t.at[1]==="top"?t.targetHeight:t.at[1]==="bottom"?-t.targetHeight:0,p=-2*t.offset[1],d,v;a<0?(v=e.top+c+h+p+t.collisionHeight-s-r,e.top+c+h+p>a&&(v<0||v<i(a))&&(e.top+=c+h+p)):f>0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)<f)&&(e.top+=c+h+p))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,n,r,i,s,o=document.getElementsByTagName("body")[0],u=document.createElement("div");t=document.createElement(o?"div":"body"),r={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(r,{position:"absolute",left:"-1000px",top:"-1000px"});for(s in r)t.style[s]=r[s];t.appendChild(u),n=o||document.documentElement,n.insertBefore(t,n.firstChild),u.style.cssText="position: absolute; left: 10.7432222px;",i=e(u).offset().left,e.support.offsetFractions=i>10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var n=this.options;return this.helper||n.disabled||e(t.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.left<u[0]&&(s=u[0]+this.offset.click.left),t.pageY-this.offset.click.top<u[1]&&(o=u[1]+this.offset.click.top),t.pageX-this.offset.click.left>u[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.top<u[1]||f-this.offset.click.top>u[3]?f-this.offset.click.top<u[1]?f+n.grid[1]:f-n.grid[1]:f:f;var l=n.grid[0]?this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0]:this.originalPageX;s=u?l-this.offset.click.left<u[0]||l-this.offset.click.left>u[2]?l-this.offset.click.left<u[0]?l+n.grid[0]:l-n.grid[0]:l:l}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(e){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("draggable"),i=this,s=function(t){var n=this.offset.click.top,r=this.offset.click.left,i=this.positionAbs.top,s=this.positionAbs.left,o=t.height,u=t.width,a=t.top,f=t.left;return e.ui.isOver(i+n,s+r,a,f,o,u)};e.each(r.sortables,function(s){var o=!1,u=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(o=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!=u&&this.instance._intersectsWith(this.instance.containerCache)&&e.ui.contains(u.instance.element[0],this.instance.element[0])&&(o=!1),o})),o?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,n){var r=e("body"),i=e(this).data("draggable").options;r.css("cursor")&&(i._cursor=r.css("cursor")),r.css("cursor",i.cursor)},stop:function(t,n){var r=e(this).data("draggable").options;r._cursor&&e("body").css("cursor",r._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(t,n){var r=e(this).data("draggable");r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"&&(r.overflowOffset=r.scrollParent.offset())},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=!1;if(r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"){if(!i.axis||i.axis!="x")r.overflowOffset.top+r.scrollParent[0].offsetHeight-t.pageY<i.scrollSensitivity?r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop+i.scrollSpeed:t.pageY-r.overflowOffset.top<i.scrollSensitivity&&(r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop-i.scrollSpeed);if(!i.axis||i.axis!="y")r.overflowOffset.left+r.scrollParent[0].offsetWidth-t.pageX<i.scrollSensitivity?r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft+i.scrollSpeed:t.pageX-r.overflowOffset.left<i.scrollSensitivity&&(r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft-i.scrollSpeed)}else{if(!i.axis||i.axis!="x")t.pageY-e(document).scrollTop()<i.scrollSensitivity?s=e(document).scrollTop(e(document).scrollTop()-i.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<i.scrollSensitivity&&(s=e(document).scrollTop(e(document).scrollTop()+i.scrollSpeed));if(!i.axis||i.axis!="y")t.pageX-e(document).scrollLeft()<i.scrollSensitivity?s=e(document).scrollLeft(e(document).scrollLeft()-i.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<i.scrollSensitivity&&(s=e(document).scrollLeft(e(document).scrollLeft()+i.scrollSpeed))}s!==!1&&e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(r,t)}}),e.ui.plugin.add("draggable","snap",{start:function(t,n){var r=e(this).data("draggable"),i=r.options;r.snapElements=[],e(i.snap.constructor!=String?i.snap.items||":data(draggable)":i.snap).each(function(){var t=e(this),n=t.offset();this!=r.element[0]&&r.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:n.top,left:n.left})})},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=i.snapTolerance,o=n.offset.left,u=o+r.helperProportions.width,a=n.offset.top,f=a+r.helperProportions.height;for(var l=r.snapElements.length-1;l>=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s<o&&o<h+s&&p-s<a&&a<d+s||c-s<o&&o<h+s&&p-s<f&&f<d+s||c-s<u&&u<h+s&&p-s<a&&a<d+s||c-s<u&&u<h+s&&p-s<f&&f<d+s)){r.snapElements[l].snapping&&r.options.snap.release&&r.options.snap.release.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=!1;continue}if(i.snapMode!="inner"){var v=Math.abs(p-f)<=s,m=Math.abs(d-a)<=s,g=Math.abs(c-u)<=s,y=Math.abs(h-o)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p-r.helperProportions.height,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c-r.helperProportions.width}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h}).left-r.margins.left)}var b=v||m||g||y;if(i.snapMode!="outer"){var v=Math.abs(p-a)<=s,m=Math.abs(d-f)<=s,g=Math.abs(c-o)<=s,y=Math.abs(h-u)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d-r.helperProportions.height,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h-r.helperProportions.width}).left-r.margins.left)}!r.snapElements[l].snapping&&(v||m||g||y||b)&&r.options.snap.snap&&r.options.snap.snap.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=v||m||g||y||b}}}),e.ui.plugin.add("draggable","stack",{start:function(t,n){var r=e(this).data("draggable").options,i=e.makeArray(e(r.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!i.length)return;var s=parseInt(i[0].style.zIndex)||0;e(i).each(function(e){this.style.zIndex=s+e}),this[0].style.zIndex=s+i.length}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("zIndex")&&(i._zIndex=r.css("zIndex")),r.css("zIndex",i.zIndex)},stop:function(t,n){var r=e(this).data("draggable").options;r._zIndex&&e(n.helper).css("zIndex",r._zIndex)}})})(jQuery);(function(e,t){e.widget("ui.droppable",{version:"1.9.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var t=this.options,n=t.accept;this.isover=0,this.isout=1,this.accept=e.isFunction(n)?n:function(e){return e.is(n)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];for(var n=0;n<t.length;n++)t[n]==this&&t.splice(n,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,n){t=="accept"&&(this.accept=e.isFunction(n)?n:function(e){return e.is(n)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),n&&this._trigger("activate",t,this.ui(n))},_deactivate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),n&&this._trigger("deactivate",t,this.ui(n))},_over:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(n)))},_out:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(n)))},_drop:function(t,n){var r=n||e.ui.ddmanager.current;if(!r||(r.currentItem||r.element)[0]==this.element[0])return!1;var i=!1;return this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"droppable");if(t.options.greedy&&!t.options.disabled&&t.options.scope==r.options.scope&&t.accept.call(t.element[0],r.currentItem||r.element)&&e.ui.intersect(r,e.extend(t,{offset:t.element.offset()}),t.options.tolerance))return i=!0,!1}),i?!1:this.accept.call(this.element[0],r.currentItem||r.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(r)),this.element):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(t,n,r){if(!n.offset)return!1;var i=(t.positionAbs||t.position.absolute).left,s=i+t.helperProportions.width,o=(t.positionAbs||t.position.absolute).top,u=o+t.helperProportions.height,a=n.offset.left,f=a+n.proportions.width,l=n.offset.top,c=l+n.proportions.height;switch(r){case"fit":return a<=i&&s<=f&&l<=o&&u<=c;case"intersect":return a<i+t.helperProportions.width/2&&s-t.helperProportions.width/2<f&&l<o+t.helperProportions.height/2&&u-t.helperProportions.height/2<c;case"pointer":var h=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,p=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,d=e.ui.isOver(p,h,l,a,n.proportions.height,n.proportions.width);return d;case"touch":return(o>=l&&o<=c||u>=l&&u<=c||o<l&&u>c)&&(i>=a&&i<=f||s>=a&&s<=f||i<a&&s>f);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;o<r.length;o++){if(r[o].options.disabled||t&&!r[o].accept.call(r[o].element[0],t.currentItem||t.element))continue;for(var u=0;u<s.length;u++)if(s[u]==r[o].element[0]){r[o].proportions.height=0;continue e}r[o].visible=r[o].element.css("display")!="none";if(!r[o].visible)continue;i=="mousedown"&&r[o]._activate.call(r[o],n),r[o].offset=r[o].element.offset(),r[o].proportions={width:r[o].element[0].offsetWidth,height:r[o].element[0].offsetHeight}}},drop:function(t,n){var r=!1;return e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(r=this._drop.call(this,n)||r),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,n))}),r},dragStart:function(t,n){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)})},drag:function(t,n){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,n),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var r=e.ui.intersect(t,this,this.options.tolerance),i=!r&&this.isover==1?"isout":r&&this.isover==0?"isover":null;if(!i)return;var s;if(this.options.greedy){var o=this.options.scope,u=this.element.parents(":data(droppable)").filter(function(){return e.data(this,"droppable").options.scope===o});u.length&&(s=e.data(u[0],"droppable"),s.greedyChild=i=="isover"?1:0)}s&&i=="isover"&&(s.isover=0,s.isout=1,s._out.call(s,n)),this[i]=1,this[i=="isout"?"isover":"isout"]=0,this[i=="isover"?"_over":"_out"].call(this,n),s&&i=="isout"&&(s.isout=0,s.isover=1,s._over.call(s,n))})},dragStop:function(t,n){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)}}})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i<r.length;i++){var s=e.trim(r[i]),o="ui-resizable-"+s,u=e('<div class="ui-resizable-handle '+o+'"></div>');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")}).insertAfter(n),n.remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),i<u.maxWidth&&(u.maxWidth=i),o<u.maxHeight&&(u.maxHeight=o);this._vBoundaries=u},_updateCache:function(e){var t=this.options;this.offset=this.helper.offset(),r(e.left)&&(this.position.left=e.left),r(e.top)&&(this.position.top=e.top),r(e.height)&&(this.size.height=e.height),r(e.width)&&(this.size.width=e.width)},_updateRatio:function(e,t){var n=this.options,i=this.position,s=this.size,o=this.axis;return r(e.height)?e.width=e.height*this.aspectRatio:r(e.width)&&(e.height=e.width/this.aspectRatio),o=="sw"&&(e.left=i.left+(s.width-e.width),e.top=null),o=="nw"&&(e.top=i.top+(s.height-e.height),e.left=i.left+(s.width-e.width)),e},_respectSize:function(e,t){var n=this.helper,i=this._vBoundaries,s=this._aspectRatio||t.shiftKey,o=this.axis,u=r(e.width)&&i.maxWidth&&i.maxWidth<e.width,a=r(e.height)&&i.maxHeight&&i.maxHeight<e.height,f=r(e.width)&&i.minWidth&&i.minWidth>e.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r<this._proportionallyResizeElements.length;r++){var i=this._proportionallyResizeElements[r];if(!this.borderDif){var s=[i.css("borderTopWidth"),i.css("borderRightWidth"),i.css("borderBottomWidth"),i.css("borderLeftWidth")],o=[i.css("paddingTop"),i.css("paddingRight"),i.css("paddingBottom"),i.css("paddingLeft")];this.borderDif=e.map(s,function(e,t){var n=parseInt(e,10)||0,r=parseInt(o[t],10)||0;return n+r})}i.css({height:n.height()-this.borderDif[0]-this.borderDif[2]||0,width:n.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var t=this.element,n=this.options;this.elementOffset=t.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var r=e.ui.ie6?1:0,i=e.ui.ie6?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+i,height:this.element.outerHeight()+i,position:"absolute",left:this.elementOffset.left-r+"px",top:this.elementOffset.top-r+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<n.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+n.scrollSpeed:t.pageY-this.overflowOffset.top<n.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-n.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<n.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+n.scrollSpeed:t.pageX-this.overflowOffset.left<n.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-n.scrollSpeed)):(t.pageY-e(document).scrollTop()<n.scrollSensitivity?r=e(document).scrollTop(e(document).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<n.scrollSensitivity&&(r=e(document).scrollTop(e(document).scrollTop()+n.scrollSpeed)),t.pageX-e(document).scrollLeft()<n.scrollSensitivity?r=e(document).scrollLeft(e(document).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<n.scrollSensitivity&&(r=e(document).scrollLeft(e(document).scrollLeft()+n.scrollSpeed))),r!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var i=this.items.length-1;i>=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+f<a&&t+l>s&&t+l<o;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:s<t+this.helperProportions.width/2&&n-this.helperProportions.width/2<o&&u<r+this.helperProportions.height/2&&i-this.helperProportions.height/2<a},_intersectsWithPointer:function(t){var n=this.options.axis==="x"||e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),r=this.options.axis==="y"||e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),i=n&&r,s=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return i?this.floating?o&&o=="right"||s=="down"?2:1:s&&(s=="down"?2:1):!1},_intersectsWithSides:function(t){var n=e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),r=e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),i=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return this.floating&&s?s=="right"&&r||s=="left"&&!r:i&&(i=="down"&&n||i=="up"&&!n)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return e!=0&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n<t.length;n++)if(t[n]==e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var n=this.items,r=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],i=this._connectWith();if(i&&this.ready)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u<c;u++){var h=e(l[u]);h.data(this.widgetName+"-item",f),n.push({item:h,instance:f,width:0,height:0,left:0,top:0})}}},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var n=this.items.length-1;n>=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else{var s=1e4,o=null,u=this.containers[r].floating?"left":"top",a=this.containers[r].floating?"width":"height",f=this.positionAbs[u]+this.offset.click[u];for(var l=this.items.length-1;l>=0;l--){if(!e.contains(this.containers[r].element[0],this.items[l].item[0]))continue;if(this.items[l].item[0]==this.currentItem[0])continue;var c=this.items[l].item.offset()[u],h=!1;Math.abs(c-f)>Math.abs(c+this.items[l][a]-f)&&(h=!0,c+=this.items[l][a]),Math.abs(c-f)<s&&(s=Math.abs(c-f),o=this.items[l],this.direction=h?"up":"down")}if(!o&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[r],o?this._rearrange(t,o,null,!0):this._rearrange(t,null,this.containers[r].element,!0),this._trigger("change",t,this._uiHash()),this.containers[r]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper=="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(r[0].style.width==""||n.forceHelperSize)&&r.width(this.currentItem.width()),(r[0].style.height==""||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)){var n=e(t.containment)[0],r=e(t.containment).offset(),i=e(n).css("overflow")!="hidden";this.containment=[r.left+(parseInt(e(n).css("borderLeftWidth"),10)||0)+(parseInt(e(n).css("paddingLeft"),10)||0)-this.margins.left,r.top+(parseInt(e(n).css("borderTopWidth"),10)||0)+(parseInt(e(n).css("paddingTop"),10)||0)-this.margins.top,r.left+(i?Math.max(n.scrollWidth,n.offsetWidth):n.offsetWidth)-(parseInt(e(n).css("borderLeftWidth"),10)||0)-(parseInt(e(n).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,r.top+(i?Math.max(n.scrollHeight,n.offsetHeight):n.offsetHeight)-(parseInt(e(n).css("borderTopWidth"),10)||0)-(parseInt(e(n).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var s=t.pageX,o=t.pageY;if(this.originalPosition){this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.top<this.containment[1]||u-this.offset.click.top>this.containment[3]?u-this.offset.click.top<this.containment[1]?u+n.grid[1]:u-n.grid[1]:u:u;var a=this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0];s=this.containment?a-this.offset.click.left<this.containment[0]||a-this.offset.click.left>this.containment[2]?a-this.offset.click.left<this.containment[0]?a+n.grid[0]:a-n.grid[0]:a:a}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i==this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var i in this._storedCSS)if(this._storedCSS[i]=="auto"||this._storedCSS[i]=="static")this._storedCSS[i]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&r.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!n&&r.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(r.push(function(e){this._trigger("remove",e,this._uiHash())}),r.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),r.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(var i=this.containers.length-1;i>=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}n||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!n){for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var n=t||this;return{helper:n.helper,placeholder:n.placeholder||e([]),position:n.position,originalPosition:n.originalPosition,offset:n.positionAbs,item:n.currentItem,sender:t?t.element:null}}})})(jQuery);(function(e,t){var n=0;e.widget("ui.autocomplete",{version:"1.9.2",defaultElement:"<input>",options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete").appendTo(this.document.find(this.options.appendTo||"body")[0]).menu({input:e(),role:null}).zIndex(this.element.zIndex()+1).hide().data("menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var n=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(r){r.target!==t.element[0]&&r.target!==n&&!e.contains(n,r.target)&&t.close()})})},menufocus:function(t,n){if(this.isNewMenu){this.isNewMenu=!1;if(t.originalEvent&&/^mouse/.test(t.originalEvent.type)){this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)});return}}var r=n.item.data("ui-autocomplete-item")||n.item.data("item.autocomplete");!1!==this._trigger("focus",t,{item:r})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value):this.liveRegion.text(r.value)},menuselect:function(e,t){var n=t.item.data("ui-autocomplete-item")||t.item.data("item.autocomplete"),r=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=r,this._delay(function(){this.previous=r,this.selectedItem=n})),!1!==this._trigger("select",e,{item:n})&&this._value(n.value),this.term=this._value(),this.close(e),this.selectedItem=n}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element),e.fn.bgiframe&&this.menu.element.bgiframe(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),e==="source"&&this._initSource(),e==="appendTo"&&this.menu.element.appendTo(this.document.find(t||"body")[0]),e==="disabled"&&t&&this.xhr&&this.xhr.abort()},_isMultiLine:function(){return this.element.is("textarea")?!0:this.element.is("input")?!1:this.element.prop("isContentEditable")},_initSource:function(){var t,n,r=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(n,r){r(e.ui.autocomplete.filter(t,n.term))}):typeof this.options.source=="string"?(n=this.options.source,this.source=function(t,i){r.xhr&&r.xhr.abort(),r.xhr=e.ajax({url:n,data:t,dataType:"json",success:function(e){i(e)},error:function(){i([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){e=e!=null?e:this._value(),this.term=this._value();if(e.length<this.options.minLength)return this.close(t);if(this._trigger("search",t)===!1)return;return this._search(e)},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var e=this,t=++n;return function(r){t===n&&e.__response(r),e.pending--,e.pending||e.element.removeClass("ui-autocomplete-loading")}},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return typeof t=="string"?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var n=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(n,t),this.menu.refresh(),n.show(),this._resizeMenu(),n.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,n){var r=this;e.each(n,function(e,n){r._renderItemData(t,n)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,n){return e("<li>").append(e("<a>").text(n.label)).appendTo(t)},_move:function(e,t){if(!this.menu.element.is(":visible")){this.search(null,t);return}if(this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)){this._value(this.term),this.menu.blur();return}this.menu[e](t)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(e,t),t.preventDefault()}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,n){var r=new RegExp(e.ui.autocomplete.escapeRegex(n),"i");return e.grep(t,function(e){return r.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments);if(this.options.disabled||this.cancelSearch)return;e&&e.length?t=this.options.messages.results(e.length):t=this.options.messages.noResults,this.liveRegion.text(t)}})})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.9.2",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,f),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,u=this.options,a=this.type==="checkbox"||this.type==="radio",c=a?"":"ui-state-active",h="ui-state-focus";u.label===null&&(u.label=this.type==="input"?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(o).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){if(u.disabled)return;this===n&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){if(u.disabled)return;e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){u.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){t.buttonElement.addClass(h)}).bind("blur"+this.eventNamespace,function(){t.buttonElement.removeClass(h)}),a&&(this.element.bind("change"+this.eventNamespace,function(){if(s)return;t.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){if(u.disabled)return;s=!1,r=e.pageX,i=e.pageY}).bind("mouseup"+this.eventNamespace,function(e){if(u.disabled)return;if(r!==e.pageX||i!==e.pageY)s=!0})),this.type==="checkbox"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).toggleClass("ui-state-active"),t.buttonElement.attr("aria-pressed",t.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var n=t.element[0];l(n).not(n).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).addClass("ui-state-active"),n=this,t.document.one("mouseup",function(){n=null})}).bind("mouseup"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).removeClass("ui-state-active")}).bind("keydown"+this.eventNamespace,function(t){if(u.disabled)return!1;(t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active")}).bind("keyup"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",u.disabled),this._resetButton()},_determineButtonType:function(){var e,t,n;this.element.is("[type=checkbox]")?this.type="checkbox":this.element.is("[type=radio]")?this.type="radio":this.element.is("input")?this.type="input":this.type="button",this.type==="checkbox"||this.type==="radio"?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),n=this.element.is(":checked"),n&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",n)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(o+" "+u+" "+a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){this._super(e,t);if(e==="disabled"){t?this.element.prop("disabled",!0):this.element.prop("disabled",!1);return}this._resetButton()},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),this.type==="radio"?l(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var t=this.buttonElement.removeClass(a),n=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),r=this.options.icons,i=r.primary&&r.secondary,s=[];r.primary||r.secondary?(this.options.text&&s.push("ui-button-text-icon"+(i?"s":r.primary?"-primary":"-secondary")),r.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+r.primary+"'></span>"),r.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+r.secondary+"'></span>"),this.options.text||(s.push(i?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(n)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.9.2",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){e==="disabled"&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function($,undefined){function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.extend(this._defaults,this.regional[""]),this.dpDiv=bindHover($('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}function bindHover(e){var t="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(t,"mouseout",function(){$(this).removeClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).removeClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).removeClass("ui-datepicker-next-hover")}).delegate(t,"mouseover",function(){$.datepicker._isDisabledDatepicker(instActive.inline?e.parent()[0]:instActive.input[0])||($(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),$(this).addClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).addClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).addClass("ui-datepicker-next-hover"))})}function extendRemove(e,t){$.extend(e,t);for(var n in t)if(t[n]==null||t[n]==undefined)e[n]=t[n];return e}$.extend($.ui,{datepicker:{version:"1.9.2"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return extendRemove(this._defaults,e||{}),this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(e,t){var n=e[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:t,dpDiv:t?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(e,t){var n=$(e);t.append=$([]),t.trigger=$([]);if(n.hasClass(this.markerClassName))return;this._attachments(n,t),n.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),this._autoSize(t),$.data(e,PROP_NAME,t),t.settings.disabled&&this._disableDatepicker(e)},_attachments:function(e,t){var n=this._get(t,"appendText"),r=this._get(t,"isRTL");t.append&&t.append.remove(),n&&(t.append=$('<span class="'+this._appendClass+'">'+n+"</span>"),e[r?"before":"after"](t.append)),e.unbind("focus",this._showDatepicker),t.trigger&&t.trigger.remove();var i=this._get(t,"showOn");(i=="focus"||i=="both")&&e.focus(this._showDatepicker);if(i=="button"||i=="both"){var s=this._get(t,"buttonText"),o=this._get(t,"buttonImage");t.trigger=$(this._get(t,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:o,alt:s,title:s}):$('<button type="button"></button>').addClass(this._triggerClass).html(o==""?s:$("<img/>").attr({src:o,alt:s,title:s}))),e[r?"before":"after"](t.trigger),t.trigger.click(function(){return $.datepicker._datepickerShowing&&$.datepicker._lastInput==e[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=e[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(e[0])):$.datepicker._showDatepicker(e[0]),!1})}},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t=new Date(2009,11,20),n=this._get(e,"dateFormat");if(n.match(/[DM]/)){var r=function(e){var t=0,n=0;for(var r=0;r<e.length;r++)e[r].length>t&&(t=e[r].length,n=r);return n};t.setMonth(r(this._get(e,n.match(/MM/)?"monthNames":"monthNamesShort"))),t.setDate(r(this._get(e,n.match(/DD/)?"dayNames":"dayNamesShort"))+20-t.getDay())}e.input.attr("size",this._formatDate(e,t).length)}},_inlineDatepicker:function(e,t){var n=$(e);if(n.hasClass(this.markerClassName))return;n.addClass(this.markerClassName).append(t.dpDiv).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),$.data(e,PROP_NAME,t),this._setDate(t,this._getDefaultDate(t),!0),this._updateDatepicker(t),this._updateAlternate(t),t.settings.disabled&&this._disableDatepicker(e),t.dpDiv.css("display","block")},_dialogDatepicker:function(e,t,n,r,i){var s=this._dialogInst;if(!s){this.uuid+=1;var o="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+o+'" style="position: absolute; top: -100px; width: 0px;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),s=this._dialogInst=this._newInst(this._dialogInput,!1),s.settings={},$.data(this._dialogInput[0],PROP_NAME,s)}extendRemove(s.settings,r||{}),t=t&&t.constructor==Date?this._formatDate(s,t):t,this._dialogInput.val(t),this._pos=i?i.length?i:[i.pageX,i.pageY]:null;if(!this._pos){var u=document.documentElement.clientWidth,a=document.documentElement.clientHeight,f=document.documentElement.scrollLeft||document.body.scrollLeft,l=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[u/2-100+f,a/2-150+l]}return this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),s.settings.onSelect=n,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,s),this},_destroyDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();$.removeData(e,PROP_NAME),r=="input"?(n.append.remove(),n.trigger.remove(),t.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(r=="div"||r=="span")&&t.removeClass(this.markerClassName).empty()},_enableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t})},_disableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t}),this._disabledInputs[this._disabledInputs.length]=e},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;t<this._disabledInputs.length;t++)if(this._disabledInputs[t]==e)return!0;return!1},_getInst:function(e){try{return $.data(e,PROP_NAME)}catch(t){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(e,t,n){var r=this._getInst(e);if(arguments.length==2&&typeof t=="string")return t=="defaults"?$.extend({},$.datepicker._defaults):r?t=="all"?$.extend({},r.settings):this._get(r,t):null;var i=t||{};typeof t=="string"&&(i={},i[t]=n);if(r){this._curInst==r&&this._hideDatepicker();var s=this._getDateDatepicker(e,!0),o=this._getMinMaxDate(r,"min"),u=this._getMinMaxDate(r,"max");extendRemove(r.settings,i),o!==null&&i.dateFormat!==undefined&&i.minDate===undefined&&(r.settings.minDate=this._formatDate(r,o)),u!==null&&i.dateFormat!==undefined&&i.maxDate===undefined&&(r.settings.maxDate=this._formatDate(r,u)),this._attachments($(e),r),this._autoSize(r),this._setDate(r,s),this._updateAlternate(r),this._updateDatepicker(r)}},_changeDatepicker:function(e,t,n){this._optionDatepicker(e,t,n)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var n=this._getInst(e);n&&(this._setDate(n,t),this._updateDatepicker(n),this._updateAlternate(n))},_getDateDatepicker:function(e,t){var n=this._getInst(e);return n&&!n.inline&&this._setDateFromField(n,t),n?this._getDate(n):null},_doKeyDown:function(e){var t=$.datepicker._getInst(e.target),n=!0,r=t.dpDiv.is(".ui-datepicker-rtl");t._keyEvent=!0;if($.datepicker._datepickerShowing)switch(e.keyCode){case 9:$.datepicker._hideDatepicker(),n=!1;break;case 13:var i=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",t.dpDiv);i[0]&&$.datepicker._selectDay(e.target,t.selectedMonth,t.selectedYear,i[0]);var s=$.datepicker._get(t,"onSelect");if(s){var o=$.datepicker._formatDate(t);s.apply(t.input?t.input[0]:null,[o,t])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&$.datepicker._clearDate(e.target),n=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&$.datepicker._gotoToday(e.target),n=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?1:-1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,-7,"D"),n=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?-1:1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,7,"D"),n=e.ctrlKey||e.metaKey;break;default:n=!1}else e.keyCode==36&&e.ctrlKey?$.datepicker._showDatepicker(this):n=!1;n&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(e){var t=$.datepicker._getInst(e.target);if($.datepicker._get(t,"constrainInput")){var n=$.datepicker._possibleChars($.datepicker._get(t,"dateFormat")),r=String.fromCharCode(e.charCode==undefined?e.keyCode:e.charCode);return e.ctrlKey||e.metaKey||r<" "||!n||n.indexOf(r)>-1}},_doKeyUp:function(e){var t=$.datepicker._getInst(e.target);if(t.input.val()!=t.lastVal)try{var n=$.datepicker.parseDate($.datepicker._get(t,"dateFormat"),t.input?t.input.val():null,$.datepicker._getFormatConfig(t));n&&($.datepicker._setDateFromField(t),$.datepicker._updateAlternate(t),$.datepicker._updateDatepicker(t))}catch(r){$.datepicker.log(r)}return!0},_showDatepicker:function(e){e=e.target||e,e.nodeName.toLowerCase()!="input"&&(e=$("input",e.parentNode)[0]);if($.datepicker._isDisabledDatepicker(e)||$.datepicker._lastInput==e)return;var t=$.datepicker._getInst(e);$.datepicker._curInst&&$.datepicker._curInst!=t&&($.datepicker._curInst.dpDiv.stop(!0,!0),t&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var n=$.datepicker._get(t,"beforeShow"),r=n?n.apply(e,[e,t]):{};if(r===!1)return;extendRemove(t.settings,r),t.lastVal=null,$.datepicker._lastInput=e,$.datepicker._setDateFromField(t),$.datepicker._inDialog&&(e.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(e),$.datepicker._pos[1]+=e.offsetHeight);var i=!1;$(e).parents().each(function(){return i|=$(this).css("position")=="fixed",!i});var s={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,t.dpDiv.empty(),t.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(t),s=$.datepicker._checkOffset(t,s,i),t.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":i?"fixed":"absolute",display:"none",left:s.left+"px",top:s.top+"px"});if(!t.inline){var o=$.datepicker._get(t,"showAnim"),u=$.datepicker._get(t,"duration"),a=function(){var e=t.dpDiv.find("iframe.ui-datepicker-cover");if(!!e.length){var n=$.datepicker._getBorders(t.dpDiv);e.css({left:-n[0],top:-n[1],width:t.dpDiv.outerWidth(),height:t.dpDiv.outerHeight()})}};t.dpDiv.zIndex($(e).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&($.effects.effect[o]||$.effects[o])?t.dpDiv.show(o,$.datepicker._get(t,"showOptions"),u,a):t.dpDiv[o||"show"](o?u:null,a),(!o||!u)&&a(),t.input.is(":visible")&&!t.input.is(":disabled")&&t.input.focus(),$.datepicker._curInst=t}},_updateDatepicker:function(e){this.maxRows=4;var t=$.datepicker._getBorders(e.dpDiv);instActive=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var n=e.dpDiv.find("iframe.ui-datepicker-cover");!n.length||n.css({left:-t[0],top:-t[1],width:e.dpDiv.outerWidth(),height:e.dpDiv.outerHeight()}),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var r=this._getNumberOfMonths(e),i=r[1],s=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),i>1&&e.dpDiv.addClass("ui-datepicker-multi-"+i).css("width",s*i+"em"),e.dpDiv[(r[0]!=1||r[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e==$.datepicker._curInst&&$.datepicker._datepickerShowing&&e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&e.input[0]!=document.activeElement&&e.input.focus();if(e.yearshtml){var o=e.yearshtml;setTimeout(function(){o===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),o=e.yearshtml=null},0)}},_getBorders:function(e){var t=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(t(e.css("border-left-width"))),parseFloat(t(e.css("border-top-width")))]},_checkOffset:function(e,t,n){var r=e.dpDiv.outerWidth(),i=e.dpDiv.outerHeight(),s=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,u=document.documentElement.clientWidth+(n?0:$(document).scrollLeft()),a=document.documentElement.clientHeight+(n?0:$(document).scrollTop());return t.left-=this._get(e,"isRTL")?r-s:0,t.left-=n&&t.left==e.input.offset().left?$(document).scrollLeft():0,t.top-=n&&t.top==e.input.offset().top+o?$(document).scrollTop():0,t.left-=Math.min(t.left,t.left+r>u&&u>r?Math.abs(t.left+r-u):0),t.top-=Math.min(t.top,t.top+i>a&&a>i?Math.abs(i+o):0),t},_findPos:function(e){var t=this._getInst(e),n=this._get(t,"isRTL");while(e&&(e.type=="hidden"||e.nodeType!=1||$.expr.filters.hidden(e)))e=e[n?"previousSibling":"nextSibling"];var r=$(e).offset();return[r.left,r.top]},_hideDatepicker:function(e){var t=this._curInst;if(!t||e&&t!=$.data(e,PROP_NAME))return;if(this._datepickerShowing){var n=this._get(t,"showAnim"),r=this._get(t,"duration"),i=function(){$.datepicker._tidyDialog(t)};$.effects&&($.effects.effect[n]||$.effects[n])?t.dpDiv.hide(n,$.datepicker._get(t,"showOptions"),r,i):t.dpDiv[n=="slideDown"?"slideUp":n=="fadeIn"?"fadeOut":"hide"](n?r:null,i),n||i(),this._datepickerShowing=!1;var s=this._get(t,"onClose");s&&s.apply(t.input?t.input[0]:null,[t.input?t.input.val():"",t]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(!$.datepicker._curInst)return;var t=$(e.target),n=$.datepicker._getInst(t[0]);(t[0].id!=$.datepicker._mainDivId&&t.parents("#"+$.datepicker._mainDivId).length==0&&!t.hasClass($.datepicker.markerClassName)&&!t.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||t.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=n)&&$.datepicker._hideDatepicker()},_adjustDate:function(e,t,n){var r=$(e),i=this._getInst(r[0]);if(this._isDisabledDatepicker(r[0]))return;this._adjustInstDate(i,t+(n=="M"?this._get(i,"showCurrentAtPos"):0),n),this._updateDatepicker(i)},_gotoToday:function(e){var t=$(e),n=this._getInst(t[0]);if(this._get(n,"gotoCurrent")&&n.currentDay)n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear;else{var r=new Date;n.selectedDay=r.getDate(),n.drawMonth=n.selectedMonth=r.getMonth(),n.drawYear=n.selectedYear=r.getFullYear()}this._notifyChange(n),this._adjustDate(t)},_selectMonthYear:function(e,t,n){var r=$(e),i=this._getInst(r[0]);i["selected"+(n=="M"?"Month":"Year")]=i["draw"+(n=="M"?"Month":"Year")]=parseInt(t.options[t.selectedIndex].value,10),this._notifyChange(i),this._adjustDate(r)},_selectDay:function(e,t,n,r){var i=$(e);if($(r).hasClass(this._unselectableClass)||this._isDisabledDatepicker(i[0]))return;var s=this._getInst(i[0]);s.selectedDay=s.currentDay=$("a",r).html(),s.selectedMonth=s.currentMonth=t,s.selectedYear=s.currentYear=n,this._selectDate(e,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear))},_clearDate:function(e){var t=$(e),n=this._getInst(t[0]);this._selectDate(t,"")},_selectDate:function(e,t){var n=$(e),r=this._getInst(n[0]);t=t!=null?t:this._formatDate(r),r.input&&r.input.val(t),this._updateAlternate(r);var i=this._get(r,"onSelect");i?i.apply(r.input?r.input[0]:null,[t,r]):r.input&&r.input.trigger("change"),r.inline?this._updateDatepicker(r):(this._hideDatepicker(),this._lastInput=r.input[0],typeof r.input[0]!="object"&&r.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var t=this._get(e,"altField");if(t){var n=this._get(e,"altFormat")||this._get(e,"dateFormat"),r=this._getDate(e),i=this.formatDate(n,r,this._getFormatConfig(e));$(t).each(function(){$(this).val(i)})}},noWeekends:function(e){var t=e.getDay();return[t>0&&t<6,""]},iso8601Week:function(e){var t=new Date(e.getTime());t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1},parseDate:function(e,t,n){if(e==null||t==null)throw"Invalid arguments";t=typeof t=="object"?t.toString():t+"";if(t=="")return null;var r=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff;r=typeof r!="string"?r:(new Date).getFullYear()%100+parseInt(r,10);var i=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,s=(n?n.dayNames:null)||this._defaults.dayNames,o=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,u=(n?n.monthNames:null)||this._defaults.monthNames,a=-1,f=-1,l=-1,c=-1,h=!1,p=function(t){var n=y+1<e.length&&e.charAt(y+1)==t;return n&&y++,n},d=function(e){var n=p(e),r=e=="@"?14:e=="!"?20:e=="y"&&n?4:e=="o"?3:2,i=new RegExp("^\\d{1,"+r+"}"),s=t.substring(g).match(i);if(!s)throw"Missing number at position "+g;return g+=s[0].length,parseInt(s[0],10)},v=function(e,n,r){var i=$.map(p(e)?r:n,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)}),s=-1;$.each(i,function(e,n){var r=n[1];if(t.substr(g,r.length).toLowerCase()==r.toLowerCase())return s=n[0],g+=r.length,!1});if(s!=-1)return s+1;throw"Unknown name at position "+g},m=function(){if(t.charAt(g)!=e.charAt(y))throw"Unexpected literal at position "+g;g++},g=0;for(var y=0;y<e.length;y++)if(h)e.charAt(y)=="'"&&!p("'")?h=!1:m();else switch(e.charAt(y)){case"d":l=d("d");break;case"D":v("D",i,s);break;case"o":c=d("o");break;case"m":f=d("m");break;case"M":f=v("M",o,u);break;case"y":a=d("y");break;case"@":var b=new Date(d("@"));a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"!":var b=new Date((d("!")-this._ticksTo1970)/1e4);a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"'":p("'")?m():h=!0;break;default:m()}if(g<t.length){var w=t.substr(g);if(!/^\s+/.test(w))throw"Extra/unparsed characters found in date: "+w}a==-1?a=(new Date).getFullYear():a<100&&(a+=(new Date).getFullYear()-(new Date).getFullYear()%100+(a<=r?0:-100));if(c>-1){f=1,l=c;do{var E=this._getDaysInMonth(a,f-1);if(l<=E)break;f++,l-=E}while(!0)}var b=this._daylightSavingAdjust(new Date(a,f-1,l));if(b.getFullYear()!=a||b.getMonth()+1!=f||b.getDate()!=l)throw"Invalid date";return b},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(e,t,n){if(!t)return"";var r=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,i=(n?n.dayNames:null)||this._defaults.dayNames,s=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,o=(n?n.monthNames:null)||this._defaults.monthNames,u=function(t){var n=h+1<e.length&&e.charAt(h+1)==t;return n&&h++,n},a=function(e,t,n){var r=""+t;if(u(e))while(r.length<n)r="0"+r;return r},f=function(e,t,n,r){return u(e)?r[t]:n[t]},l="",c=!1;if(t)for(var h=0;h<e.length;h++)if(c)e.charAt(h)=="'"&&!u("'")?c=!1:l+=e.charAt(h);else switch(e.charAt(h)){case"d":l+=a("d",t.getDate(),2);break;case"D":l+=f("D",t.getDay(),r,i);break;case"o":l+=a("o",Math.round(((new Date(t.getFullYear(),t.getMonth(),t.getDate())).getTime()-(new Date(t.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":l+=a("m",t.getMonth()+1,2);break;case"M":l+=f("M",t.getMonth(),s,o);break;case"y":l+=u("y")?t.getFullYear():(t.getYear()%100<10?"0":"")+t.getYear()%100;break;case"@":l+=t.getTime();break;case"!":l+=t.getTime()*1e4+this._ticksTo1970;break;case"'":u("'")?l+="'":c=!0;break;default:l+=e.charAt(h)}return l},_possibleChars:function(e){var t="",n=!1,r=function(t){var n=i+1<e.length&&e.charAt(i+1)==t;return n&&i++,n};for(var i=0;i<e.length;i++)if(n)e.charAt(i)=="'"&&!r("'")?n=!1:t+=e.charAt(i);else switch(e.charAt(i)){case"d":case"m":case"y":case"@":t+="0123456789";break;case"D":case"M":return null;case"'":r("'")?t+="'":n=!0;break;default:t+=e.charAt(i)}return t},_get:function(e,t){return e.settings[t]!==undefined?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()==e.lastVal)return;var n=this._get(e,"dateFormat"),r=e.lastVal=e.input?e.input.val():null,i,s;i=s=this._getDefaultDate(e);var o=this._getFormatConfig(e);try{i=this.parseDate(n,r,o)||s}catch(u){this.log(u),r=t?"":r}e.selectedDay=i.getDate(),e.drawMonth=e.selectedMonth=i.getMonth(),e.drawYear=e.selectedYear=i.getFullYear(),e.currentDay=r?i.getDate():0,e.currentMonth=r?i.getMonth():0,e.currentYear=r?i.getFullYear():0,this._adjustInstDate(e)},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(e,t,n){var r=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},i=function(t){try{return $.datepicker.parseDate($.datepicker._get(e,"dateFormat"),t,$.datepicker._getFormatConfig(e))}catch(n){}var r=(t.toLowerCase().match(/^c/)?$.datepicker._getDate(e):null)||new Date,i=r.getFullYear(),s=r.getMonth(),o=r.getDate(),u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,a=u.exec(t);while(a){switch(a[2]||"d"){case"d":case"D":o+=parseInt(a[1],10);break;case"w":case"W":o+=parseInt(a[1],10)*7;break;case"m":case"M":s+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s));break;case"y":case"Y":i+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s))}a=u.exec(t)}return new Date(i,s,o)},s=t==null||t===""?n:typeof t=="string"?i(t):typeof t=="number"?isNaN(t)?n:r(t):new Date(t.getTime());return s=s&&s.toString()=="Invalid Date"?n:s,s&&(s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)),this._daylightSavingAdjust(s)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,n){var r=!t,i=e.selectedMonth,s=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),(i!=e.selectedMonth||s!=e.selectedYear)&&!n&&this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(r?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&e.input.val()==""?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(e){var t=this._get(e,"stepMonths"),n="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,-t,"M")},next:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,+t,"M")},hide:function(){window["DP_jQuery_"+dpuuid].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+dpuuid].datepicker._gotoToday(n)},selectDay:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectDay(n,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"Y"),!1}};$(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t=new Date;t=this._daylightSavingAdjust(new Date(t.getFullYear(),t.getMonth(),t.getDate()));var n=this._get(e,"isRTL"),r=this._get(e,"showButtonPanel"),i=this._get(e,"hideIfNoPrevNext"),s=this._get(e,"navigationAsDateFormat"),o=this._getNumberOfMonths(e),u=this._get(e,"showCurrentAtPos"),a=this._get(e,"stepMonths"),f=o[0]!=1||o[1]!=1,l=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),c=this._getMinMaxDate(e,"min"),h=this._getMinMaxDate(e,"max"),p=e.drawMonth-u,d=e.drawYear;p<0&&(p+=12,d--);if(h){var v=this._daylightSavingAdjust(new Date(h.getFullYear(),h.getMonth()-o[0]*o[1]+1,h.getDate()));v=c&&v<c?c:v;while(this._daylightSavingAdjust(new Date(d,p,1))>v)p--,p<0&&(p=11,d--)}e.drawMonth=p,e.drawYear=d;var m=this._get(e,"prevText");m=s?this.formatDate(m,this._daylightSavingAdjust(new Date(d,p-a,1)),this._getFormatConfig(e)):m;var g=this._canAdjustMonth(e,-1,d,p)?'<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>":i?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>",y=this._get(e,"nextText");y=s?this.formatDate(y,this._daylightSavingAdjust(new Date(d,p+a,1)),this._getFormatConfig(e)):y;var b=this._canAdjustMonth(e,1,d,p)?'<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>":i?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>",w=this._get(e,"currentText"),E=this._get(e,"gotoCurrent")&&e.currentDay?l:t;w=s?this.formatDate(w,E,this._getFormatConfig(e)):w;var S=e.inline?"":'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">'+this._get(e,"closeText")+"</button>",x=r?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(n?S:"")+(this._isInRange(e,E)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click">'+w+"</button>":"")+(n?"":S)+"</div>":"",T=parseInt(this._get(e,"firstDay"),10);T=isNaN(T)?0:T;var N=this._get(e,"showWeek"),C=this._get(e,"dayNames"),k=this._get(e,"dayNamesShort"),L=this._get(e,"dayNamesMin"),A=this._get(e,"monthNames"),O=this._get(e,"monthNamesShort"),M=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),D=this._get(e,"selectOtherMonths"),P=this._get(e,"calculateWeek")||this.iso8601Week,H=this._getDefaultDate(e),B="";for(var j=0;j<o[0];j++){var F="";this.maxRows=4;for(var I=0;I<o[1];I++){var q=this._daylightSavingAdjust(new Date(d,p,e.selectedDay)),R=" ui-corner-all",U="";if(f){U+='<div class="ui-datepicker-group';if(o[1]>1)switch(I){case 0:U+=" ui-datepicker-group-first",R=" ui-corner-"+(n?"right":"left");break;case o[1]-1:U+=" ui-datepicker-group-last",R=" ui-corner-"+(n?"left":"right");break;default:U+=" ui-datepicker-group-middle",R=""}U+='">'}U+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+R+'">'+(/all|left/.test(R)&&j==0?n?b:g:"")+(/all|right/.test(R)&&j==0?n?g:b:"")+this._generateMonthYearHeader(e,p,d,c,h,j>0||I>0,A,O)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var z=N?'<th class="ui-datepicker-week-col">'+this._get(e,"weekHeader")+"</th>":"";for(var W=0;W<7;W++){var X=(W+T)%7;z+="<th"+((W+T+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+C[X]+'">'+L[X]+"</span></th>"}U+=z+"</tr></thead><tbody>";var V=this._getDaysInMonth(d,p);d==e.selectedYear&&p==e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,V));var J=(this._getFirstDayOfMonth(d,p)-T+7)%7,K=Math.ceil((J+V)/7),Q=f?this.maxRows>K?this.maxRows:K:K;this.maxRows=Q;var G=this._daylightSavingAdjust(new Date(d,p,1-J));for(var Y=0;Y<Q;Y++){U+="<tr>";var Z=N?'<td class="ui-datepicker-week-col">'+this._get(e,"calculateWeek")(G)+"</td>":"";for(var W=0;W<7;W++){var et=M?M.apply(e.input?e.input[0]:null,[G]):[!0,""],tt=G.getMonth()!=p,nt=tt&&!D||!et[0]||c&&G<c||h&&G>h;Z+='<td class="'+((W+T+6)%7>=5?" ui-datepicker-week-end":"")+(tt?" ui-datepicker-other-month":"")+(G.getTime()==q.getTime()&&p==e.selectedMonth&&e._keyEvent||H.getTime()==G.getTime()&&H.getTime()==q.getTime()?" "+this._dayOverClass:"")+(nt?" "+this._unselectableClass+" ui-state-disabled":"")+(tt&&!_?"":" "+et[1]+(G.getTime()==l.getTime()?" "+this._currentClass:"")+(G.getTime()==t.getTime()?" ui-datepicker-today":""))+'"'+((!tt||_)&&et[2]?' title="'+et[2]+'"':"")+(nt?"":' data-handler="selectDay" data-event="click" data-month="'+G.getMonth()+'" data-year="'+G.getFullYear()+'"')+">"+(tt&&!_?" ":nt?'<span class="ui-state-default">'+G.getDate()+"</span>":'<a class="ui-state-default'+(G.getTime()==t.getTime()?" ui-state-highlight":"")+(G.getTime()==l.getTime()?" ui-state-active":"")+(tt?" ui-priority-secondary":"")+'" href="#">'+G.getDate()+"</a>")+"</td>",G.setDate(G.getDate()+1),G=this._daylightSavingAdjust(G)}U+=Z+"</tr>"}p++,p>11&&(p=0,d++),U+="</tbody></table>"+(f?"</div>"+(o[0]>0&&I==o[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),F+=U}B+=F}return B+=x+($.ui.ie6&&!e.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='<div class="ui-datepicker-title">',h="";if(s||!a)h+='<span class="ui-datepicker-month">'+o[t]+"</span>";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';for(var v=0;v<12;v++)(!p||v>=r.getMonth())&&(!d||v<=i.getMonth())&&(h+='<option value="'+v+'"'+(v==t?' selected="selected"':"")+">"+u[v]+"</option>");h+="</select>"}l||(c+=h+(s||!a||!f?" ":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+='<span class="ui-datepicker-year">'+n+"</span>";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';for(;b<=w;b++)e.yearshtml+='<option value="'+b+'"'+(b==n?' selected="selected"':"")+">"+b+"</option>";e.yearshtml+="</select>",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?" ":"")+h),c+="</div>",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&t<n?n:t;return i=r&&i>r?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.2",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.2",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||" ",s,o,u,a,f;s=(this.uiDialog=e("<div>")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),o=(this.uiDialogTitlebar=e("<div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").bind("mousedown",function(){s.focus()}).prependTo(s),u=e("<a href='#'></a>").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(o),(this.uiDialogTitlebarCloseText=e("<span>")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u),a=e("<span>").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o),f=(this.uiDialogButtonPane=e("<div>")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),(this.uiButtonSet=e("<div>")).addClass("ui-dialog-buttonset").appendTo(f),s.attr({role:"dialog","aria-labelledby":a.attr("id")}),o.find("*").add(o).disableSelection(),this._hoverable(u),this._focusable(u),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n=this,r=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(r=!0)}),r?(e.each(t,function(t,r){var i,s;r=e.isFunction(r)?{click:r,text:t}:r,r=e.extend({type:"button"},r),s=r.click,r.click=function(){s.apply(n.element[0],arguments)},i=e("<button></button>",r).appendTo(n.uiButtonSet),e.fn.button&&i.button()}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)):this.uiDialog.removeClass("ui-dialog-buttons")},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s)),e.ui.dialog.overlay.resize()}})},_makeResizable:function(n){function u(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}n=n===t?this.options.resizable:n;var r=this,i=this.options,s=this.uiDialog.css("position"),o=typeof n=="string"?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:o,start:function(t,n){e(this).addClass("ui-dialog-resizing"),r._trigger("resizeStart",t,u(n))},resize:function(e,t){r._trigger("resize",e,u(t))},stop:function(t,n){e(this).removeClass("ui-dialog-resizing"),i.height=e(this).height(),i.width=e(this).width(),r._trigger("resizeStop",t,u(n)),e.ui.dialog.overlay.resize()}}).css("position",s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(t){var n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()},_setOptions:function(t){var n=this,s={},o=!1;e.each(t,function(e,t){n._setOption(e,t),e in r&&(o=!0),e in i&&(s[e]=t)}),o&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",s)},_setOption:function(t,r){var i,s,o=this.uiDialog;switch(t){case"buttons":this._createButtons(r);break;case"closeText":this.uiDialogTitlebarCloseText.text(""+r);break;case"dialogClass":o.removeClass(this.options.dialogClass).addClass(n+r);break;case"disabled":r?o.addClass("ui-dialog-disabled"):o.removeClass("ui-dialog-disabled");break;case"draggable":i=o.is(":data(draggable)"),i&&!r&&o.draggable("destroy"),!i&&r&&this._makeDraggable();break;case"position":this._position(r);break;case"resizable":s=o.is(":data(resizable)"),s&&!r&&o.resizable("destroy"),s&&typeof r=="string"&&o.resizable("option","handles",r),!s&&r!==!1&&this._makeResizable(r);break;case"title":e(".ui-dialog-title",this.uiDialogTitlebar).html(""+(r||" "))}this._super(t,r)},_size:function(){var t,n,r,i=this.options,s=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),i.minWidth>i.width&&(i.width=i.minWidth),t=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),n=Math.max(0,i.minHeight-t),i.height==="auto"?e.support.minHeight?this.element.css({minHeight:n,height:"auto"}):(this.uiDialog.show(),r=this.element.css("height","auto").height(),s||this.uiDialog.hide(),this.element.height(Math.max(r,n))):this.element.height(Math.max(i.height-t,0)),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),e.extend(e.ui.dialog,{uuid:0,maxZ:0,getTitleId:function(e){var t=e.attr("id");return t||(this.uuid+=1,t=this.uuid),"ui-dialog-title-"+t},overlay:function(t){this.$el=e.ui.dialog.overlay.create(t)}}),e.extend(e.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(e){return e+".dialog-overlay"}).join(" "),create:function(t){this.instances.length===0&&(setTimeout(function(){e.ui.dialog.overlay.instances.length&&e(document).bind(e.ui.dialog.overlay.events,function(t){if(e(t.target).zIndex()<e.ui.dialog.overlay.maxZ)return!1})},1),e(window).bind("resize.dialog-overlay",e.ui.dialog.overlay.resize));var n=this.oldInstances.pop()||e("<div>").addClass("ui-widget-overlay");return e(document).bind("keydown.dialog-overlay",function(r){var i=e.ui.dialog.overlay.instances;i.length!==0&&i[i.length-1]===n&&t.options.closeOnEscape&&!r.isDefaultPrevented()&&r.keyCode&&r.keyCode===e.ui.keyCode.ESCAPE&&(t.close(r),r.preventDefault())}),n.appendTo(document.body).css({width:this.width(),height:this.height()}),e.fn.bgiframe&&n.bgiframe(),this.instances.push(n),n},destroy:function(t){var n=e.inArray(t,this.instances),r=0;n!==-1&&this.oldInstances.push(this.instances.splice(n,1)[0]),this.instances.length===0&&e([document,window]).unbind(".dialog-overlay"),t.height(0).width(0).remove(),e.each(this.instances,function(){r=Math.max(r,this.css("z-index"))}),this.maxZ=r},height:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),n=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),t<n?e(window).height()+"px":t+"px"):e(document).height()+"px"},width:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),n=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth),t<n?e(window).width()+"px":t+"px"):e(document).width()+"px"},resize:function(){var t=e([]);e.each(e.ui.dialog.overlay.instances,function(){t=t.add(this)}),t.css({width:0,height:0}).css({width:e.ui.dialog.overlay.width(),height:e.ui.dialog.overlay.height()})}}),e.extend(e.ui.dialog.overlay.prototype,{destroy:function(){e.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);(function(e,t){var n=!1;e.widget("ui.menu",{version:"1.9.2",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var n={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,n)}})})(jQuery);(function(e,t){var n=5;e.widget("ui.slider",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var t,r,i=this.options,s=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),o="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",u=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(i.disabled?" ui-slider-disabled ui-disabled":"")),this.range=e([]),i.range&&(i.range===!0&&(i.values||(i.values=[this._valueMin(),this._valueMin()]),i.values.length&&i.values.length!==2&&(i.values=[i.values[0],i.values[0]])),this.range=e("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(i.range==="min"||i.range==="max"?" ui-slider-range-"+i.range:""))),r=i.values&&i.values.length||1;for(t=s.length;t<r;t++)u.push(o);this.handles=s.add(e(u.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(e){e.preventDefault()}).mouseenter(function(){i.disabled||e(this).addClass("ui-state-hover")}).mouseleave(function(){e(this).removeClass("ui-state-hover")}).focus(function(){i.disabled?e(this).blur():(e(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),e(this).addClass("ui-state-focus"))}).blur(function(){e(this).removeClass("ui-state-focus")}),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)}),this._on(this.handles,{keydown:function(t){var r,i,s,o,u=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:t.preventDefault();if(!this._keySliding){this._keySliding=!0,e(t.target).addClass("ui-state-active"),r=this._start(t,u);if(r===!1)return}}o=this.options.step,this.options.values&&this.options.values.length?i=s=this.values(u):i=s=this.value();switch(t.keyCode){case e.ui.keyCode.HOME:s=this._valueMin();break;case e.ui.keyCode.END:s=this._valueMax();break;case e.ui.keyCode.PAGE_UP:s=this._trimAlignValue(i+(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.PAGE_DOWN:s=this._trimAlignValue(i-(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(i===this._valueMax())return;s=this._trimAlignValue(i+o);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(i===this._valueMin())return;s=this._trimAlignValue(i-o)}this._slide(t,u,s)},keyup:function(t){var n=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,n),this._change(t,n),e(t.target).removeClass("ui-state-active"))}}),this._refreshValue(),this._animateOff=!1},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var n,r,i,s,o,u,a,f,l=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),n={x:t.pageX,y:t.pageY},r=this._normValueFromMouse(n),i=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var n=Math.abs(r-l.values(t));i>n&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n<r)&&(n=r),n!==this.values(t)&&(i=this.values(),i[t]=n,s=this._trigger("slide",e,{handle:this.handles[t],value:n,values:i}),r=this.values(t?0:1),s!==!1&&this.values(t,n,!0))):n!==this.value()&&(s=this._trigger("slide",e,{handle:this.handles[t],value:n}),s!==!1&&this.value(n))},_stop:function(e,t){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("stop",e,n)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("change",e,n)}},value:function(e){if(arguments.length){this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0);return}return this._value()},values:function(t,n){var r,i,s;if(arguments.length>1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s<r.length;s+=1)r[s]=this._trimAlignValue(i[s]),this._change(null,s);this._refreshValue()},_setOption:function(t,n){var r,i=0;e.isArray(this.options.values)&&(i=this.options.values.length),e.Widget.prototype._setOption.apply(this,arguments);switch(t){case"disabled":n?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.prop("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.prop("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(r=0;r<i;r+=1)this._change(null,r);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e),e},_values:function(e){var t,n,r;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t),t;n=this.options.values.slice();for(r=0;r<n.length;r+=1)n[r]=this._trimAlignValue(n[r]);return n},_trimAlignValue:function(e){if(e<=this._valueMin())return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&e.href.replace(r,"")===location.href.replace(r,"").replace(/\s/g,"%20")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options,r=n.active,i=location.hash.substring(1);this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(r===null){i&&this.tabs.each(function(t,n){if(e(n).attr("aria-controls")===i)return r=t,!1}),r===null&&(r=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(r===null||r===-1)r=this.tabs.length?0:!1}r!==!1&&(r=this.tabs.index(this.tabs.eq(r)),r===-1&&(r=n.collapsible?!1:0)),n.active=r,!n.collapsible&&n.active===!1&&this.anchors.length&&(n.active=0),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"<em>Loading…</em>"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1<this.anchors.length?1:-1)),n.disabled=e.map(e.grep(n.disabled,function(e){return e!==t}),function(e){return e>=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"<div></div>"},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r,i,s=this._superApply(arguments);return s?(e==="beforeActivate"?(r=n.newTab.length?n.newTab:n.oldTab,i=n.newPanel.length?n.newPanel:n.oldPanel,s=this._super("select",t,{tab:r.find(".ui-tabs-anchor")[0],panel:i[0],index:r.closest("li").index()})):e==="activate"&&n.newTab.length&&(s=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),s):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);jQuery.effects||function(e,t){var n=e.uiBackCompat!==!1,r="ui-effects-";e.effects={effect:{}},function(t,n){function p(e,t,n){var r=a[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max<e?r.max:e)}function d(e){var n=o(),r=n._rgba=[];return e=e.toLowerCase(),h(s,function(t,i){var s,o=i.re.exec(e),a=o&&i.parse(o),f=i.space||"rgba";if(a)return s=n[f](a),n[u[f].cache]=s[u[f].cache],r=n._rgba=s._rgba,!1}),r.length?(r.join()==="0,0,0,0"&&t.extend(r,c.transparent),n):c[e]}function v(e,t,n){return n=(n+1)%1,n*6<1?e+(t-e)*n*6:n*2<1?t:n*3<2?e+(t-e)*(2/3-n)*6:e}var r="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "),i=/^([\-+])=\s*(\d+\.?\d*)/,s=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1]*2.55,e[2]*2.55,e[3]*2.55,e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],o=t.Color=function(e,n,r,i){return new t.Color.fn.parse(e,n,r,i)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},a={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},f=o.support={},l=t("<p>")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[];i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(l){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i;if(t&&t.length&&t[0]&&t[t[0]]){i=t.length;while(i--)r=t[i],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.2",save:function(e,t){for(var n=0;n<t.length;n++)t[n]!==null&&e.data(r+t[n],e[0].style[t[n]])},restore:function(e,n){var i,s;for(s=0;s<n.length;s++)n[s]!==null&&(i=e.data(r+n[s]),i===t&&(i=""),e.css(n[s],i))},setMode:function(e,t){return t==="toggle"&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var n,r;switch(e[0]){case"top":n=0;break;case"middle":n=.5;break;case"bottom":n=1;break;default:n=e[0]/t.height}switch(e[1]){case"left":r=0;break;case"center":r=.5;break;case"right":r=1;break;default:r=e[1]/t.width}return{x:r,y:n}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var n={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},r=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function a(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,s=t.mode;(r.is(":hidden")?s==="hide":s==="show")?u():o.call(r[0],t,u)}var t=i.apply(this,arguments),r=t.mode,s=t.queue,o=e.effects.effect[t.effect],u=!o&&n&&e.effects[t.effect];return e.fx.off||!o&&!u?r?this[r](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):o?s===!1?this.each(a):this.queue(s||"fx",a):u.call(this,{options:t,duration:t.duration,callback:t.complete,mode:t.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery); diff --git a/pub/lib/jquery/jquery.iframe-auto-height.plugin.1.9.0.js b/pub/lib/jquery/jquery.iframe-auto-height.plugin.1.9.0.js new file mode 100644 index 0000000000000000000000000000000000000000..5f7d4d14b27a0635bf0a1c63d8f4c86b32fed110 --- /dev/null +++ b/pub/lib/jquery/jquery.iframe-auto-height.plugin.1.9.0.js @@ -0,0 +1,198 @@ +/*jslint white: true, indent: 2, onevar: false, browser: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, regexp: true, strict: false, newcap: true, immed: true */ +/*global window, console, jQuery, setTimeout */ + +/* + Plugin: iframe autoheight jQuery Plugin + Version: 1.9.0 + Author and Contributors + ======================================== + NATHAN SMITH (http://sonspring.com/) + Jesse House (https://github.com/house9) + aaron manela (https://github.com/aaronmanela) + Hideki Abe (https://github.com/hideki-a) + Patrick Clark (https://github.com/hellopat) + ChristineP2 (https://github.com/ChristineP2) + Mmjavellana (https://github.com/Mmjavellana) + yiqing-95 (https://github.com/yiqing-95) + jcaspian (https://github.com/jcaspian) + adamjgray (https://github.com/adamjgray) + Jens Bissinger (https://github.com/dpree) + + File: jquery.iframe-auto-height.plugin.js + Remarks: original code from http://sonspring.com/journal/jquery-iframe-sizing + Description: when the page loads set the height of an iframe based on the height of its contents + see README: http://github.com/house9/jquery-iframe-auto-height + +*/ +(function ($) { + $.fn.iframeAutoHeight = function (spec) { + + // set default option values + var options = $.extend({ + heightOffset: 0, + minHeight: 0, + callback: function (newHeight) {}, + animate: false, + debug: false, + diagnostics: false, // used for development only + resetToMinHeight: false, + triggerFunctions: [], + heightCalculationOverrides: [] + }, spec); + + // logging + function debug(message) { + if (options.debug && options.debug === true && window.console) { + console.log(message); + } + } + + // not used by production code + function showDiagnostics(iframe, calledFrom) { + debug("Diagnostics from '" + calledFrom + "'"); + try { + debug(" " + $(iframe, window.top.document).contents().find('body')[0].scrollHeight + " for ...find('body')[0].scrollHeight"); + debug(" " + $(iframe.contentWindow.document).height() + " for ...contentWindow.document).height()"); + debug(" " + $(iframe.contentWindow.document.body).height() + " for ...contentWindow.document.body).height()"); + } catch (ex) { + // ie fails when called during for each, ok later on + // probably not an issue if called in a document ready block + debug(" unable to check in this state"); + } + debug("End diagnostics -> results vary by browser and when diagnostics are requested"); + } + + // show all option values + debug(options); + + // ****************************************************** + // iterate over the matched elements passed to the plugin ; return will make it chainable + return this.each(function () { + + // ****************************************************** + // http://api.jquery.com/jQuery.browser/ + var strategyKeys = ['webkit', 'mozilla', 'msie', 'opera']; + var strategies = []; + strategies['default'] = function (iframe, $iframeBody, options, browser) { + // NOTE: this is how the plugin determines the iframe height, override if you need custom + return $iframeBody[0].scrollHeight + options.heightOffset; + }; + + jQuery.each(strategyKeys, function (index, value) { + // use the default strategy for all browsers, can be overridden if desired + strategies[value] = strategies['default']; + }); + + // override strategies if registered in options + jQuery.each(options.heightCalculationOverrides, function(index, value) { + strategies[value.browser] = value.calculation; + }); + + function findStrategy(browser) { + var strategy = null; + + jQuery.each(strategyKeys, function (index, value) { + if (browser[value]) { + strategy = strategies[value]; + return false; + } + }); + + if (strategy === null) { + strategy = strategies['default']; + } + + return strategy; + } + // ****************************************************** + + // for use by webkit only + var loadCounter = 0; + + // resizeHeight + function resizeHeight(iframe) { + if (options.diagnostics) { + showDiagnostics(iframe, "resizeHeight"); + } + + // set the iframe size to minHeight so it'll get smaller on resizes in FF and IE + if (options.resetToMinHeight && options.resetToMinHeight === true) { + iframe.style.height = options.minHeight + 'px'; + } + + // get the iframe body height and set inline style to that plus a little + var $body = $(iframe, window.top.document).contents().find('body'); + var strategy = findStrategy($.browser); + var newHeight = strategy(iframe, $body, options, $.browser); + debug(newHeight); + + if (newHeight < options.minHeight) { + debug("new height is less than minHeight"); + newHeight = options.minHeight + options.heightOffset; + } + + debug("New Height: " + newHeight); + if (options.animate) { + $(iframe).animate({height: newHeight + 'px'}, {duration: 500}); + } else { + iframe.style.height = newHeight + 'px'; + } + + options.callback.apply($(iframe), [{newFrameHeight: newHeight}]); + } // END resizeHeight + + // debug me + debug(this); + if (options.diagnostics) { + showDiagnostics(this, "each iframe"); + } + + // if trigger functions are registered, invoke them + if (options.triggerFunctions.length > 0) { + debug(options.triggerFunctions.length + " trigger Functions"); + for (var i = 0; i < options.triggerFunctions.length; i++) { + options.triggerFunctions[i](resizeHeight, this); + } + } + + // Check if browser is Webkit (Safari/Chrome) or Opera + if ($.browser.webkit || $.browser.opera) { + debug("browser is webkit or opera"); + + // Start timer when loaded. + $(this).load(function () { + var delay = 0; + var iframe = this; + + var delayedResize = function () { + resizeHeight(iframe); + }; + + if (loadCounter === 0) { + // delay the first one + delay = 500; + } else { + // Reset iframe height to 0 to force new frame size to fit window properly + // this is only an issue when going from large to small iframe, not executed on page load + iframe.style.height = options.minHeight + 'px'; + } + + debug("load delay: " + delay); + setTimeout(delayedResize, delay); + loadCounter++; + }); + + // Safari and Opera need a kick-start. + var source = $(this).attr('src'); + $(this).attr('src', ''); + $(this).attr('src', source); + } else { + // For other browsers. + $(this).load(function () { + resizeHeight(this); + }); + } // if browser + + }); // $(this).each(function () { + }; // $.fn.iframeAutoHeight = function (options) { +}(jQuery)); // (function ($) { \ No newline at end of file diff --git a/pub/lib/mage/adminhtml/loader.js b/pub/lib/mage/adminhtml/varienLoader.js similarity index 100% rename from pub/lib/mage/adminhtml/loader.js rename to pub/lib/mage/adminhtml/varienLoader.js diff --git a/pub/lib/mage/backend/bootstrap.js b/pub/lib/mage/backend/bootstrap.js index 92e5a93509cfea049f74e0d3104eda525752bb81..8776d031988e910b617ff02f2f7662201f741c0f 100644 --- a/pub/lib/mage/backend/bootstrap.js +++ b/pub/lib/mage/backend/bootstrap.js @@ -25,6 +25,19 @@ /*jshint jquery:true browser:true */ /*global FORM_KEY:true*/ jQuery(function ($) { + 'use strict'; + // @TODO move isJSON method inside file with utility functions + $.extend(true, $, { + mage: { + isJSON : function(json){ + json = json.replace(/\\["\\\/bfnrtu]/g, '@'); + json = json.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); + json = json.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); + return (/^[\],:{}\s]*$/.test(json)); + } + } + }); + $.ajaxSetup({ /* * @type {string} @@ -68,9 +81,11 @@ jQuery(function ($) { */ complete: function(jqXHR) { if (jqXHR.readyState === 4) { - var jsonObject = jQuery.parseJSON(jqXHR.responseText); - if (jsonObject.ajaxExpired && jsonObject.ajaxRedirect) { - window.location.replace(jsonObject.ajaxRedirect); + if($.mage.isJSON(jqXHR.responseText)) { + var jsonObject = jQuery.parseJSON(jqXHR.responseText); + if (jsonObject.ajaxExpired && jsonObject.ajaxRedirect) { + window.location.replace(jsonObject.ajaxRedirect); + } } } } @@ -85,10 +100,12 @@ jQuery(function ($) { /* * Show loader on ajax send */ - $('body').on('ajaxSend', function(e) { - $(e.target).loader({ - icon: $('#loading_mask_loader img').attr('src') - }).loader('show'); + $('body').on('ajaxSend processStart', function(e, jqxhr, settings) { + if (settings && settings.showLoader) { + $(e.target).loader({ + icon: $('#loading_mask_loader img').attr('src') + }).loader('show'); + } }); /* diff --git a/pub/lib/mage/backend/form.js b/pub/lib/mage/backend/form.js index 266b911323835f3a8f8fbda65377a5134e2479fc..10446756d6528aeeb62adf3d93bb09a553f05a93 100644 --- a/pub/lib/mage/backend/form.js +++ b/pub/lib/mage/backend/form.js @@ -59,6 +59,33 @@ } }, + /** + * Check if field value is changed + * @protected + * @param {Object} e event object + */ + _changesObserver: function(e) { + var target = $(e.target); + if (e.type === 'focus' || e.type === 'focusin') { + this.currentField = { + statuses: { + checked: target.is(':checked'), + selected: target.is(':selected') + }, + val: target.val() + }; + + } else { + if (this.currentField) { + var changed = target.val() !== this.currentField.val || + target.is(':checked') !== this.currentField.statuses.checked || + target.is(':selected') !== this.currentField.statuses.selected; + if (changed) { + target.trigger('changed'); + } + } + } + }, /** * Get array with handler names * @protected @@ -90,7 +117,9 @@ * @protected */ _bind: function() { - this.element.on(this._getHandlers().join(' '), $.proxy(this._submit, this)); + this.element + .on(this._getHandlers().join(' '), $.proxy(this._submit, this)) + .on('focus blur focusin focusout', $.proxy(this._changesObserver, this)); }, /** @@ -152,7 +181,7 @@ _submit: function(e, data) { this._rollback(); this._beforeSubmit(e.type, data); - this.element.triggerHandler('submit'); + this.element.trigger('submit'); } }); diff --git a/pub/lib/mage/backend/notification.js b/pub/lib/mage/backend/notification.js index 38de4de69f1d5eed6545ffe5d05ebb796a93d0f1..12d611cdf8dd127ad10f54e4dd84c6bc2b8ed329 100644 --- a/pub/lib/mage/backend/notification.js +++ b/pub/lib/mage/backend/notification.js @@ -50,9 +50,11 @@ * @param {Object} */ _add: function(e, jqXHR) { - var response = $.parseJSON(jqXHR.responseText); - if (response.error) { - this.element.append($.tmpl('globalNotification', response)); + if($.mage.isJSON(jqXHR.responseText)) { + var response = $.parseJSON(jqXHR.responseText); + if (response.error) { + this.element.append($.tmpl('globalNotification', response)); + } } } }); diff --git a/pub/lib/mage/backend/tabs.js b/pub/lib/mage/backend/tabs.js new file mode 100644 index 0000000000000000000000000000000000000000..8a80809ec62cc73a2e0e6c47a051a05d0270fb08 --- /dev/null +++ b/pub/lib/mage/backend/tabs.js @@ -0,0 +1,289 @@ +/** + * 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 mage + * @copyright Copyright (c) 2012 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +/*jshint jquery:true*/ +/*global FORM_KEY:true*/ +(function($) { + 'use strict'; + // mage.tabs base functionality + $.widget('mage.tabs', $.ui.tabs, { + options: { + spinner: false + }, + + /** + * Tabs creation + * @protected + */ + _create: function() { + var activeIndex = this._getTabIndex(this.options.active); + this.options.active = activeIndex >= 0 ? activeIndex : 0; + this._super(); + }, + + /** + * Get active anchor + * @return {Element} + */ + activeAnchor: function() { + return this.anchors.eq(this.option("active")); + }, + + /** + * Get tab index by tab id + * @protected + * @param {string} id - id of tab + * @return {number} + */ + _getTabIndex: function(id) { + var anchors = this.anchors ? + this.anchors : + this._getList().find("> li > a[href]"); + return anchors.index($('#' + id)); + }, + + /** + * Switch between tabs + * @protected + * @param {Object} event - event object + * @param {undefined|Object} eventData + */ + _toggle: function(event, eventData) { + var anchor = $(eventData.newTab).find('a'); + if ($(eventData.newTab).find('a').data().tabType === 'link') { + location.href = anchor.prop('href'); + } else { + this._superApply(arguments); + } + } + }); + + // Extension for mage.tabs - Move panels in destination element + $.widget('mage.tabs', $.mage.tabs, { + /** + * Move panels in destination element on creation + * @protected + * @override + */ + _create: function() { + this._super(); + this._movePanelsInDestination(this.panels); + }, + + /** + * Get panel for tab. If panel no exist in tabs container, then find panel in destination element + * @protected + * @override + * @param {Element} tab - tab "li" DOM-element + * @return {Element} + */ + _getPanelForTab: function(tab) { + var panel = this._superApply(arguments); + if (!panel.length) { + var id = $(tab).attr("aria-controls"); + panel = $(this.options.destination).find(this._sanitizeSelector( "#" + id )); + } + return panel; + }, + + /** + * Move panels in destination element + * @protected + * @override + * @param {Array} panels - array of panels DOM elements + */ + _movePanelsInDestination: function(panels) { + if (this.options.destination && !panels.parents(this.options.destination).length) { + panels + .find('script').remove(); + panels.appendTo(this.options.destination) + .each($.proxy(function(i, panel) { + $(panel).trigger('move.tabs', this.anchors.eq(i)); + }, this)); + } + }, + + /** + * Move panels in destination element on tabs switching + * @protected + * @override + * @param {Object} event - event object + * @param {Object} eventData + */ + _toggle: function(event, eventData) { + this._movePanelsInDestination(eventData.newPanel); + this._superApply(arguments); + } + }); + + // Extension for mage.tabs - Ajax functionality for tabs + $.widget('mage.tabs', $.mage.tabs, { + options: { + ajaxOptions: { + data: { + isAjax: true, + form_key: typeof FORM_KEY !== 'undefined' ? FORM_KEY : null + } + }, + + /** + * Trigger event 'processStart' before tab is loaded + */ + beforeLoad: function() {$('body').trigger('processStart');}, + + /** + * Trigger event 'processStop' after tab is loaded + * @param {Object} event - event object + * @param {Object} + */ + load: function(event, ui) { + $('body').trigger('processStop'); + $(ui.tab).prop('href', '#' + $(ui.panel).prop('id')); + } + } + }); + + // Extension for mage.tabs - Attach event handlers to tabs + $.widget('mage.tabs', $.mage.tabs, { + options: { + tabIdArgument: 'tab', + tabsBlockPrefix: null + }, + + /** + * Attach event handlers to tabs, on creation + * @protected + * @override + */ + _create: function() { + this._super(); + this._bind(); + }, + + /** + * Attach event handlers to tabs + * @protected + */ + _bind: function() { + $.each(this.panels, $.proxy(function(i, panel) { + $(panel) + .on('changed', {index: i}, $.proxy(this._onContentChange, this)) + .on('highlight.validate', {index: i}, $.proxy(this._onInvalid, this)) + .on('focusin', {index: i}, $.proxy(this._onFocus, this)); + }, this)); + + ($(this.options.destination).is('form') ? + $(this.options.destination) : + $(this.options.destination).closest('form')) + .on('beforeSubmit', $.proxy(this._onBeforeSubmit, this)); + }, + + /** + * Mark tab as changed if some field inside tab panel is changed + * @protected + * @param {Object} e - event object + */ + _onContentChange: function(e) { + this.anchors.eq(e.data.index).addClass('changed'); + }, + + /** + * Mark tab as error if some field inside tab panel is not passed validation + * @param {Object} e - event object + * @protected + */ + _onInvalid: function(e) { + this.anchors.eq(e.data.index).addClass('error').find('.error').show(); + }, + + /** + * Show tab panel if focus event triggered of some field inside tab panel + * @param {Object} e - event object + * @protected + */ + _onFocus: function(e) { + this.option("active", e.data.index); + }, + + /** + * Add active tab id in data object when "beforeSubmit" event is triggered + * @param {Object} e - event object + * @param {Object} data - event data object + * @protected + */ + _onBeforeSubmit: function(e, data) { + var activeAnchor = this.activeAnchor(), + activeTabId = activeAnchor.prop('id'); + if (this.options.tabsBlockPrefix) { + if (activeAnchor.is('[id*="' + this.options.tabsBlockPrefix + '"]')) { + activeTabId = activeAnchor.prop('id').substr(this.options.tabsBlockPrefix.length); + } + } + $(this.anchors).removeClass('error'); + var options = { + action: { + args: {} + } + }; + options.action.args[this.options.tabIdArgument] = activeTabId; + data = data ? $.extend(data, options) : options; + } + }); + + // Extension for mage.tabs - Shadow tabs functionality + $.widget('mage.tabs', $.mage.tabs, { + /** + * Add shadow tabs functionality on creation + * @protected + * @override + */ + _bind: function() { + this._super(); + this._bindShadowTabs(); + }, + + /** + * Process shadow tabs + * @protected + */ + _bindShadowTabs: function() { + var anchors = this.anchors, + shadowTabs = this.options.shadowTabs, + tabs = this.tabs; + + if (shadowTabs) { + anchors.each($.proxy(function(i, anchor) { + var anchorId = $(anchor).prop('id'); + if (shadowTabs[anchorId]) { + $(anchor).parents('li').on('click', $.proxy(function(e) { + $.each(shadowTabs[anchorId], $.proxy(function(i, id) { + this.load($(tabs).index($('#' + id).parents('li')), {}); + }, this)); + }, this)); + } + }, this)); + } + } + }); +})(jQuery); diff --git a/pub/lib/mage/backend/validation.js b/pub/lib/mage/backend/validation.js index 98bd1059958ee28ef5e080104bdb35928c51f697..d6418a20ce80d39f3a806ed99a782ec960a64b98 100644 --- a/pub/lib/mage/backend/validation.js +++ b/pub/lib/mage/backend/validation.js @@ -92,9 +92,10 @@ type: 'POST', dataType: 'json', data: this.element.serialize(), - context: this, - success: this._onSuccess, - error: this._onError + context: $('body'), + success: $.proxy(this._onSuccess, this), + error: $.proxy(this._onError, this), + showLoader: true }); }, diff --git a/pub/lib/mage/loader.js b/pub/lib/mage/loader.js index bfd3d8786488cf6122464b486b6c74059e131e61..f5b545128b7b3db8ad80476b1a40c44059e7449b 100644 --- a/pub/lib/mage/loader.js +++ b/pub/lib/mage/loader.js @@ -50,7 +50,7 @@ * @protected */ _bind: function() { - this.element.on('ajaxComplete ajaxError', function(e) { + this.element.on('ajaxComplete ajaxError processStop', function(e) { e.stopImmediatePropagation(); $($(e.target).is(document) ? 'body' : e.target).loader('hide'); }); @@ -106,6 +106,7 @@ */ destroy: function() { this.loader.remove(); + this.element.off('ajaxComplete ajaxError processStop'); return $.Widget.prototype.destroy.call(this); } }); diff --git a/pub/lib/mage/translate-inline.js b/pub/lib/mage/translate-inline.js index f97a9ae082d5066ce2a517ecbac89050b36f1b8e..ecab6503e77b18f9d67f2f22725bd95e402fe6de 100644 --- a/pub/lib/mage/translate-inline.js +++ b/pub/lib/mage/translate-inline.js @@ -154,7 +154,8 @@ url: this.options.ajaxUrl, type: 'POST', data: parameters, - context: this.translateDialog + context: this.translateDialog, + showLoader: true }).complete(jQuery.proxy(function() { this.translateDialog.dialog('close'); }, this));