diff --git a/app/code/Magento/Backup/Controller/Adminhtml/Index/Grid.php b/app/code/Magento/Backup/Controller/Adminhtml/Index/Grid.php index 6a1c17a1b083d075508d84434dd0b2df9ab73740..0b9321033825562391fe32f168a6becd278ceacb 100644 --- a/app/code/Magento/Backup/Controller/Adminhtml/Index/Grid.php +++ b/app/code/Magento/Backup/Controller/Adminhtml/Index/Grid.php @@ -15,7 +15,7 @@ class Grid extends \Magento\Backup\Controller\Adminhtml\Index */ public function execute() { - $this->renderLayot(false); + $this->_view->loadLayout(); $this->_view->renderLayout(); } } diff --git a/app/code/Magento/Catalog/Model/Layer/Filter/Price/Range.php b/app/code/Magento/Catalog/Model/Layer/Filter/Price/Range.php index c1ff0681b3e7fde38c1fcb648671f32065e587cb..1d701dad26af6afb599ea97ad19a725e1e80201a 100644 --- a/app/code/Magento/Catalog/Model/Layer/Filter/Price/Range.php +++ b/app/code/Magento/Catalog/Model/Layer/Filter/Price/Range.php @@ -25,9 +25,9 @@ class Range private $scopeConfig; /** - * @var \Magento\Catalog\Model\Layer + * @var Resolver */ - private $layer; + private $layerResolver; /** * @param Registry $registry @@ -39,7 +39,7 @@ class Range { $this->registry = $registry; $this->scopeConfig = $scopeConfig; - $this->layer = $layerResolver->get(); + $this->layerResolver = $layerResolver; } /** @@ -47,7 +47,8 @@ class Range */ public function getPriceRange() { - $currentCategory = $this->registry->registry('current_category_filter') ?: $this->layer->getCurrentCategory(); + $currentCategory = $this->registry->registry('current_category_filter') + ?: $this->layerResolver->get()->getCurrentCategory(); return $currentCategory->getFilterPriceRange(); } diff --git a/app/code/Magento/Catalog/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/Catalog/Model/Layout/DepersonalizePlugin.php index 61ec24047fa6a6c5c756fd903c1fba0427b9d549..faacce917f4d3968a4c095f8358f8b759a3ff43c 100644 --- a/app/code/Magento/Catalog/Model/Layout/DepersonalizePlugin.php +++ b/app/code/Magento/Catalog/Model/Layout/DepersonalizePlugin.php @@ -7,25 +7,17 @@ */ namespace Magento\Catalog\Model\Layout; +use Magento\PageCache\Model\DepersonalizeChecker; + /** * Class DepersonalizePlugin */ class DepersonalizePlugin { /** - * @var \Magento\Framework\App\RequestInterface - */ - protected $request; - - /** - * @var \Magento\Framework\Module\Manager - */ - protected $moduleManager; - - /** - * @var \Magento\PageCache\Model\Config + * @var DepersonalizeChecker */ - protected $cacheConfig; + protected $depersonalizeChecker; /** * Catalog session @@ -35,21 +27,15 @@ class DepersonalizePlugin protected $catalogSession; /** + * @param DepersonalizeChecker $depersonalizeChecker * @param \Magento\Catalog\Model\Session $catalogSession - * @param \Magento\Framework\App\RequestInterface $request - * @param \Magento\Framework\Module\Manager $moduleManager - * @param \Magento\PageCache\Model\Config $cacheConfig */ public function __construct( - \Magento\Catalog\Model\Session $catalogSession, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\Framework\App\RequestInterface $request, - \Magento\PageCache\Model\Config $cacheConfig + DepersonalizeChecker $depersonalizeChecker, + \Magento\Catalog\Model\Session $catalogSession ) { $this->catalogSession = $catalogSession; - $this->request = $request; - $this->moduleManager = $moduleManager; - $this->cacheConfig = $cacheConfig; + $this->depersonalizeChecker = $depersonalizeChecker; } /** @@ -61,11 +47,7 @@ class DepersonalizePlugin */ public function afterGenerateXml(\Magento\Framework\View\LayoutInterface $subject, $result) { - if ($this->moduleManager->isEnabled('Magento_PageCache') - && $this->cacheConfig->isEnabled() - && !$this->request->isAjax() - && $subject->isCacheable() - ) { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { $this->catalogSession->clearStorage(); } return $result; diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Dynamic/DataProvider.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Dynamic/DataProvider.php index 341783fa0dcd6b1a71ec600f8edd392e0ccccc6b..4e4ab9680665bb8ccefe28c44674952fc5373d11 100644 --- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Dynamic/DataProvider.php +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Dynamic/DataProvider.php @@ -7,7 +7,6 @@ namespace Magento\CatalogSearch\Model\Adapter\Mysql\Dynamic; use Magento\Catalog\Model\Layer\Filter\Price\Range; use Magento\Customer\Model\Session; -use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Resource; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; @@ -15,17 +14,12 @@ use Magento\Framework\Search\Adapter\Mysql\Aggregation\DataProviderInterface as use Magento\Framework\Search\Dynamic\DataProviderInterface; use Magento\Framework\Search\Dynamic\IntervalFactory; use Magento\Framework\Search\Request\BucketInterface; -use Magento\Store\Model\ScopeInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DataProvider implements DataProviderInterface { - const XML_PATH_INTERVAL_DIVISION_LIMIT = 'catalog/layered_navigation/interval_division_limit'; - const XML_PATH_RANGE_STEP = 'catalog/layered_navigation/price_range_step'; - const XML_PATH_RANGE_MAX_INTERVALS = 'catalog/layered_navigation/price_range_max_intervals'; - /** * @var Resource */ @@ -36,11 +30,6 @@ class DataProvider implements DataProviderInterface */ private $range; - /** - * @var ScopeConfigInterface - */ - private $scopeConfig; - /** * @var Session */ @@ -58,7 +47,6 @@ class DataProvider implements DataProviderInterface /** * @param Resource $resource - * @param ScopeConfigInterface $scopeConfig * @param Range $range * @param Session $customerSession * @param MysqlDataProviderInterface $dataProvider @@ -66,7 +54,6 @@ class DataProvider implements DataProviderInterface */ public function __construct( Resource $resource, - ScopeConfigInterface $scopeConfig, Range $range, Session $customerSession, MysqlDataProviderInterface $dataProvider, @@ -74,7 +61,6 @@ class DataProvider implements DataProviderInterface ) { $this->resource = $resource; $this->range = $range; - $this->scopeConfig = $scopeConfig; $this->customerSession = $customerSession; $this->dataProvider = $dataProvider; $this->intervalFactory = $intervalFactory; @@ -97,7 +83,7 @@ class DataProvider implements DataProviderInterface 'count' => 'count(DISTINCT entity_id)', 'max' => 'MAX(min_price)', 'min' => 'MIN(min_price)', - 'std' => 'STDDEV_SAMP(min_price)', + 'std' => 'STDDEV_SAMP(min_price)' ]; $select = $this->getSelect(); @@ -115,28 +101,6 @@ class DataProvider implements DataProviderInterface return $result; } - /** - * {@inheritdoc} - */ - public function getOptions() - { - return [ - 'interval_division_limit' => (int)$this->scopeConfig->getValue( - self::XML_PATH_INTERVAL_DIVISION_LIMIT, - ScopeInterface::SCOPE_STORE - ), - 'range_step' => (double)$this->scopeConfig->getValue( - self::XML_PATH_RANGE_STEP, - ScopeInterface::SCOPE_STORE - ), - 'min_range_power' => 10, - 'max_intervals_number' => (int)$this->scopeConfig->getValue( - self::XML_PATH_RANGE_MAX_INTERVALS, - ScopeInterface::SCOPE_STORE - ) - ]; - } - /** * {@inheritdoc} */ @@ -190,7 +154,7 @@ class DataProvider implements DataProviderInterface $data[] = [ 'from' => $fromPrice, 'to' => $toPrice, - 'count' => $count, + 'count' => $count ]; } } diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Options.php b/app/code/Magento/CatalogSearch/Model/Adapter/Options.php new file mode 100644 index 0000000000000000000000000000000000000000..54871f6b60e2aebff0608ff5926b9db1c0304ce7 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Options.php @@ -0,0 +1,52 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogSearch\Model\Adapter; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Search\Adapter\OptionsInterface; +use Magento\Store\Model\ScopeInterface; + +class Options implements OptionsInterface +{ + const XML_PATH_INTERVAL_DIVISION_LIMIT = 'catalog/layered_navigation/interval_division_limit'; + const XML_PATH_RANGE_STEP = 'catalog/layered_navigation/price_range_step'; + const XML_PATH_RANGE_MAX_INTERVALS = 'catalog/layered_navigation/price_range_max_intervals'; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @param ScopeConfigInterface $scopeConfig + */ + public function __construct(ScopeConfigInterface $scopeConfig) + { + $this->scopeConfig = $scopeConfig; + } + + /** + * {@inheritdoc} + */ + public function get() + { + return [ + 'interval_division_limit' => (int)$this->scopeConfig->getValue( + self::XML_PATH_INTERVAL_DIVISION_LIMIT, + ScopeInterface::SCOPE_STORE + ), + 'range_step' => (double)$this->scopeConfig->getValue( + self::XML_PATH_RANGE_STEP, + ScopeInterface::SCOPE_STORE + ), + 'min_range_power' => 10, + 'max_intervals_number' => (int)$this->scopeConfig->getValue( + self::XML_PATH_RANGE_MAX_INTERVALS, + ScopeInterface::SCOPE_STORE + ) + ]; + } +} diff --git a/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php b/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php new file mode 100644 index 0000000000000000000000000000000000000000..b72299fd5fadbd88fc8773752ccd0d6a02c90106 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogSearch\Model\Adminhtml\System\Config\Backend; + +/** + * @author Magento Core Team <core@magentocommerce.com> + */ +class Engine extends \Magento\Framework\App\Config\Value +{ + /** @var \Magento\Indexer\Model\IndexerRegistry */ + protected $indexerRegistry; + + /** + * @param \Magento\Framework\Model\Context $context + * @param \Magento\Framework\Registry $registry + * @param \Magento\Framework\App\Config\ScopeConfigInterface $config + * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry + * @param \Magento\Framework\Model\Resource\AbstractResource $resource + * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param array $data + */ + public function __construct( + \Magento\Framework\Model\Context $context, + \Magento\Framework\Registry $registry, + \Magento\Framework\App\Config\ScopeConfigInterface $config, + \Magento\Indexer\Model\IndexerRegistry $indexerRegistry, + \Magento\Framework\Model\Resource\AbstractResource $resource = null, + \Magento\Framework\Data\Collection\Db $resourceCollection = null, + array $data = [] + ) { + $this->indexerRegistry = $indexerRegistry; + parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); + } + + /** + * After save call + * Invalidate catalog search index if engine was changed + * + * @return $this + */ + public function afterSave() + { + parent::afterSave(); + + if ($this->isValueChanged()) { + $this->indexerRegistry->get(\Magento\CatalogSearch\Model\Indexer\Fulltext::INDEXER_ID)->invalidate(); + } + return $this; + } +} diff --git a/app/code/Magento/CatalogSearch/Model/Advanced.php b/app/code/Magento/CatalogSearch/Model/Advanced.php index fbdfee9d801b629c38de863335dc7ca6a07e86ad..03f897697931cf741b8aa1943766e93acab4ed9c 100644 --- a/app/code/Magento/CatalogSearch/Model/Advanced.php +++ b/app/code/Magento/CatalogSearch/Model/Advanced.php @@ -9,13 +9,14 @@ use Magento\Catalog\Model\Config; use Magento\Catalog\Model\Product\Visibility; use Magento\Catalog\Model\ProductFactory; use Magento\Catalog\Model\Resource\Eav\Attribute; -use Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory; -use Magento\CatalogSearch\Model\Resource\Advanced\Collection; -use Magento\CatalogSearch\Model\Resource\ResourceProvider; -use Magento\Directory\Model\Currency; +use Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory as AttributeCollectionFactory; +use Magento\Catalog\Model\Resource\Product\CollectionFactory as ProductCollectionFactory; +use Magento\CatalogSearch\Model\Resource\Advanced\Collection as ProductCollection; +use Magento\CatalogSearch\Model\Resource\AdvancedFactory; use Magento\Directory\Model\CurrencyFactory; use Magento\Eav\Model\Entity\Attribute as EntityAttribute; use Magento\Framework\Model\Context; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Registry; use Magento\Store\Model\StoreManagerInterface; @@ -52,9 +53,9 @@ class Advanced extends \Magento\Framework\Model\AbstractModel protected $_searchCriterias = []; /** - * Found products collection + * Product collection * - * @var Collection + * @var ProductCollection */ protected $_productCollection; @@ -75,7 +76,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel /** * Attribute collection factory * - * @var CollectionFactory + * @var AttributeCollectionFactory */ protected $_attributeCollectionFactory; @@ -101,37 +102,40 @@ class Advanced extends \Magento\Framework\Model\AbstractModel protected $_currencyFactory; /** - * Resources factory + * Advanced Collection Factory * - * @var ResourceProvider + * @var ProductCollectionFactory */ - protected $_resourceProvider; + protected $productCollectionFactory; /** * Construct * * @param Context $context * @param Registry $registry - * @param CollectionFactory $attributeCollectionFactory + * @param AttributeCollectionFactory $attributeCollectionFactory * @param Visibility $catalogProductVisibility * @param Config $catalogConfig * @param CurrencyFactory $currencyFactory * @param ProductFactory $productFactory - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param ResourceProvider $resourceProvider + * @param StoreManagerInterface $storeManager + * @param ProductCollectionFactory $productCollectionFactory + * @param AdvancedFactory $advancedFactory * @param array $data + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Context $context, Registry $registry, - CollectionFactory $attributeCollectionFactory, + AttributeCollectionFactory $attributeCollectionFactory, Visibility $catalogProductVisibility, Config $catalogConfig, CurrencyFactory $currencyFactory, ProductFactory $productFactory, StoreManagerInterface $storeManager, - ResourceProvider $resourceProvider, + ProductCollectionFactory $productCollectionFactory, + AdvancedFactory $advancedFactory, array $data = [] ) { $this->_attributeCollectionFactory = $attributeCollectionFactory; @@ -140,12 +144,12 @@ class Advanced extends \Magento\Framework\Model\AbstractModel $this->_currencyFactory = $currencyFactory; $this->_productFactory = $productFactory; $this->_storeManager = $storeManager; - $this->_resourceProvider = $resourceProvider; + $this->productCollectionFactory = $productCollectionFactory; parent::__construct( $context, $registry, - $this->_resourceProvider->getResource(), - $this->_resourceProvider->getResourceCollection(), + $advancedFactory->create(), + $this->productCollectionFactory->create(), $data ); } @@ -155,7 +159,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel * * @param array $values * @return $this - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ @@ -171,7 +175,11 @@ class Advanced extends \Magento\Framework\Model\AbstractModel continue; } $value = $values[$attribute->getAttributeCode()]; - $this->_addSearchCriteria($attribute, $value); + $preparedSearchValue = $this->getPreparedSearchCriteria($attribute, $value); + if (false === $preparedSearchValue) { + continue; + } + $this->addSearchCriteria($attribute, $preparedSearchValue); if ($attribute->getAttributeCode() == 'price') { $rate = 1; @@ -188,6 +196,15 @@ class Advanced extends \Magento\Framework\Model\AbstractModel ? (float)$value['to'] / $rate : ''; } + + if ($attribute->getBackendType() == 'datetime') { + $value['from'] = (isset($value['from']) && !empty($value['from'])) + ? date('Y-m-d\TH:i:s\Z', strtotime($value['from'])) + : ''; + $value['to'] = (isset($value['to']) && !empty($value['to'])) + ? date('Y-m-d\TH:i:s\Z', strtotime($value['to'])) + : ''; + } $condition = $this->_getResource()->prepareCondition( $attribute, $value, @@ -209,7 +226,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel $this->_registry->register('advanced_search_conditions', $allConditions); $this->getProductCollection()->addFieldsToFilter($allConditions); } elseif (!$hasConditions) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please specify at least one search term.')); + throw new LocalizedException(__('Please specify at least one search term.')); } return $this; @@ -248,7 +265,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel public function getProductCollection() { if (is_null($this->_productCollection)) { - $collection = $this->_resourceProvider->getAdvancedResultCollection(); + $collection = $this->productCollectionFactory->create(); $this->prepareProductCollection($collection); if (!$collection) { return $collection; @@ -278,6 +295,18 @@ class Advanced extends \Magento\Framework\Model\AbstractModel return $this; } + /** + * @param EntityAttribute $attribute + * @param mixed $value + * @return void + */ + protected function addSearchCriteria($attribute, $value) + { + if (!empty($value)) { + $this->_searchCriterias[] = ['name' => $attribute->getStoreLabel(), 'value' => $value]; + } + } + /** * Add data about search criteria to object state * @@ -285,14 +314,12 @@ class Advanced extends \Magento\Framework\Model\AbstractModel * * @param EntityAttribute $attribute * @param mixed $value - * @return $this + * @return string|bool * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - protected function _addSearchCriteria($attribute, $value) + protected function getPreparedSearchCriteria($attribute, $value) { - $name = $attribute->getStoreLabel(); - if (is_array($value)) { if (isset($value['from']) && isset($value['to'])) { if (!empty($value['from']) || !empty($value['to'])) { @@ -320,7 +347,7 @@ class Advanced extends \Magento\Framework\Model\AbstractModel $value = __('up to %1', $currencyModel ? $to : $value['to']); } } else { - return $this; + return ''; } } } @@ -346,10 +373,8 @@ class Advanced extends \Magento\Framework\Model\AbstractModel ? __('Yes') : __('No'); } - if (!empty($value)) { - $this->_searchCriterias[] = ['name' => $name, 'value' => $value]; - } - return $this; + + return $value; } /** diff --git a/app/code/Magento/CatalogSearch/Model/Autocomplete/DataProvider.php b/app/code/Magento/CatalogSearch/Model/Autocomplete/DataProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..f721b1ea3ac4454ade38208a5e69e6058ab96585 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/Autocomplete/DataProvider.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogSearch\Model\Autocomplete; + +use Magento\Search\Model\Resource\Query\Collection; +use Magento\Search\Model\QueryFactory; +use Magento\Search\Model\Autocomplete\DataProviderInterface; +use Magento\Search\Model\Autocomplete\ItemFactory; + +class DataProvider implements DataProviderInterface +{ + /** + * Query factory + * + * @var QueryFactory + */ + protected $queryFactory; + + /** + * Autocomplete result item factory + * + * @var ItemFactory + */ + protected $itemFactory; + + /** + * @param QueryFactory $queryFactory + * @param ItemFactory $itemFactory + */ + public function __construct( + QueryFactory $queryFactory, + ItemFactory $itemFactory + ) { + $this->queryFactory = $queryFactory; + $this->itemFactory = $itemFactory; + } + + /** + * {@inheritdoc} + */ + public function getItems() + { + $collection = $this->getSuggestCollection(); + $query = $this->queryFactory->get()->getQueryText(); + $result = []; + foreach ($collection as $item) { + $resultItem = $this->itemFactory->create([ + 'title' => $item->getQueryText(), + 'num_results' => $item->getNumResults(), + ]); + if ($resultItem->getTitle() == $query) { + array_unshift($result, $resultItem); + } else { + $result[] = $resultItem; + } + } + return $result; + } + + /** + * Retrieve suggest collection for query + * + * @return Collection + */ + private function getSuggestCollection() + { + return $this->queryFactory->get()->getSuggestCollection(); + } +} diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php index e4f6fea57b08b1ef8befff137a864eca3aa6cebd..104843591917cd0000399b15a7e8bae60ac7737d 100644 --- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php +++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php @@ -443,12 +443,8 @@ class Full $this->searchableAttributes = []; $productAttributes = $this->productAttributeCollectionFactory->create(); + $productAttributes->addToIndexFilter(true); - if ($this->engineProvider->get() && $this->engineProvider->get()->allowAdvancedIndex()) { - $productAttributes->addToIndexFilter(true); - } else { - $productAttributes->addSearchableAttributeFilter(); - } /** @var \Magento\Eav\Model\Entity\Attribute[] $attributes */ $attributes = $productAttributes->getItems(); @@ -672,7 +668,7 @@ class Full foreach ($indexData as $entityId => $attributeData) { foreach ($attributeData as $attributeId => $attributeValue) { $value = $this->getAttributeValue($attributeId, $attributeValue, $storeId); - if (!is_null($value) && $value !== false) { + if (!empty($value)) { $attributeCode = $this->getSearchableAttribute($attributeId)->getAttributeCode(); if (isset($index[$attributeCode])) { @@ -684,19 +680,17 @@ class Full } } - if ($this->engineProvider->get()->allowAdvancedIndex()) { - $product = $this->getProductEmulator( - $productData['type_id'] - )->setId( - $productData['entity_id'] - )->setStoreId( - $storeId - ); - $typeInstance = $this->getProductTypeInstance($productData['type_id']); - $data = $typeInstance->getSearchableData($product); - if ($data) { - $index['options'] = $data; - } + $product = $this->getProductEmulator( + $productData['type_id'] + )->setId( + $productData['entity_id'] + )->setStoreId( + $storeId + ); + $typeInstance = $this->getProductTypeInstance($productData['type_id']); + $data = $typeInstance->getSearchableData($product); + if ($data) { + $index['options'] = $data; } if ($this->engineProvider->get()) { @@ -721,6 +715,7 @@ class Full if ($attribute->getIsSearchable() && $attribute->usesSource() + && $this->engineProvider->get()->allowAdvancedIndex() ) { $attribute->setStoreId($storeId); $valueText = $attribute->getSource()->getIndexOptionText($valueId); diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php index 7acc2cd6a3b2041b7b751fc4f5ad0ad373a1189a..d5bb6d4fe7222e9645bb74533a05eda53ad60829 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/CollectionFilter.php @@ -15,11 +15,6 @@ class CollectionFilter implements CollectionFilterInterface */ protected $catalogConfig; - /** - * @var \Magento\CatalogSearch\Helper\Data - */ - protected $helper; - /** * @var \Magento\Store\Model\StoreManagerInterface */ @@ -32,20 +27,17 @@ class CollectionFilter implements CollectionFilterInterface /** * @param \Magento\Catalog\Model\Config $catalogConfig - * @param \Magento\CatalogSearch\Helper\Data $helper * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Catalog\Model\Product\Visibility $productVisibility * @param \Magento\Framework\Registry $registry */ public function __construct( \Magento\Catalog\Model\Config $catalogConfig, - \Magento\CatalogSearch\Helper\Data $helper, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Catalog\Model\Product\Visibility $productVisibility, \Magento\Framework\Registry $registry ) { $this->catalogConfig = $catalogConfig; - $this->helper = $helper; $this->storeManager = $storeManager; $this->productVisibility = $productVisibility; $this->_registry = $registry; diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Price.php b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Price.php index f026a8fc4f4c897ccbbc5f3059f0d06a9df4707e..bdb6e8cd568c7fa191dee6dcc4dd70aa6c969965 100644 --- a/app/code/Magento/CatalogSearch/Model/Layer/Filter/Price.php +++ b/app/code/Magento/CatalogSearch/Model/Layer/Filter/Price.php @@ -193,6 +193,8 @@ class Price extends AbstractFilter * Get data array for building attribute filter items * * @return array + * + * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _getItemsData() { @@ -207,26 +209,10 @@ class Price extends AbstractFilter if (count($facets) > 1) { // two range minimum foreach ($facets as $key => $aggregation) { $count = $aggregation['count']; - list($from, $to) = explode('_', $key); - if ($from == '*') { - $from = $this->getFrom($to); + if (strpos($key, '_') === false) { + continue; } - if ($to == '*') { - $to = $this->getTo($to); - } - $label = $this->_renderRangeLabel( - empty($from) ? 0 : $from * $this->getCurrencyRate(), - empty($to) ? $to : $to * $this->getCurrencyRate() - ); - $value = $from . '-' . $to . $this->dataProvider->getAdditionalRequestData(); - - $data[] = [ - 'label' => $label, - 'value' => $value, - 'count' => $count, - 'from' => $from, - 'to' => $to, - ]; + $data[] = $this->prepareData($key, $count, $data); } } @@ -260,4 +246,35 @@ class Price extends AbstractFilter } return $to; } + + /** + * @param string $key + * @param int $count + * @return array + */ + private function prepareData($key, $count) + { + list($from, $to) = explode('_', $key); + if ($from == '*') { + $from = $this->getFrom($to); + } + if ($to == '*') { + $to = $this->getTo($to); + } + $label = $this->_renderRangeLabel( + empty($from) ? 0 : $from * $this->getCurrencyRate(), + empty($to) ? $to : $to * $this->getCurrencyRate() + ); + $value = $from . '-' . $to . $this->dataProvider->getAdditionalRequestData(); + + $data = [ + 'label' => $label, + 'value' => $value, + 'count' => $count, + 'from' => $from, + 'to' => $to, + ]; + + return $data; + } } diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Advanced.php b/app/code/Magento/CatalogSearch/Model/Resource/Advanced.php index c1978631106ef9ce1924db4d20232adfd387de36..84220246535dfd353cc0cbe975390283bd243eeb 100644 --- a/app/code/Magento/CatalogSearch/Model/Resource/Advanced.php +++ b/app/code/Magento/CatalogSearch/Model/Resource/Advanced.php @@ -55,32 +55,6 @@ class Advanced extends \Magento\Framework\Model\Resource\Db\AbstractDb $this->_init('catalog_product_entity', 'entity_id'); } - /** - * Prepare response object and dispatch prepare price event - * Return response object - * - * @param \Magento\Framework\DB\Select $select - * @return \Magento\Framework\Object - */ - protected function _dispatchPreparePriceEvent($select) - { - // prepare response object for event - $response = new \Magento\Framework\Object(); - $response->setAdditionalCalculations([]); - - // prepare event arguments - $eventArgs = [ - 'select' => $select, - 'table' => 'price_index', - 'store_id' => $this->_storeManager->getStore()->getId(), - 'response_object' => $response, - ]; - - $this->_eventManager->dispatch('catalog_prepare_price_select', $eventArgs); - - return $response; - } - /** * Prepare search condition for attribute * @@ -116,103 +90,4 @@ class Advanced extends \Magento\Framework\Model\Resource\Db\AbstractDb return $condition; } - - /** - * Add filter by attribute rated price - * - * @param \Magento\CatalogSearch\Model\Resource\Advanced\Collection $collection - * @param \Magento\Catalog\Model\Resource\Eav\Attribute $attribute - * @param string|array $value - * @param int $rate - * @return bool - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function addRatedPriceFilter($collection, $attribute, $value, $rate = 1) - { - $adapter = $this->_getReadAdapter(); - - $conditions = []; - if (strlen($value['from']) > 0) { - $conditions[] = $adapter->quoteInto( - 'price_index.min_price %s * %s >= ?', - $value['from'], - \Zend_Db::FLOAT_TYPE - ); - } - if (strlen($value['to']) > 0) { - $conditions[] = $adapter->quoteInto( - 'price_index.min_price %s * %s <= ?', - $value['to'], - \Zend_Db::FLOAT_TYPE - ); - } - - if (!$conditions) { - return false; - } - - $collection->addPriceData(); - $select = $collection->getSelect(); - $response = $this->_dispatchPreparePriceEvent($select); - $additional = join('', $response->getAdditionalCalculations()); - - foreach ($conditions as $condition) { - $select->where(sprintf($condition, $additional, $rate)); - } - - return true; - } - - /** - * Add filter by indexable attribute - * - * @param \Magento\CatalogSearch\Model\Resource\Advanced\Collection $collection - * @param \Magento\Catalog\Model\Resource\Eav\Attribute $attribute - * @param string|array $value - * @return bool - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function addIndexableAttributeModifiedFilter($collection, $attribute, $value) - { - if ($attribute->getIndexType() == 'decimal') { - $table = $this->getTable('catalog_product_index_eav_decimal'); - } else { - $table = $this->getTable('catalog_product_index_eav'); - } - - $tableAlias = 'a_' . $attribute->getAttributeId(); - $storeId = $this->_storeManager->getStore()->getId(); - $select = $collection->getSelect(); - - if (is_array($value)) { - if (isset($value['from']) && isset($value['to'])) { - if (empty($value['from']) && empty($value['to'])) { - return false; - } - } - } - - $select->distinct(true); - $select->join( - [$tableAlias => $table], - "e.entity_id={$tableAlias}.entity_id " . - " AND {$tableAlias}.attribute_id={$attribute->getAttributeId()}" . - " AND {$tableAlias}.store_id={$storeId}", - [] - ); - - if (is_array($value) && (isset($value['from']) || isset($value['to']))) { - if (isset($value['from']) && !empty($value['from'])) { - $select->where("{$tableAlias}.value >= ?", $value['from']); - } - if (isset($value['to']) && !empty($value['to'])) { - $select->where("{$tableAlias}.value <= ?", $value['to']); - } - return true; - } - - $select->where("{$tableAlias}.value IN(?)", $value); - - return true; - } } diff --git a/app/code/Magento/CatalogSearch/Model/Resource/EngineProvider.php b/app/code/Magento/CatalogSearch/Model/Resource/EngineProvider.php index 1d021b322f757222f69b83ab86b2691e8db0bcdc..4524b19419f67994034b49fb246e5a886647ba3b 100644 --- a/app/code/Magento/CatalogSearch/Model/Resource/EngineProvider.php +++ b/app/code/Magento/CatalogSearch/Model/Resource/EngineProvider.php @@ -18,28 +18,38 @@ class EngineProvider /** * @var \Magento\CatalogSearch\Model\Resource\EngineInterface */ - protected $_engine; + protected $engine; /** * @var \Magento\Framework\App\Config\ScopeConfigInterface */ - protected $_scopeConfig; + protected $scopeConfig; /** * @var \Magento\Framework\ObjectManagerInterface */ - private $_objectManager; + private $objectManager; + + /** + * Pool of existing engines + * + * @var array + */ + private $enginePool; /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param array $engines */ public function __construct( \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Framework\ObjectManagerInterface $objectManager + \Magento\Framework\ObjectManagerInterface $objectManager, + array $engines ) { - $this->_scopeConfig = $scopeConfig; - $this->_objectManager = $objectManager; + $this->scopeConfig = $scopeConfig; + $this->objectManager = $objectManager; + $this->enginePool = $engines; } /** @@ -49,28 +59,26 @@ class EngineProvider */ public function get() { - if (!$this->_engine) { - $engineClassName = $this->_scopeConfig->getValue(self::CONFIG_ENGINE_PATH, ScopeInterface::SCOPE_STORE); - - /** - * This needed if there already was saved in configuration some none-default engine - * and module of that engine was disabled after that. - * Problem is in this engine in database configuration still set. - */ - if ($engineClassName) { - $engine = $this->_objectManager->create($engineClassName); + if (!$this->engine) { + $currentEngine = $this->scopeConfig->getValue(self::CONFIG_ENGINE_PATH, ScopeInterface::SCOPE_STORE); + if (!isset($this->enginePool[$currentEngine])) { + throw new \LogicException( + 'There is no such engine: ' . $currentEngine + ); + } + $engineClassName = $this->enginePool[$currentEngine]; - if (false === $engine instanceof \Magento\CatalogSearch\Model\Resource\EngineInterface) { - throw new \LogicException( - $engineClassName . ' doesn\'t implement \Magento\CatalogSearch\Model\Resource\EngineInterface' - ); - } - if ($engine && $engine->test()) { - $this->_engine = $engine; - } + $engine = $this->objectManager->create($engineClassName); + if (false === $engine instanceof \Magento\CatalogSearch\Model\Resource\EngineInterface) { + throw new \LogicException( + $engineClassName . ' doesn\'t implement \Magento\CatalogSearch\Model\Resource\EngineInterface' + ); + } + if ($engine && $engine->test()) { + $this->engine = $engine; } } - return $this->_engine; + return $this->engine; } } diff --git a/app/code/Magento/CatalogSearch/Model/Resource/ResourceProvider.php b/app/code/Magento/CatalogSearch/Model/Resource/ResourceProvider.php deleted file mode 100644 index c18aa10f02c4349591c4a2c4e0affaa809b24068..0000000000000000000000000000000000000000 --- a/app/code/Magento/CatalogSearch/Model/Resource/ResourceProvider.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\CatalogSearch\Model\Resource; - -use Magento\Store\Model\ScopeInterface; - -class ResourceProvider -{ - /** - * Object Manager instance - * - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $objectManager = null; - - /** - * Array of resource factory names - * - * @var array - */ - protected $resourceFactoryNames; - - /** - * Engine used for search - * - * @var string - */ - protected $engineKey; - - /** - * Constructor - * - * @param \Magento\Framework\ObjectManagerInterface $objectManager - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param array $resourceFactoryNames - */ - public function __construct( - \Magento\Framework\ObjectManagerInterface $objectManager, - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - array $resourceFactoryNames - ) { - $this->objectManager = $objectManager; - $this->resourceFactoryNames = $resourceFactoryNames; - $this->engineKey = $scopeConfig->getValue(EngineProvider::CONFIG_ENGINE_PATH, ScopeInterface::SCOPE_STORE); - } - - /** - * @return \Magento\Framework\Model\Resource\AbstractResource - */ - public function getResource() - { - return $this->createResource('resource'); - } - - /** - * @return \Magento\CatalogSearch\Model\Resource\Advanced\Collection - */ - public function getResourceCollection() - { - return $this->createResource('resource_collection'); - } - - /** - * @return \Magento\CatalogSearch\Model\Resource\Fulltext\Collection - */ - public function getResultCollection() - { - return $this->createResource('result_collection'); - } - - /** - * @return \Magento\CatalogSearch\Model\Resource\Advanced\Collection - */ - public function getAdvancedResultCollection() - { - return $this->createResource('advanced_result_collection'); - } - - /** - * Create resource - * - * @param string $resourceKey - * @return mixed - */ - protected function createResource($resourceKey) - { - if (!isset($this->resourceFactoryNames[$this->engineKey][$resourceKey])) { - throw new \RuntimeException(__('Resource has not been set.')); - } - $factory = $this->objectManager->create($this->resourceFactoryNames[$this->engineKey][$resourceKey]); - return $factory->create(); - } -} diff --git a/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml b/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml index 6eea100e7396a76b33ab1de9890b2baf5da1e476..98b2123e03f5a327b30270ca2862d749d7db31dc 100644 --- a/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml +++ b/app/code/Magento/CatalogSearch/etc/adminhtml/system.xml @@ -16,6 +16,9 @@ </group> <group id="search" translate="label" type="text" sortOrder="500" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Catalog Search</label> + <field id="engine"> + <backend_model>Magento\CatalogSearch\Model\Adminhtml\System\Config\Backend\Engine</backend_model> + </field> <field id="min_query_length" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Minimal Query Length</label> <validate>validate-digits</validate> diff --git a/app/code/Magento/CatalogSearch/etc/config.xml b/app/code/Magento/CatalogSearch/etc/config.xml index 22ceebd32bac4b4cd0c499025d488e33322015e4..e6812e9c2629a7555da67222270e2f16db705ce1 100644 --- a/app/code/Magento/CatalogSearch/etc/config.xml +++ b/app/code/Magento/CatalogSearch/etc/config.xml @@ -12,7 +12,7 @@ <search_terms>1</search_terms> </seo> <search> - <engine>Magento\CatalogSearch\Model\Resource\Engine</engine> + <engine>mysql</engine> <min_query_length>1</min_query_length> <max_query_length>128</max_query_length> <use_layered_navigation_count>0</use_layered_navigation_count> diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml index e4c718050c3ffce84cd873a4adcfd7f01cefd03d..6e20a7176214251945e7fbe56e011e6655348782 100644 --- a/app/code/Magento/CatalogSearch/etc/di.xml +++ b/app/code/Magento/CatalogSearch/etc/di.xml @@ -10,6 +10,7 @@ <preference for="Magento\Framework\Search\Adapter\Mysql\Aggregation\DataProviderInterface" type="Magento\CatalogSearch\Model\Adapter\Mysql\Aggregation\DataProvider"/> <preference for="Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface" type="Magento\CatalogSearch\Model\Adapter\Mysql\Filter\Preprocessor" /> <preference for="Magento\Framework\Search\Dynamic\DataProviderInterface" type="Magento\CatalogSearch\Model\Adapter\Mysql\Dynamic\DataProvider" /> + <preference for="Magento\Framework\Search\Adapter\OptionsInterface" type="Magento\CatalogSearch\Model\Adapter\Options" /> <type name="Magento\Framework\Search\Adapter\Mysql\Aggregation\DataProviderContainer"> <arguments> <argument name="dataProviders" xsi:type="array"> @@ -70,11 +71,20 @@ </type> <type name="Magento\Framework\Search\Dynamic\IntervalFactory"> <arguments> - <argument name="configPath" xsi:type="const">\Magento\CatalogSearch\Model\Resource\EngineProvider::CONFIG_ENGINE_PATH</argument> + <argument name="configPath" xsi:type="const">Magento\CatalogSearch\Model\Resource\EngineProvider::CONFIG_ENGINE_PATH</argument> <argument name="intervals" xsi:type="array"> - <item name="Magento\CatalogSearch\Model\Resource\Engine" xsi:type="string">Magento\CatalogSearch\Model\Price\Interval</item> + <item name="mysql" xsi:type="string">Magento\Framework\Search\Adapter\Mysql\Aggregation\Interval</item> </argument> - <argument name="scope" xsi:type="const">\Magento\Store\Model\ScopeInterface::SCOPE_STORE</argument> + <argument name="scope" xsi:type="const">Magento\Store\Model\ScopeInterface::SCOPE_STORE</argument> + </arguments> + </type> + <type name="Magento\Framework\Search\Dynamic\DataProviderFactory"> + <arguments> + <argument name="configPath" xsi:type="const">Magento\CatalogSearch\Model\Resource\EngineProvider::CONFIG_ENGINE_PATH</argument> + <argument name="dataProviders" xsi:type="array"> + <item name="mysql" xsi:type="string">Magento\CatalogSearch\Model\Adapter\Mysql\Dynamic\DataProvider</item> + </argument> + <argument name="scope" xsi:type="const">Magento\Store\Model\ScopeInterface::SCOPE_STORE</argument> </arguments> </type> <type name="Magento\Backend\Controller\Adminhtml\Index\GlobalSearch"> @@ -116,16 +126,6 @@ <argument name="instanceName" xsi:type="string">Magento\CatalogSearch\Model\Resource\Fulltext\Collection</argument> </arguments> </virtualType> - <virtualType name="Magento\CatalogSearch\Model\Resource\Advanced\CollectionFactory" type="Magento\Catalog\Model\Resource\Product\CollectionFactory"> - <arguments> - <argument name="instanceName" xsi:type="string">Magento\CatalogSearch\Model\Resource\Advanced\Collection</argument> - </arguments> - </virtualType> - <virtualType name="Magento\CatalogSearch\Model\Resource\AdvancedFactory" type="Magento\Catalog\Model\Resource\Product\CollectionFactory"> - <arguments> - <argument name="instanceName" xsi:type="string">Magento\CatalogSearch\Model\Resource\Advanced</argument> - </arguments> - </virtualType> <type name="Magento\CatalogSearch\Model\Layer\Category\ItemCollectionProvider"> <arguments> <argument name="collectionFactory" xsi:type="object">Magento\CatalogSearch\Model\Resource\Fulltext\CollectionFactory</argument> @@ -136,11 +136,22 @@ <argument name="collectionFactory" xsi:type="object">Magento\CatalogSearch\Model\Resource\Fulltext\CollectionFactory</argument> </arguments> </virtualType> + <virtualType name="Magento\CatalogSearch\Model\Resource\Advanced\CollectionFactory" + type="Magento\Catalog\Model\Resource\Product\CollectionFactory"> + <arguments> + <argument name="instanceName" xsi:type="string">Magento\CatalogSearch\Model\Resource\Advanced\Collection</argument> + </arguments> + </virtualType> <virtualType name="Magento\CatalogSearch\Model\Layer\Advanced\ItemCollectionProvider" type="Magento\Catalog\Model\Layer\Search\ItemCollectionProvider"> <arguments> <argument name="collectionFactory" xsi:type="object">Magento\CatalogSearch\Model\Resource\Advanced\CollectionFactory</argument> </arguments> </virtualType> + <type name="Magento\CatalogSearch\Model\Advanced"> + <arguments> + <argument name="productCollectionFactory" xsi:type="object">Magento\CatalogSearch\Model\Resource\Advanced\CollectionFactory</argument> + </arguments> + </type> <virtualType name="Magento\CatalogSearch\Model\Layer\Category\Context" type="Magento\Catalog\Model\Layer\Category\Context"> <arguments> <argument name="collectionProvider" xsi:type="object">Magento\CatalogSearch\Model\Layer\Category\ItemCollectionProvider</argument> @@ -199,16 +210,23 @@ <argument name="attributePrefix" xsi:type="const">Magento\CatalogSearch\Model\Resource\Engine::ATTRIBUTE_PREFIX</argument> </arguments> </type> - - <type name="Magento\CatalogSearch\Model\Resource\ResourceProvider"> + <type name="Magento\CatalogSearch\Model\Resource\EngineProvider"> <arguments> - <argument name="resourceFactoryNames" xsi:type="array"> - <item name="Magento\CatalogSearch\Model\Resource\Engine" xsi:type="array"> - <item name="resource" xsi:type="string">Magento\CatalogSearch\Model\Resource\AdvancedFactory</item> - <item name="resource_collection" xsi:type="string">Magento\CatalogSearch\Model\Resource\Advanced\CollectionFactory</item> - <item name="result_collection" xsi:type="string">Magento\CatalogSearch\Model\Resource\Fulltext\CollectionFactory</item> - <item name="advanced_result_collection" xsi:type="string">Magento\CatalogSearch\Model\Resource\Advanced\CollectionFactory</item> - </item> + <argument name="engines" xsi:type="array"> + <item name="mysql" xsi:type="string">Magento\CatalogSearch\Model\Resource\Engine</item> + </argument> + </arguments> + </type> + <type name="Magento\Search\Model\AdapterFactory"> + <arguments> + <argument name="path" xsi:type="const">Magento\CatalogSearch\Model\Resource\EngineProvider::CONFIG_ENGINE_PATH</argument> + <argument name="scopeType" xsi:type="const">\Magento\Store\Model\ScopeInterface::SCOPE_STORE</argument> + </arguments> + </type> + <type name="Magento\Search\Model\Autocomplete"> + <arguments> + <argument name="dataProviders" xsi:type="array"> + <item name="10" xsi:type="object">Magento\CatalogSearch\Model\Autocomplete\DataProvider</item> </argument> </arguments> </type> diff --git a/app/code/Magento/CatalogSearch/etc/search_request.xml b/app/code/Magento/CatalogSearch/etc/search_request.xml index b2a0df87925ff1f94a0cee750a42ea6610ca18b7..5c224284a050fb9960992fb1a47689fe1fc6154b 100644 --- a/app/code/Magento/CatalogSearch/etc/search_request.xml +++ b/app/code/Magento/CatalogSearch/etc/search_request.xml @@ -19,7 +19,7 @@ <queryReference clause="must" ref="visibility"/> </query> <query xsi:type="matchQuery" value="$search_term$" name="search"> - <match field="name" boost="1"/> + <match field="sku" boost="1"/> </query> <query xsi:type="filteredQuery" name="category"> <filterReference clause="must" ref="category_filter"/> diff --git a/app/code/Magento/Checkout/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/Checkout/Model/Layout/DepersonalizePlugin.php index d45d8fbc78d64382d284e3fd5c0d0262412617e2..8726d579e4fea675a73466ab45dc4e4734346066 100644 --- a/app/code/Magento/Checkout/Model/Layout/DepersonalizePlugin.php +++ b/app/code/Magento/Checkout/Model/Layout/DepersonalizePlugin.php @@ -3,50 +3,35 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Checkout\Model\Layout; +use Magento\PageCache\Model\DepersonalizeChecker; + /** * Class DepersonalizePlugin */ class DepersonalizePlugin { /** - * @var \Magento\Checkout\Model\Session - */ - protected $checkoutSession; - - /** - * @var \Magento\Framework\Module\Manager - */ - protected $moduleManager; - - /** - * @var \Magento\Framework\App\RequestInterface + * @var DepersonalizeChecker */ - protected $request; + protected $depersonalizeChecker; /** - * @var \Magento\PageCache\Model\Config + * @var \Magento\Checkout\Model\Session */ - protected $cacheConfig; + protected $checkoutSession; /** + * @param DepersonalizeChecker $depersonalizeChecker * @param \Magento\Checkout\Model\Session $checkoutSession - * @param \Magento\Framework\Module\Manager $moduleManager - * @param \Magento\Framework\App\RequestInterface $request - * @param \Magento\PageCache\Model\Config $cacheConfig */ public function __construct( - \Magento\Checkout\Model\Session $checkoutSession, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\Framework\App\RequestInterface $request, - \Magento\PageCache\Model\Config $cacheConfig + DepersonalizeChecker $depersonalizeChecker, + \Magento\Checkout\Model\Session $checkoutSession ) { $this->checkoutSession = $checkoutSession; - $this->moduleManager = $moduleManager; - $this->request = $request; - $this->cacheConfig = $cacheConfig; + $this->depersonalizeChecker = $depersonalizeChecker; } /** @@ -58,11 +43,7 @@ class DepersonalizePlugin */ public function afterGenerateXml(\Magento\Framework\View\LayoutInterface $subject, $result) { - if ($this->moduleManager->isEnabled('Magento_PageCache') - && $this->cacheConfig->isEnabled() - && !$this->request->isAjax() - && $subject->isCacheable() - ) { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { $this->checkoutSession->clearStorage(); } return $result; diff --git a/app/code/Magento/ConfigurableProduct/Setup/InstallSchema.php b/app/code/Magento/ConfigurableProduct/Setup/InstallSchema.php index 6d4ac479646157bd8287f9353c592df7098c8a7a..51ce770c9aa042b6da48a047baa8752c3e67f706 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/InstallSchema.php +++ b/app/code/Magento/ConfigurableProduct/Setup/InstallSchema.php @@ -315,18 +315,6 @@ class InstallSchema implements InstallSchemaInterface $installer->getConnection()->createTable($table); - $table = $installer->getConnection() - ->addColumn( - $installer->getTable('catalog_eav_attribute'), - 'is_configurable', - [ - 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - 'unsigned' => true, - 'default' => null, - 'comment' => 'Can be used to create configurable product' - ] - ); - $installer->endSetup(); } diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeSchema.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeSchema.php deleted file mode 100644 index a16348e81cde8bd9c697236434f314c3263b0889..0000000000000000000000000000000000000000 --- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeSchema.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\ConfigurableProduct\Setup; - -use Magento\Framework\Setup\UpgradeSchemaInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\SchemaSetupInterface; - -/** - * @codeCoverageIgnore - */ -class UpgradeSchema implements UpgradeSchemaInterface -{ - /** - * {@inheritdoc} - */ - public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) - { - if (version_compare($context->getVersion(), '2.0.1') < 0) { - $installer = $setup; - - $installer->startSetup(); - - $installer->getConnection() - ->dropColumn( - $installer->getTable('catalog_eav_attribute'), - 'is_configurable' - ); - - $installer->endSetup(); - } - } -} diff --git a/app/code/Magento/ConfigurableProduct/etc/eav_attributes.xml b/app/code/Magento/ConfigurableProduct/etc/eav_attributes.xml deleted file mode 100644 index c8069b16392419e2762bcaf89670dcf0d6db859e..0000000000000000000000000000000000000000 --- a/app/code/Magento/ConfigurableProduct/etc/eav_attributes.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Eav/etc/eav_attributes.xsd"> - <entity type="catalog_product"> - <attribute code="status"> - <field code="is_configurable" locked="true" /> - </attribute> - <attribute code="visibility"> - <field code="is_configurable" locked="true" /> - </attribute> - </entity> -</config> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/attribute-js-template.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/attribute-js-template.phtml index 4ec8ac1d5036e5f01563b7970e88b69064f635a5..ffb0246382d04a4b777f46a05a4ffd3d544d7365 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/attribute-js-template.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/attribute-js-template.phtml @@ -9,7 +9,7 @@ /* @var $block \Magento\Framework\View\Element\Template */ ?> <script data-template-for="configurable-attribute" type="text/x-magento-template"> - <div class="entry-edit" data-role="configurable-attribute" data-attribute="<%= JSON.stringify(data.attribute) %>"> + <div class="entry-edit" data-role="configurable-attribute" data-attribute="<%- JSON.stringify(data.attribute) %>"> <input name="attributes[]" id="configurable_attribute_<%= data.attribute.id %>" value="<%= data.attribute.id %>" type="hidden"> <input value="new" type="hidden" diff --git a/app/code/Magento/Customer/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/Customer/Model/Layout/DepersonalizePlugin.php index c355bed23826e94795338b8ec53c10ea99532231..05ca2de151976c86ce56c93686b13cddc9594304 100644 --- a/app/code/Magento/Customer/Model/Layout/DepersonalizePlugin.php +++ b/app/code/Magento/Customer/Model/Layout/DepersonalizePlugin.php @@ -7,11 +7,18 @@ */ namespace Magento\Customer\Model\Layout; +use Magento\PageCache\Model\DepersonalizeChecker; + /** * Class DepersonalizePlugin */ class DepersonalizePlugin { + /** + * @var DepersonalizeChecker + */ + protected $depersonalizeChecker; + /** * @var \Magento\Framework\Session\SessionManagerInterface */ @@ -27,16 +34,6 @@ class DepersonalizePlugin */ protected $customerFactory; - /** - * @var \Magento\Framework\App\RequestInterface - */ - protected $request; - - /** - * @var \Magento\Framework\Module\Manager - */ - protected $moduleManager; - /** * @var \Magento\Customer\Model\Visitor */ @@ -53,35 +50,24 @@ class DepersonalizePlugin protected $formKey; /** - * @var \Magento\PageCache\Model\Config - */ - protected $cacheConfig; - - /** + * @param DepersonalizeChecker $depersonalizeChecker * @param \Magento\Framework\Session\SessionManagerInterface $session * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Customer\Model\CustomerFactory $customerFactory - * @param \Magento\Framework\App\RequestInterface $request - * @param \Magento\Framework\Module\Manager $moduleManager * @param \Magento\Customer\Model\Visitor $visitor - * @param \Magento\PageCache\Model\Config $cacheConfig */ public function __construct( + DepersonalizeChecker $depersonalizeChecker, \Magento\Framework\Session\SessionManagerInterface $session, \Magento\Customer\Model\Session $customerSession, \Magento\Customer\Model\CustomerFactory $customerFactory, - \Magento\Framework\App\RequestInterface $request, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\Customer\Model\Visitor $visitor, - \Magento\PageCache\Model\Config $cacheConfig + \Magento\Customer\Model\Visitor $visitor ) { $this->session = $session; $this->customerSession = $customerSession; $this->customerFactory = $customerFactory; - $this->request = $request; - $this->moduleManager = $moduleManager; $this->visitor = $visitor; - $this->cacheConfig = $cacheConfig; + $this->depersonalizeChecker = $depersonalizeChecker; } /** @@ -92,10 +78,7 @@ class DepersonalizePlugin */ public function beforeGenerateXml(\Magento\Framework\View\LayoutInterface $subject) { - if ($this->moduleManager->isEnabled( - 'Magento_PageCache' - ) && $this->cacheConfig->isEnabled() && !$this->request->isAjax() && $subject->isCacheable() - ) { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { $this->customerGroupId = $this->customerSession->getCustomerGroupId(); $this->formKey = $this->session->getData(\Magento\Framework\Data\Form\FormKey::FORM_KEY); } @@ -111,11 +94,7 @@ class DepersonalizePlugin */ public function afterGenerateXml(\Magento\Framework\View\LayoutInterface $subject, $result) { - if ($this->moduleManager->isEnabled('Magento_PageCache') - && $this->cacheConfig->isEnabled() - && !$this->request->isAjax() - && $subject->isCacheable() - ) { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { $this->visitor->setSkipRequestLogging(true); $this->visitor->unsetData(); $this->session->clearStorage(); diff --git a/app/code/Magento/PageCache/Model/DepersonalizeChecker.php b/app/code/Magento/PageCache/Model/DepersonalizeChecker.php new file mode 100644 index 0000000000000000000000000000000000000000..5837cccbc7d0924daf7185f0d428d0f0f6eabf2e --- /dev/null +++ b/app/code/Magento/PageCache/Model/DepersonalizeChecker.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\PageCache\Model; + +/** + * Checks if session should be depersonalized in Depersonalize plugin + */ +class DepersonalizeChecker +{ + /** + * Request + * + * @var \Magento\Framework\App\RequestInterface + */ + private $request; + + /** + * Module manager + * + * @var \Magento\Framework\Module\Manager + */ + private $moduleManager; + + /** + * Cache config + * + * @var Config + */ + private $cacheConfig; + + /** + * @param \Magento\Framework\App\RequestInterface $request + * @param \Magento\Framework\Module\Manager $moduleManager + * @param Config $cacheConfig + */ + public function __construct( + \Magento\Framework\App\RequestInterface $request, + \Magento\Framework\Module\Manager $moduleManager, + Config $cacheConfig + ) { + $this->request = $request; + $this->moduleManager = $moduleManager; + $this->cacheConfig = $cacheConfig; + } + + /** + * Check if depersonalize or not + * + * @param \Magento\Framework\View\LayoutInterface $subject + * @return bool + */ + public function checkIfDepersonalize(\Magento\Framework\View\LayoutInterface $subject) + { + return ($this->moduleManager->isEnabled('Magento_PageCache') + && $this->cacheConfig->isEnabled() + && !$this->request->isAjax() + && ($this->request->isGet() || $this->request->isHead()) + && $subject->isCacheable()); + } +} diff --git a/app/code/Magento/PageCache/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/PageCache/Model/Layout/DepersonalizePlugin.php index 79b5dcc9f84c698603d7e9885b0acbae88543669..930ceeb6bdc0c3e764d5c16d64375cf90c693f84 100644 --- a/app/code/Magento/PageCache/Model/Layout/DepersonalizePlugin.php +++ b/app/code/Magento/PageCache/Model/Layout/DepersonalizePlugin.php @@ -3,57 +3,42 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\PageCache\Model\Layout; +use Magento\PageCache\Model\DepersonalizeChecker; + /** * Class DepersonalizePlugin */ class DepersonalizePlugin { /** - * @var \Magento\Framework\App\RequestInterface - */ - protected $request; - - /** - * @var \Magento\Framework\Module\Manager + * @var DepersonalizeChecker */ - protected $moduleManager; + protected $depersonalizeChecker; /** * @var \Magento\Framework\Event\Manager */ protected $eventManager; - /** - * @var \Magento\PageCache\Model\Config - */ - protected $cacheConfig; - /** * @var \Magento\Framework\Message\Session */ protected $messageSession; /** - * @param \Magento\Framework\App\RequestInterface $request - * @param \Magento\Framework\Module\Manager $moduleManager + * @param DepersonalizeChecker $depersonalizeChecker * @param \Magento\Framework\Event\Manager $eventManager - * @param \Magento\PageCache\Model\Config $cacheConfig * @param \Magento\Framework\Message\Session $messageSession */ public function __construct( - \Magento\Framework\App\RequestInterface $request, - \Magento\Framework\Module\Manager $moduleManager, + DepersonalizeChecker $depersonalizeChecker, \Magento\Framework\Event\Manager $eventManager, - \Magento\PageCache\Model\Config $cacheConfig, \Magento\Framework\Message\Session $messageSession ) { - $this->request = $request; - $this->moduleManager = $moduleManager; + $this->depersonalizeChecker = $depersonalizeChecker; $this->eventManager = $eventManager; - $this->cacheConfig = $cacheConfig; $this->messageSession = $messageSession; } @@ -66,11 +51,7 @@ class DepersonalizePlugin */ public function afterGenerateXml(\Magento\Framework\View\LayoutInterface $subject, $result) { - if ($this->moduleManager->isEnabled('Magento_PageCache') - && $this->cacheConfig->isEnabled() - && !$this->request->isAjax() - && $subject->isCacheable() - ) { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { $this->eventManager->dispatch('depersonalize_clear_session'); session_write_close(); $this->messageSession->clearStorage(); diff --git a/app/code/Magento/PageCache/Model/Observer/InvalidateCacheIfChanged.php b/app/code/Magento/PageCache/Model/Observer/InvalidateCacheIfChanged.php new file mode 100644 index 0000000000000000000000000000000000000000..da5f388c6c79a899e389b191951c3866d6c5bbde --- /dev/null +++ b/app/code/Magento/PageCache/Model/Observer/InvalidateCacheIfChanged.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\PageCache\Model\Observer; + +/** + * An observer to invalidate full page cache when the content given is changed + */ +class InvalidateCacheIfChanged +{ + /** + * @var \Magento\Framework\App\Cache\TypeListInterface + */ + protected $typeList; + + /** + * Application config object + * + * @var \Magento\PageCache\Model\Config + */ + protected $config; + + /** + * @param \Magento\PageCache\Model\Config $config + * @param \Magento\Framework\App\Cache\TypeListInterface $typeList + */ + public function __construct( + \Magento\PageCache\Model\Config $config, + \Magento\Framework\App\Cache\TypeListInterface $typeList + ) { + $this->config = $config; + $this->typeList = $typeList; + } + + /** + * Invalidate full page cache if content is changed + * + * @param \Magento\Framework\Event\Observer $observer + * @return void + */ + public function execute(\Magento\Framework\Event\Observer $observer) + { + if ($this->config->isEnabled()) { + $object = $observer->getEvent()->getObject(); + if ($object instanceof \Magento\Framework\Object\IdentityInterface) { + if ($object->getIdentities()) { + $this->typeList->invalidate('full_page'); + } + } + } + } +} diff --git a/app/code/Magento/PageCache/etc/events.xml b/app/code/Magento/PageCache/etc/events.xml index 3be6c75f94f9b4e508ea31bfe9d1cfa78e7d5bf1..e368daf233a14f993694a1f7613f85ffb840c471 100644 --- a/app/code/Magento/PageCache/etc/events.xml +++ b/app/code/Magento/PageCache/etc/events.xml @@ -13,7 +13,7 @@ <observer name="invalidate_builtin" instance="Magento\PageCache\Model\Observer\FlushCacheByTags" method="execute" /> </event> <event name="clean_cache_after_reindex"> - <observer name="reindex_cache_flush" instance="Magento\PageCache\Model\Observer\InvalidateCache" method="execute" /> + <observer name="reindex_cache_flush" instance="Magento\PageCache\Model\Observer\InvalidateCacheIfChanged" method="execute" /> </event> <event name="adminhtml_cache_flush_system"> <observer name="flush_system_pagecache" instance="Magento\PageCache\Model\Observer\FlushAllCache" method="execute" /> diff --git a/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php index 850e262479daa1a5889b5144d87f69a6b617472d..b73ccc8b2275c669958bf5d2fd5cabde74b3b802 100644 --- a/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php +++ b/app/code/Magento/Persistent/Model/Layout/DepersonalizePlugin.php @@ -5,49 +5,35 @@ */ namespace Magento\Persistent\Model\Layout; +use Magento\PageCache\Model\DepersonalizeChecker; + /** * Class DepersonalizePlugin */ class DepersonalizePlugin { /** - * @var \Magento\Persistent\Model\Session - */ - protected $persistentSession; - - /** - * @var \Magento\Framework\App\RequestInterface + * @var DepersonalizeChecker */ - protected $request; + protected $depersonalizeChecker; /** - * @var \Magento\Framework\Module\Manager - */ - protected $moduleManager; - - /** - * @var \Magento\PageCache\Model\Config + * @var \Magento\Persistent\Model\Session */ - protected $cacheConfig; + protected $persistentSession; /** * Constructor * + * @param DepersonalizeChecker $depersonalizeChecker * @param \Magento\Persistent\Model\Session $persistentSession - * @param \Magento\Framework\App\RequestInterface $request - * @param \Magento\Framework\Module\Manager $moduleManager - * @param \Magento\PageCache\Model\Config $cacheConfig */ public function __construct( - \Magento\Persistent\Model\Session $persistentSession, - \Magento\Framework\App\RequestInterface $request, - \Magento\Framework\Module\Manager $moduleManager, - \Magento\PageCache\Model\Config $cacheConfig + DepersonalizeChecker $depersonalizeChecker, + \Magento\Persistent\Model\Session $persistentSession ) { $this->persistentSession = $persistentSession; - $this->request = $request; - $this->moduleManager = $moduleManager; - $this->cacheConfig = $cacheConfig; + $this->depersonalizeChecker = $depersonalizeChecker; } /** @@ -61,11 +47,7 @@ class DepersonalizePlugin \Magento\Framework\View\LayoutInterface $subject, \Magento\Framework\View\LayoutInterface $result ) { - if ($this->moduleManager->isEnabled('Magento_PageCache') - && $this->cacheConfig->isEnabled() - && !$this->request->isAjax() - && $subject->isCacheable() - ) { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { $this->persistentSession->setCustomerId(null); } diff --git a/app/code/Magento/Search/Controller/Ajax/Suggest.php b/app/code/Magento/Search/Controller/Ajax/Suggest.php index 6465add7eac01ef7e41daf62baa303d049367094..de76161e9f9b96173f0f04f78dbb592a6139b6c7 100644 --- a/app/code/Magento/Search/Controller/Ajax/Suggest.php +++ b/app/code/Magento/Search/Controller/Ajax/Suggest.php @@ -6,8 +6,28 @@ */ namespace Magento\Search\Controller\Ajax; +use Magento\Search\Model\AutocompleteInterface; +use Magento\Framework\App\Action\Context; + class Suggest extends \Magento\Framework\App\Action\Action { + /** + * @var AutocompleteInterface + */ + private $autocomplete; + + /** + * @param Context $context + * @param AutocompleteInterface $autocomplete + */ + public function __construct( + Context $context, + AutocompleteInterface $autocomplete + ) { + parent::__construct($context); + $this->autocomplete = $autocomplete; + } + /** * @return void */ @@ -15,9 +35,14 @@ class Suggest extends \Magento\Framework\App\Action\Action { if (!$this->getRequest()->getParam('q', false)) { $this->getResponse()->setRedirect($this->_url->getBaseUrl()); + return; } - $suggestData = $this->_objectManager->get('Magento\Search\Helper\Data')->getSuggestData(); - $this->getResponse()->representJson(json_encode($suggestData)); + $autocompleteData = $this->autocomplete->getItems(); + $responseData = []; + foreach ($autocompleteData as $resultItem) { + $responseData[] = $resultItem->toArray(); + } + $this->getResponse()->representJson(json_encode($responseData)); } } diff --git a/app/code/Magento/Search/Helper/Data.php b/app/code/Magento/Search/Helper/Data.php index 94958da6a15389726e79f06676405c72fd6f90bf..f29486cf034589a3524413d7c22a0ecbdb132e34 100644 --- a/app/code/Magento/Search/Helper/Data.php +++ b/app/code/Magento/Search/Helper/Data.php @@ -9,12 +9,10 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Helper\AbstractHelper; use Magento\Framework\App\Helper\Context; use Magento\Framework\Escaper; -use Magento\Framework\Filter\FilterManager; use Magento\Framework\Stdlib\String; use Magento\Store\Model\StoreManagerInterface; use Magento\Search\Model\Query as SearchQuery; use Magento\Search\Model\QueryFactory; -use Magento\Search\Model\Resource\Query\Collection; /** * Search helper @@ -54,6 +52,13 @@ class Data extends AbstractHelper */ protected $string; + /** + * Core store config + * + * @var ScopeConfigInterface + */ + protected $_scopeConfig; + /** * Query factory * @@ -66,11 +71,6 @@ class Data extends AbstractHelper */ protected $_escaper; - /** - * @var FilterManager - */ - protected $filter; - /** * @var \Magento\Store\Model\StoreManagerInterface */ @@ -83,7 +83,6 @@ class Data extends AbstractHelper * @param String $string * @param QueryFactory $queryFactory * @param Escaper $escaper - * @param FilterManager $filter * @param StoreManagerInterface $storeManager */ public function __construct( @@ -91,13 +90,12 @@ class Data extends AbstractHelper String $string, QueryFactory $queryFactory, Escaper $escaper, - FilterManager $filter, StoreManagerInterface $storeManager ) { $this->string = $string; + $this->_scopeConfig = $context->getScopeConfig(); $this->_queryFactory = $queryFactory; $this->_escaper = $escaper; - $this->filter = $filter; $this->_storeManager = $storeManager; parent::__construct($context); } @@ -124,16 +122,6 @@ class Data extends AbstractHelper return $this->_escaper->escapeHtml($this->_queryFactory->get()->getQueryText()); } - /** - * Retrieve suggest collection for query - * - * @return Collection - */ - public function getSuggestCollection() - { - return $this->_queryFactory->get()->getSuggestCollection(); - } - /** * Retrieve result page url and set "secure" param to avoid confirm * message when we submit form from secure page to unsecure @@ -180,7 +168,7 @@ class Data extends AbstractHelper */ public function getMinQueryLength($store = null) { - return $this->scopeConfig->getValue( + return $this->_scopeConfig->getValue( SearchQuery::XML_PATH_MIN_QUERY_LENGTH, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store @@ -195,7 +183,7 @@ class Data extends AbstractHelper */ public function getMaxQueryLength($store = null) { - return $this->scopeConfig->getValue( + return $this->_scopeConfig->getValue( SearchQuery::XML_PATH_MAX_QUERY_LENGTH, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store @@ -278,34 +266,6 @@ class Data extends AbstractHelper return join($separator, array_filter($_index)); } - /** - * @return array - */ - public function getSuggestData() - { - if (!$this->_suggestData) { - $collection = $this->getSuggestCollection(); - $query = $this->_queryFactory->get()->getQueryText(); - $counter = 0; - $data = []; - foreach ($collection as $item) { - $_data = [ - 'title' => $item->getQueryText(), - 'row_class' => ++$counter % 2 ? 'odd' : 'even', - 'num_of_results' => $item->getNumResults(), - ]; - - if ($item->getQueryText() == $query) { - array_unshift($data, $_data); - } else { - $data[] = $_data; - } - } - $this->_suggestData = $data; - } - return $this->_suggestData; - } - /** * @return string */ diff --git a/app/code/Magento/Search/Model/AdapterFactory.php b/app/code/Magento/Search/Model/AdapterFactory.php index 8d480f67dceab2d53c0df631ea79af5009483e5c..742e527e210a630f54c7aa680b4a2a4d850c02c6 100644 --- a/app/code/Magento/Search/Model/AdapterFactory.php +++ b/app/code/Magento/Search/Model/AdapterFactory.php @@ -33,20 +33,30 @@ class AdapterFactory */ protected $scope; + /** + * Pool of existing adapters + * + * @var array + */ + private $adapterPool; + /** * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param array $adapters * @param string $path * @param string $scopeType */ public function __construct( \Magento\Framework\ObjectManagerInterface $objectManager, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, + array $adapters, $path, $scopeType ) { $this->objectManager = $objectManager; $this->scopeConfig = $scopeConfig; + $this->adapterPool = $adapters; $this->path = $path; $this->scope = $scopeType; } @@ -59,7 +69,13 @@ class AdapterFactory */ public function create(array $data = []) { - $adapterClass = $this->scopeConfig->getValue($this->path, $this->scope); + $currentAdapter = $this->scopeConfig->getValue($this->path, $this->scope); + if (!isset($this->adapterPool[$currentAdapter])) { + throw new \LogicException( + 'There is no such adapter: ' . $currentAdapter + ); + } + $adapterClass = $this->adapterPool[$currentAdapter]; $adapter = $this->objectManager->create($adapterClass, $data); if (!($adapter instanceof \Magento\Framework\Search\AdapterInterface)) { throw new \InvalidArgumentException( diff --git a/app/code/Magento/Search/Model/Adminhtml/System/Config/Source/Engine.php b/app/code/Magento/Search/Model/Adminhtml/System/Config/Source/Engine.php new file mode 100644 index 0000000000000000000000000000000000000000..ee42aad0903c21dbff49d6129b90c1a971f752aa --- /dev/null +++ b/app/code/Magento/Search/Model/Adminhtml/System/Config/Source/Engine.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Search\Model\Adminhtml\System\Config\Source; + +/** + * All registered search adapters + * + * @author Magento Core Team <core@magentocommerce.com> + */ +class Engine implements \Magento\Framework\Option\ArrayInterface +{ + /** + * Engines list + * + * @var array + */ + private $engines; + + /** + * Construct + * + * @param array $engines + */ + public function __construct( + array $engines + ) { + $this->engines = $engines; + } + + /** + * {@inheritdoc} + */ + public function toOptionArray() + { + $options = []; + foreach ($this->engines as $key => $label) { + $options[] = ['value' => $key, 'label' => $label]; + } + return $options; + } +} diff --git a/app/code/Magento/Search/Model/Autocomplete.php b/app/code/Magento/Search/Model/Autocomplete.php new file mode 100644 index 0000000000000000000000000000000000000000..0db0f89ad7d5ca2a600f9eb215104240528a87cb --- /dev/null +++ b/app/code/Magento/Search/Model/Autocomplete.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Search\Model; + +class Autocomplete implements AutocompleteInterface +{ + /** + * @var Autocomplete\DataProviderInterface[] + */ + private $dataProviders; + + /** + * @param array $dataProviders + */ + public function __construct( + array $dataProviders + ) { + $this->dataProviders = $dataProviders; + ksort($this->dataProviders); + } + + /** + * {@inheritdoc} + */ + public function getItems() + { + $data = []; + foreach ($this->dataProviders as $dataProvider) { + $data = array_merge($data, $dataProvider->getItems()); + } + + return $data; + } +} diff --git a/app/code/Magento/Search/Model/Autocomplete/DataProviderInterface.php b/app/code/Magento/Search/Model/Autocomplete/DataProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..3dd28f21a743e7a17ab53776615e13a5f1fdaccb --- /dev/null +++ b/app/code/Magento/Search/Model/Autocomplete/DataProviderInterface.php @@ -0,0 +1,15 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Search\Model\Autocomplete; + +interface DataProviderInterface +{ + /** + * @return ItemInterface[] + */ + public function getItems(); +} diff --git a/app/code/Magento/Search/Model/Autocomplete/Item.php b/app/code/Magento/Search/Model/Autocomplete/Item.php new file mode 100644 index 0000000000000000000000000000000000000000..7113b795d137c2ed1e3bd49214079154c77ebff6 --- /dev/null +++ b/app/code/Magento/Search/Model/Autocomplete/Item.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Search\Model\Autocomplete; + +class Item extends \Magento\Framework\Object implements ItemInterface +{ + /** + * {@inheritdoc} + */ + public function getTitle() + { + return $this->_getData('title'); + } +} diff --git a/app/code/Magento/Search/Model/Autocomplete/ItemFactory.php b/app/code/Magento/Search/Model/Autocomplete/ItemFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..e09f507ec06ba698da064ae3a6405d7b349a94b7 --- /dev/null +++ b/app/code/Magento/Search/Model/Autocomplete/ItemFactory.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Search\Model\Autocomplete; + +use Magento\Framework\ObjectManagerInterface; + +class ItemFactory +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @param ObjectManagerInterface $objectManager + */ + public function __construct( + ObjectManagerInterface $objectManager + ) { + $this->objectManager = $objectManager; + } + + /** + * @param array $data + * @return Item + */ + public function create(array $data) + { + return $this->objectManager->create('\Magento\Search\Model\Autocomplete\Item', ['data' => $data]); + } +} diff --git a/app/code/Magento/Search/Model/Autocomplete/ItemInterface.php b/app/code/Magento/Search/Model/Autocomplete/ItemInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a69753c048d4e2a9be93101ed68552f2dfa1b381 --- /dev/null +++ b/app/code/Magento/Search/Model/Autocomplete/ItemInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Search\Model\Autocomplete; + +interface ItemInterface +{ + /** + * @return string + */ + public function getTitle(); + + /** + * @return array + */ + public function toArray(); +} diff --git a/app/code/Magento/Search/Model/AutocompleteInterface.php b/app/code/Magento/Search/Model/AutocompleteInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..181568df635b1875fda319616d43e3eba4b5222e --- /dev/null +++ b/app/code/Magento/Search/Model/AutocompleteInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Search\Model; + +use Magento\Search\Model\Autocomplete\ItemInterface; + +interface AutocompleteInterface +{ + /** + * @return ItemInterface[] + */ + public function getItems(); +} diff --git a/app/code/Magento/Search/etc/adminhtml/system.xml b/app/code/Magento/Search/etc/adminhtml/system.xml new file mode 100644 index 0000000000000000000000000000000000000000..e13489ef12965eb4410f965b93578adb5a7e519a --- /dev/null +++ b/app/code/Magento/Search/etc/adminhtml/system.xml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Config/etc/system_file.xsd"> + <system> + <section id="catalog"> + <group id="search"> + <field id="engine" translate="label" type="select" sortOrder="19" showInDefault="1" showInWebsite="0" showInStore="0"> + <label>Search Engine</label> + <source_model>Magento\Search\Model\Adminhtml\System\Config\Source\Engine</source_model> + </field> + <field id="search_type"> + <depends> + <field id="engine">mysql</field> + </depends> + </field> + <field id="use_layered_navigation_count"> + <depends> + <field id="engine">mysql</field> + </depends> + </field> + </group> + </section> + </system> +</config> diff --git a/app/code/Magento/Search/etc/config.xml b/app/code/Magento/Search/etc/config.xml deleted file mode 100644 index 0608bfe0b0e1149e9070e8472630099e409c1505..0000000000000000000000000000000000000000 --- a/app/code/Magento/Search/etc/config.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Core/etc/config.xsd"> - <default> - <catalog> - <search> - <adapter>Magento\Framework\Search\Adapter\Mysql\Adapter</adapter> - </search> - </catalog> - </default> -</config> \ No newline at end of file diff --git a/app/code/Magento/Search/etc/di.xml b/app/code/Magento/Search/etc/di.xml index 2ef57e4f699fd5f5c0f5a5b2ec49931f7b4ef340..83b4b96571050d3ce54dce583e222364f1f9bea4 100644 --- a/app/code/Magento/Search/etc/di.xml +++ b/app/code/Magento/Search/etc/di.xml @@ -16,10 +16,20 @@ </type> <type name="Magento\Search\Model\AdapterFactory"> <arguments> - <argument name="path" xsi:type="string">catalog/search/adapter</argument> - <argument name="scopeType" xsi:type="const">\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT</argument> + <argument name="adapters" xsi:type="array"> + <item name="mysql" xsi:type="string">Magento\Framework\Search\Adapter\Mysql\Adapter</item> + </argument> </arguments> </type> <preference for="Magento\Search\Model\QueryFactoryInterface" type="Magento\Search\Model\QueryFactory" /> <preference for="Magento\Search\Model\QueryInterface" type="Magento\Search\Model\Query" /> + <type name="Magento\Search\Model\Adminhtml\System\Config\Source\Engine"> + <arguments> + <argument name="engines" xsi:type="array"> + <item name="mysql" xsi:type="string">MySQL</item> + </argument> + </arguments> + </type> + <preference for="Magento\Search\Model\AutocompleteInterface" type="Magento\Search\Model\Autocomplete" /> + <preference for="Magento\Search\Model\Autocomplete\ItemInterface" type="Magento\Search\Model\Autocomplete\Item" /> </config> diff --git a/app/code/Magento/Search/view/frontend/web/form-mini.js b/app/code/Magento/Search/view/frontend/web/form-mini.js index 8ac2fb72632e2202695bb5b561282a2fbd9a3edf..871edd66681497704ab6ec92b93175cd352339e3 100644 --- a/app/code/Magento/Search/view/frontend/web/form-mini.js +++ b/app/code/Magento/Search/view/frontend/web/form-mini.js @@ -29,14 +29,14 @@ define([ responseFieldElements: 'ul li', selectClass: 'selected', template: - '<li class="<%= data.row_class %>" id="qs-option-<%= data.index %>" role="option">' + - '<span class="qs-option-name">' + - ' <%= data.title %>' + - '</span>' + - '<span aria-hidden="true" class="amount">' + - '<%= data.num_of_results %>' + - '</span>' + - '</li>', + '<li class="<%= data.row_class %>" id="qs-option-<%= data.index %>" role="option">' + + '<span class="qs-option-name">' + + ' <%= data.title %>' + + '</span>' + + '<span aria-hidden="true" class="amount">' + + '<%= data.num_results %>' + + '</span>' + + '</li>', submitBtn: 'button[type="submit"]', searchLabel: '[data-role=minisearch-label]' }, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml index 6368a7edb24a6d4eac80da9d0a3c5c90c3fdd0ba..0562055a8c5ad9f034875f10a1a3d94066879ddc 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml @@ -19,7 +19,6 @@ <field name="attribute_code" xsi:type="string">attribute_dropdown%isolation%</field> <field name="frontend_input" xsi:type="string">Dropdown</field> <field name="is_required" xsi:type="string">No</field> - <field name="is_configurable" xsi:type="string">Yes</field> <field name="options" xsi:type="array"> <item name="0" xsi:type="array"> <item name="is_default" xsi:type="string">Yes</item> @@ -44,7 +43,6 @@ <field name="attribute_code" xsi:type="string">attribute_dropdown%isolation%</field> <field name="frontend_input" xsi:type="string">Dropdown</field> <field name="is_required" xsi:type="string">No</field> - <field name="is_configurable" xsi:type="string">Yes</field> <field name="options" xsi:type="array"> <item name="0" xsi:type="array"> <item name="is_default" xsi:type="string">Yes</item> @@ -64,7 +62,6 @@ <field name="attribute_code" xsi:type="string">attribute_dropdown%isolation%</field> <field name="frontend_input" xsi:type="string">Dropdown</field> <field name="is_required" xsi:type="string">No</field> - <field name="is_configurable" xsi:type="string">Yes</field> <field name="options" xsi:type="array"> <item name="0" xsi:type="array"> <item name="is_default" xsi:type="string">Yes</item> @@ -79,7 +76,6 @@ <field name="attribute_code" xsi:type="string">color_%isolation%</field> <field name="frontend_input" xsi:type="string">Dropdown</field> <field name="is_required" xsi:type="string">No</field> - <field name="is_configurable" xsi:type="string">Yes</field> <field name="options" xsi:type="array"> <item name="0" xsi:type="array"> <item name="is_default" xsi:type="string">Yes</item> @@ -99,7 +95,6 @@ <field name="attribute_code" xsi:type="string">size_%isolation%</field> <field name="frontend_input" xsi:type="string">Dropdown</field> <field name="is_required" xsi:type="string">No</field> - <field name="is_configurable" xsi:type="string">Yes</field> <field name="options" xsi:type="array"> <item name="0" xsi:type="array"> <item name="is_default" xsi:type="string">Yes</item> @@ -124,7 +119,6 @@ <field name="attribute_code" xsi:type="string">attribute_dropdown%isolation%</field> <field name="frontend_input" xsi:type="string">Dropdown</field> <field name="is_required" xsi:type="string">Yes</field> - <field name="is_configurable" xsi:type="string">Yes</field> <field name="is_filterable" xsi:type="string">Filterable (with results)</field> <field name="options" xsi:type="array"> <item name="0" xsi:type="array"> diff --git a/dev/tests/integration/phpunit.xml.dist b/dev/tests/integration/phpunit.xml.dist index 120994409138e3213a36c9c71166fa191225e793..222f10815b65ca38c55c8330ba1df90a5e45de08 100644 --- a/dev/tests/integration/phpunit.xml.dist +++ b/dev/tests/integration/phpunit.xml.dist @@ -37,6 +37,8 @@ <ini name="xdebug.max_nesting_level" value="200"/> <!-- Local XML configuration file ('.dist' extension will be added, if the specified file doesn't exist) --> <const name="TESTS_INSTALL_CONFIG_FILE" value="etc/install-config-mysql.php"/> + <!-- Local XML configuration file ('.dist' extension will be added, if the specified file doesn't exist) --> + <const name="TESTS_GLOBAL_CONFIG_FILE" value="etc/config-global.php"/> <!-- Semicolon-separated 'glob' patterns, that match global XML configuration files --> <const name="TESTS_GLOBAL_CONFIG_DIR" value="../../../app/etc"/> <!-- Whether to cleanup the application before running tests or not --> diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmAdvancedTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmAdvancedTest.php index d7ff5a2064c96c36221e24753e87511b61dcfe8e..ade70e848efd262d5c01cc89fa2a2806442340a2 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmAdvancedTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmAdvancedTest.php @@ -18,7 +18,7 @@ class AlgorithmAdvancedTest extends \PHPUnit_Framework_TestCase /** * @magentoDbIsolation enabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @covers \Magento\Framework\Search\Dynamic\Algorithm::calculateSeparators */ public function testWithoutLimits() @@ -90,7 +90,7 @@ class AlgorithmAdvancedTest extends \PHPUnit_Framework_TestCase /** * @magentoDbIsolation enabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @covers \Magento\Framework\Search\Dynamic\Algorithm::calculateSeparators */ public function testWithLimits() diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmBaseTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmBaseTest.php index 448b3b5fd14382abc8de1dcbb05be3f1ebc151a8..ccab86302b981284960689f68a34d8c4a274fed9 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmBaseTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Layer/Filter/Price/AlgorithmBaseTest.php @@ -36,7 +36,7 @@ class AlgorithmBaseTest extends \PHPUnit_Framework_TestCase /** * @magentoDbIsolation enabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @dataProvider pricesSegmentationDataProvider * @covers \Magento\Framework\Search\Dynamic\Algorithm::calculateSeparators */ diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php index 8fc949b02dae32d688e313f9700cf5b902321868..f54d376db44d1507fa7518a73b31317d3ed1c300 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Model/Indexer/FulltextTest.php @@ -5,6 +5,9 @@ */ namespace Magento\CatalogSearch\Model\Indexer; +use Magento\CatalogSearch\Model\Resource\Fulltext\Collection; +use Magento\TestFramework\Helper\Bootstrap; + /** * @magentoDbIsolation disabled * @magentoDataFixture Magento/CatalogSearch/_files/indexer_fulltext.php @@ -58,32 +61,23 @@ class FulltextTest extends \PHPUnit_Framework_TestCase */ protected $productCherry; - /** - * @var \Magento\CatalogSearch\Model\Resource\ResourceProvider - */ - protected $resourceProvider; - protected function setUp() { /** @var \Magento\Indexer\Model\IndexerInterface indexer */ - $this->indexer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + $this->indexer = Bootstrap::getObjectManager()->create( 'Magento\Indexer\Model\Indexer' ); $this->indexer->load('catalogsearch_fulltext'); - $this->engine = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + $this->engine = Bootstrap::getObjectManager()->get( 'Magento\CatalogSearch\Model\Resource\Engine' ); - $this->resourceFulltext = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + $this->resourceFulltext = Bootstrap::getObjectManager()->get( 'Magento\CatalogSearch\Model\Resource\Fulltext' ); - $this->resourceProvider = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( - '\Magento\CatalogSearch\Model\Resource\ResourceProvider' - ); - - $this->queryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + $this->queryFactory = Bootstrap::getObjectManager()->get( 'Magento\Search\Model\QueryFactory' ); @@ -153,7 +147,7 @@ class FulltextTest extends \PHPUnit_Framework_TestCase ]; /** @var \Magento\Catalog\Model\Product\Action $action */ - $action = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + $action = Bootstrap::getObjectManager()->get( 'Magento\Catalog\Model\Product\Action' ); $action->updateAttributes($productIds, $attrData, 1); @@ -210,7 +204,7 @@ class FulltextTest extends \PHPUnit_Framework_TestCase $query = $this->queryFactory->get(); $query->unsetData()->setQueryText($text)->prepare(); $products = []; - $collection = $this->resourceProvider->getResultCollection(); + $collection = Bootstrap::getObjectManager()->create(Collection::class); $collection->addSearchFilter($text); foreach ($collection as $product) { $products[] = $product; @@ -227,7 +221,7 @@ class FulltextTest extends \PHPUnit_Framework_TestCase protected function getProductBySku($sku) { /** @var \Magento\Catalog\Model\Product $product */ - $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + $product = Bootstrap::getObjectManager()->get( 'Magento\Catalog\Model\Product' ); return $product->loadByAttribute('sku', $sku); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php index a09fe3bb5c715faae282b549a115485bdc87c5fe..f378bb929e0aaddb26a649b91afdf5b056b1b857 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php @@ -52,7 +52,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -98,7 +98,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -121,7 +121,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -142,7 +142,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -161,7 +161,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -179,7 +179,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -197,7 +197,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -216,7 +216,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -234,7 +234,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -252,7 +252,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -284,7 +284,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -311,7 +311,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ @@ -339,7 +339,7 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * @dataProvider advancedSearchDataProvider * @magentoDbIsolation disabled * @magentoAppIsolation enabled - * @magentoConfigFixture current_store catalog/search/engine Magento\CatalogSearch\Model\Resource\Engine + * @magentoConfigFixture current_store catalog/search/engine mysql * @magentoConfigFixture current_store catalog/search/search_type 2 * @magentoDataFixture Magento/Framework/Search/_files/products.php */ diff --git a/dev/tests/integration/testsuite/Magento/Search/Model/Adminhtml/System/Config/Source/EngineTest.php b/dev/tests/integration/testsuite/Magento/Search/Model/Adminhtml/System/Config/Source/EngineTest.php new file mode 100644 index 0000000000000000000000000000000000000000..59728749127cbb5b694ae97296a584ebac6ab2d1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Search/Model/Adminhtml/System/Config/Source/EngineTest.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Search\Model\Adminhtml\System\Config\Source; + +/** + * @magentoAppArea adminhtml + */ +class EngineTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Search\Model\Adminhtml\System\Config\Source\Engine + */ + protected $_model; + + protected function setUp() + { + parent::setUp(); + $this->_model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\Search\Model\Adminhtml\System\Config\Source\Engine' + ); + } + + public function testToOptionArray() + { + $options = $this->_model->toOptionArray(); + $this->assertNotEmpty($options); + + foreach ($options as $option) { + $this->assertArrayHasKey('label', $option); + $this->assertArrayHasKey('value', $option); + } + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php index 102e4097cdf517e61870170264460613687b144f..2cbd11a348fe259e0591cc86f395914b63fbc1ed 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php @@ -534,9 +534,16 @@ class ClassesTest extends \PHPUnit_Framework_TestCase $errors = []; foreach ($files->getFiles([BP . '/dev/tests/{integration,unit}'], '*') as $file) { $code = file_get_contents($file); - if (preg_match('/@covers(DefaultClass)?\s+([\w\\\\]+)(::([\w\\\\]+))?/', $code, $matches)) { - if ($this->isNonexistentEntityCovered($matches)) { - $errors[] = $file . ': ' . $matches[0]; + if (preg_match_all( + '/@covers(DefaultClass)?\s+([\w\\\\]+)(::([\w\\\\]+))?/', + $code, + $matchesAll, + PREG_SET_ORDER + )) { + foreach ($matchesAll as $matches) { + if ($this->isNonexistentEntityCovered($matches)) { + $errors[] = $file . ': ' . $matches[0]; + } } } } diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php index 2ab9b5c8f8b33fe20ee205e215ef9d1a7946cc5f..9555448ca26cf48e2c5d092fbbb689f8a4a1192f 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Xml/SchemaTest.php @@ -81,6 +81,8 @@ class SchemaTest extends \PHPUnit_Framework_TestCase { $list = [ '#Dhl/etc/countries.xml$#', + '#conf/schema.xml$#', + '#conf/solrconfig.xml$#', ]; foreach ($list as $pattern) { foreach ($files as $key => $value) { diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php index a2404c455dadb341d927c2fee051d1a1d98cfff3..ac1049b5672b073247eec732ad8f9953aa8e644b 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php @@ -792,7 +792,6 @@ return [ ['Mage_Core_Model_Config_System'], ['Mage_Core_Model_Design_Source_Apply'], ['Mage_Core_Model_Language'], - ['Magento\Core\Helper\Data'], ['Magento\Core\Model\Flag', 'Magento\Framework\Flag'], ['Magento\Framework\Model\Exception', 'Magento\Framework\Exception\LocalizedException'], ['Magento\Core\Model\AbstractModel', 'Magento\Framework\Model\AbstractModel'], @@ -1369,6 +1368,8 @@ return [ ['Magento\Core\Model\Module\Declaration\FileResolver'], ['Magento\Core\Model\Module\Declaration\SchemaLocator'], ['Magento\Core\Model\Module\Dir\ReverseResolver'], + ['Magento\Core\Model\Module\ResourceResolver'], + ['Magento\Core\Model\Module\ResourceResolverInterface'], ['Magento\Core\Model\Resource\SetupInterface'], ['Magento\Core\Model\Db\UpdaterInterface'], ['Magento\Core\Model\Router\NoRouteHandlerInterface'], @@ -1382,8 +1383,6 @@ return [ ['Magento\Quote\Model\Resource\Quote\Address\Attribute\Backend\Parent'], ['Magento\Core\Helper\Http'], ['Magento\Core\Helper\Theme', 'Magento\Theme\Helper\Theme'], - ['Magento\Core\Helper\Url', 'Magento\Framework\Url\Helper\Data'], - ['Magento\Core\Helper\PostData', 'Magento\Framework\Data\Helper\PostHelper'], ['Magento\Core\Model\Theme', 'Magento\Theme\Model\Theme'], ['Magento\Core\Model\Theme\Collection', 'Magento\Theme\Model\Theme\Collection'], ['Magento\Core\Model\Theme\Data', 'Magento\Theme\Model\Theme\Data'], @@ -1662,7 +1661,7 @@ return [ ['Magento\Core\Block\Text\TextList\Link', 'Magento\Framework\View\Element\Text\TextList\Link'], ['Magento\Core\Block\Messages', 'Magento\Framework\View\Element\Messages'], ['Magento\Core\Model\Message', 'Magento\Framework\Message\Factory'], - ['Magento\Core\Model\Resource\Setup'], + ['Magento\Core\Model\Resource\Setup', 'Magento\Theme\Model\Resource\Setup'], ['Magento\Core\Model\Message\AbstractMessage', 'Magento\Framework\Message\AbstractMessage'], ['Magento\Core\Model\Message\Collection', 'Magento\Framework\Message\Collection'], ['Magento\Core\Model\Message\CollectionFactory', 'Magento\Framework\Message\CollectionFactory'], @@ -3099,4 +3098,5 @@ return [ ['Magento\Framework\Module\Updater'], ['Magento\Setup\Module\SetupFactory'], ['Magento\Framework\Module\Updater\SetupFactory'], + ['Magento\Backend\Model\Config\Source\Yesno', 'Magento\Config\Model\Config\Source\Yesno'], ]; diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Layout/DepersonalizePluginTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Layout/DepersonalizePluginTest.php index e3785dc0597438b0d723a5cfe4ffe143a504d6c5..ab1f05a08b4c7a680709ac43dc0c50d5a2ae490c 100644 --- a/dev/tests/unit/testsuite/Magento/Catalog/Model/Layout/DepersonalizePluginTest.php +++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Layout/DepersonalizePluginTest.php @@ -17,30 +17,15 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase */ protected $plugin; - /** - * @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $layoutMock; - /** * @var \Magento\Catalog\Model\Session|\PHPUnit_Framework_MockObject_MockObject */ protected $catalogSessionMock; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - - /** - * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\PageCache\Model\DepersonalizeChecker|\PHPUnit_Framework_MockObject_MockObject */ - protected $moduleManagerMock; - - /** - * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject - */ - protected $cacheConfigMock; + protected $depersonalizeCheckerMock; /** * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject @@ -56,82 +41,33 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase '', false ); - $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - $this->moduleManagerMock = $this->getMock('Magento\Framework\Module\Manager', [], [], '', false); - $this->cacheConfigMock = $this->getMock('Magento\PageCache\Model\Config', [], [], '', false); $this->resultLayout = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); + $this->depersonalizeCheckerMock = $this->getMock( + 'Magento\PageCache\Model\DepersonalizeChecker', + [], + [], + '', + false + ); - $this->plugin = (new ObjectManager($this))->getObject('Magento\Catalog\Model\Layout\DepersonalizePlugin', [ - 'catalogSession' => $this->catalogSessionMock, - 'moduleManager' => $this->moduleManagerMock, - 'request' => $this->requestMock, - 'cacheConfig' => $this->cacheConfigMock - ]); + $this->plugin = (new ObjectManager($this))->getObject( + 'Magento\Catalog\Model\Layout\DepersonalizePlugin', + ['catalogSession' => $this->catalogSessionMock, 'depersonalizeChecker' => $this->depersonalizeCheckerMock] + ); } public function testAfterGenerateXml() { - $this->moduleManagerMock->expects($this->once())->method('isEnabled')->with('Magento_PageCache') - ->willReturn(true); - $this->cacheConfigMock->expects($this->once())->method('isEnabled')->willReturn(true); - $this->requestMock->expects($this->once($this->once()))->method('isAjax')->willReturn(false); - $this->layoutMock->expects($this->once())->method('isCacheable')->willReturn(true); $this->catalogSessionMock->expects($this->once())->method('clearStorage'); - - $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $this->resultLayout); - $this->assertEquals($this->resultLayout, $actualResult); - } - - public function testPageCacheModuleIsDisabled() - { - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->willReturn(false); - $this->catalogSessionMock->expects($this->never())->method('clearStorage'); - + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(true); $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $this->resultLayout); $this->assertEquals($this->resultLayout, $actualResult); } - public function testCacheIsDisabledInConfig() + public function testAfterGenerateXmlNoDepersonalize() { - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->willReturn(true); - $this->cacheConfigMock->expects($this->once())->method('isEnabled')->willReturn(false); $this->catalogSessionMock->expects($this->never())->method('clearStorage'); - - $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $this->resultLayout); - $this->assertEquals($this->resultLayout, $actualResult); - } - - public function testIsAjax() - { - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->willReturn(true); - $this->cacheConfigMock->expects($this->once())->method('isEnabled')->willReturn(true); - $this->requestMock->expects($this->once($this->once()))->method('isAjax')->willReturn(true); - $this->catalogSessionMock->expects($this->never())->method('clearStorage'); - - $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $this->resultLayout); - $this->assertEquals($this->resultLayout, $actualResult); - } - - public function testLayoutIsNotCacheable() - { - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->willReturn(true); - $this->cacheConfigMock->expects($this->once())->method('isEnabled')->willReturn(true); - $this->requestMock->expects($this->once($this->once()))->method('isAjax')->willReturn(false); - $this->layoutMock->expects($this->once())->method('isCacheable')->willReturn(false); - $this->catalogSessionMock->expects($this->never())->method('clearStorage'); - + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(false); $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $this->resultLayout); $this->assertEquals($this->resultLayout, $actualResult); } diff --git a/dev/tests/unit/testsuite/Magento/CatalogSearch/Helper/DataTest.php b/dev/tests/unit/testsuite/Magento/CatalogSearch/Helper/DataTest.php index 5887e064778652409f8f774dc7c942dfeb14887f..0d452291e7c5435a202423f9d5b0932fea027755 100644 --- a/dev/tests/unit/testsuite/Magento/CatalogSearch/Helper/DataTest.php +++ b/dev/tests/unit/testsuite/Magento/CatalogSearch/Helper/DataTest.php @@ -11,24 +11,57 @@ namespace Magento\CatalogSearch\Helper; class DataTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\CatalogSearch\Helper\Data + * @var \Magento\CatalogSearch\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ protected $_model; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\App\Helper\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_contextMock; + + /** + * @var \Magento\Framework\Stdlib\String|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_stringMock; + + /** + * @var \Magento\Search\Model\QueryFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_queryFactoryMock; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $_scopeConfigMock; + /** + * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_escaperMock; + + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_storeManagerMock; + public function setUp() { - $objectManagerHelper = new \Magento\TestFramework\Helper\ObjectManager($this); - $className = 'Magento\CatalogSearch\Helper\Data'; - $arguments = $objectManagerHelper->getConstructArguments($className); - /** @var \Magento\Framework\App\Helper\Context $context */ - $context = $arguments['context']; - $this->_scopeConfigMock = $context->getScopeConfig(); - $this->_model = $objectManagerHelper->getObject($className, $arguments); + $this->_stringMock = $this->getMock('Magento\Framework\Stdlib\String'); + $this->_queryFactoryMock = $this->getMock('Magento\Search\Model\QueryFactory', [], [], '', false); + $this->_scopeConfigMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); + $this->_escaperMock = $this->getMock('Magento\Framework\Escaper'); + $this->_storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->_contextMock = $this->getMock('Magento\Framework\App\Helper\Context', [], [], '', false); + $this->_contextMock->expects($this->any())->method('getScopeConfig')->willReturn($this->_scopeConfigMock); + + $this->_model = new \Magento\CatalogSearch\Helper\Data( + $this->_contextMock, + $this->_stringMock, + $this->_queryFactoryMock, + $this->_escaperMock, + $this->_storeManagerMock + ); } /** diff --git a/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Adapter/OptionsTest.php b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Adapter/OptionsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..91bbb914bd28399349a736107904d4393c62f29e --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Adapter/OptionsTest.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogSearch\Model\Adapter; + +use Magento\Store\Model\ScopeInterface; +use Magento\TestFramework\Helper\ObjectManager; + +class OptionsTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeConfig; + + /** + * @var Options + */ + private $options; + + protected function setUp() + { + $helper = new ObjectManager($this); + + $this->scopeConfig = $this->getMockBuilder('Magento\Framework\App\Config\ScopeConfigInterface') + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $this->options = $helper->getObject( + 'Magento\CatalogSearch\Model\Adapter\Options', + [ + 'scopeConfig' => $this->scopeConfig + ] + ); + } + + public function testGet() + { + $expectedResult = [ + 'interval_division_limit' => 15, + 'range_step' => 3.3, + 'min_range_power' => 10, + 'max_intervals_number' => 33 + ]; + + $this->scopeConfig->expects($this->at(0)) + ->method('getValue') + ->withConsecutive([Options::XML_PATH_INTERVAL_DIVISION_LIMIT, ScopeInterface::SCOPE_STORE]) + ->willReturn($expectedResult['interval_division_limit']); + $this->scopeConfig->expects($this->at(1)) + ->method('getValue') + ->withConsecutive([Options::XML_PATH_RANGE_STEP, ScopeInterface::SCOPE_STORE]) + ->willReturn($expectedResult['range_step']); + $this->scopeConfig->expects($this->at(2)) + ->method('getValue') + ->withConsecutive([Options::XML_PATH_RANGE_MAX_INTERVALS, ScopeInterface::SCOPE_STORE]) + ->willReturn($expectedResult['max_intervals_number']); + + $this->options->get(); + } +} diff --git a/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php index f023f8f3ed183a3f8ab86156a3602241bc2a58c9..79f821f6d47d5298312d0813d862b11fd395c673 100644 --- a/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php +++ b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/AdvancedTest.php @@ -11,45 +11,41 @@ namespace Magento\CatalogSearch\Model; */ class AdvancedTest extends \PHPUnit_Framework_TestCase { - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Product\Attribute\Backend\Sku - */ - protected $skuAttribute; - /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogSearch\Model\Resource\Advanced\Collection */ protected $collection; - /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogSearch\Model\Resource\Advanced */ protected $resource; - /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogSearch\Model\Resource\ResourceProvider */ protected $resourceProvider; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Resource\Eav\Attribute + * @var \PHPUnit_Framework_MockObject_MockObject[]|\Magento\Catalog\Model\Resource\Eav\Attribute[] */ - protected $attribute; - + protected $attributes; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Data\Collection */ protected $dataCollection; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Directory\Model\Currency + */ + private $currency; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Store\Model\StoreManagerInterface + */ + private $storeManager; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Store\Model\Store + */ + private $store; protected function setUp() { - $this->skuAttribute = $this->getMock( - 'Magento\Catalog\Model\Product\Attribute\Backend\Sku', - ['getTable'], - [], - '', - false - ); $this->collection = $this->getMock( 'Magento\CatalogSearch\Model\Resource\Advanced\Collection', [ @@ -81,13 +77,6 @@ class AdvancedTest extends \PHPUnit_Framework_TestCase false ); - $this->attribute = $this->getMock( - 'Magento\Catalog\Model\Resource\Eav\Attribute', - ['getAttributeCode', 'getStoreLabel', 'getFrontendInput', 'getBackend', 'getBackendType', '__wakeup'], - [], - '', - false - ); $this->dataCollection = $this->getMock( 'Magento\Framework\Data\Collection', ['getIterator'], @@ -95,25 +84,108 @@ class AdvancedTest extends \PHPUnit_Framework_TestCase '', false ); + + $this->currency = $this->getMockBuilder('\Magento\Directory\Model\Currency') + ->setMethods(['getRate']) + ->disableOriginalConstructor() + ->getMock(); + $this->store = $this->getMockBuilder('\Magento\Store\Model\Store') + ->setMethods(['getCurrentCurrencyCode', 'getBaseCurrencyCode', 'getBaseCurrency']) + ->disableOriginalConstructor() + ->getMock(); + $this->store->expects($this->any()) + ->method('getBaseCurrency') + ->willReturn($this->currency); + $this->storeManager = $this->getMockBuilder('\Magento\Store\Model\StoreManagerInterface') + ->setMethods(['getStore']) + ->getMockForAbstractClass(); + $this->storeManager->expects($this->any()) + ->method('getStore') + ->willReturn($this->store); } - public function testAddFiltersVerifyAddConditionsToRegistry() + public function addFiltersDataProvider() { + return array_merge( + [ + 'sku' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('catalog_product_entity'), + $this->createSource(), + 'sku', + 'SKU', + 'text', + 'static' + ) + ], + 'values' => ['sku' => 'simple'] + ], + 'color_multiselect' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('color_multiselect'), + $this->createSource(['label' => 'Color']), + 'color', + 'Color', + 'multiselect', + 'static' + ) + ], + 'values' => ['color' => [100 => 'red', 200 => 'blue']], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ], + 'color_select' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('color_select'), + $this->createSource(['label' => 'Color']), + 'color', + 'Color', + 'select', + 'static' + ) + ], + 'values' => ['color' => 'red'], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ], + 'boolean' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('boolean'), + $this->createSource(['label' => 'Color']), + 'is_active', + 'Is active?', + 'boolean', + 'static' + ) + ], + 'values' => ['is_active' => false], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ], + ], + $this->addFiltersPriceDataProvider() + ); + } + + /** + * @param array $attributes + * @param array $values + * @param string $currentCurrencyCode + * @param string $baseCurrencyCode + * @dataProvider addFiltersDataProvider + */ + public function testAddFiltersVerifyAddConditionsToRegistry( + array $attributes, + array $values, + $currentCurrencyCode = 'GBP', + $baseCurrencyCode = 'USD' + ) { $registry = new \Magento\Framework\Registry(); - $values = ['sku' => 'simple']; - - $this->resourceProvider->expects($this->once()) - ->method('getResource') - ->willReturn($this->resource); - $this->resourceProvider->expects($this->once()) - ->method('getResourceCollection') - ->willReturn($this->collection); - $this->resourceProvider->expects($this->once()) - ->method('getAdvancedResultCollection') - ->willReturn($this->collection); - - $this->skuAttribute->expects($this->once())->method('getTable') - ->will($this->returnValue('catalog_product_entity')); + $this->collection->expects($this->any())->method('addAttributeToSelect')->will($this->returnSelf()); $this->collection->expects($this->any())->method('setStore')->will($this->returnSelf()); $this->collection->expects($this->any())->method('addMinimalPrice')->will($this->returnSelf()); @@ -123,24 +195,219 @@ class AdvancedTest extends \PHPUnit_Framework_TestCase $this->resource->expects($this->any())->method('prepareCondition') ->will($this->returnValue(['like' => '%simple%'])); $this->resource->expects($this->any())->method('getIdFieldName')->will($this->returnValue('entity_id')); - $this->attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue('sku')); - $this->attribute->expects($this->any())->method('getStoreLabel')->will($this->returnValue('SKU')); - $this->attribute->expects($this->any())->method('getFrontendInput')->will($this->returnValue('text')); - $this->attribute->expects($this->any())->method('getBackend')->will($this->returnValue($this->skuAttribute)); - $this->attribute->expects($this->any())->method('getBackendType')->will($this->returnValue('static')); $this->dataCollection->expects($this->any())->method('getIterator') - ->will($this->returnValue(new \ArrayIterator([$this->attribute]))); + ->will($this->returnValue(new \ArrayIterator($attributes))); $objectManager = new \Magento\TestFramework\Helper\ObjectManager($this); + + $advancedFactory = $this->getMockBuilder('Magento\CatalogSearch\Model\Resource\AdvancedFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $advancedFactory->expects($this->once())->method('create')->willReturn($this->resource); + + $productCollectionFactory = $this->getMockBuilder('Magento\Catalog\Model\Resource\Product\CollectionFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $productCollectionFactory->expects($this->any())->method('create')->willReturn($this->collection); + + $this->store->expects($this->any()) + ->method('getCurrentCurrencyCode') + ->willReturn($currentCurrencyCode); + $this->store->expects($this->any()) + ->method('getBaseCurrencyCode') + ->willReturn($baseCurrencyCode); + $this->currency->expects($this->any()) + ->method('getRate') + ->with($currentCurrencyCode) + ->willReturn(1.5); + + $currency = $this->getMockBuilder('Magento\Directory\Model\Currency') + ->setMethods(['load', 'format']) + ->disableOriginalConstructor() + ->getMock(); + $currency->expects($this->any()) + ->method('load') + ->willReturnSelf(); + $currency->expects($this->any()) + ->method('format') + ->willReturnArgument(0); + $currencyFactory = $this->getMockBuilder('Magento\Directory\Model\CurrencyFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $currencyFactory->expects($this->any()) + ->method('create') + ->willReturn($currency); + /** @var \Magento\CatalogSearch\Model\Advanced $instance */ $instance = $objectManager->getObject( 'Magento\CatalogSearch\Model\Advanced', [ 'registry' => $registry, 'resourceProvider' => $this->resourceProvider, - 'data' => ['attributes' => $this->dataCollection] + 'data' => ['attributes' => $this->dataCollection], + 'advancedFactory' => $advancedFactory, + 'productCollectionFactory' => $productCollectionFactory, + 'storeManager' => $this->storeManager, + 'currencyFactory' => $currencyFactory, ] ); $instance->addFilters($values); $this->assertNotNull($registry->registry('advanced_search_conditions')); } + + /** + * @param $table + * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend + */ + private function createBackend($table) + { + $backend = $this->getMock( + 'Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend', + ['getTable'], + [], + '', + false + ); + $backend->expects($this->once()) + ->method('getTable') + ->willReturn($table); + return $backend; + } + + private function createSource($optionText = 'optionText') + { + $source = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Source\AbstractSource') + ->setMethods(['getOptionText']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $source->expects($this->any()) + ->method('getOptionText') + ->willReturn($optionText); + return $source; + } + + private function addFiltersPriceDataProvider() + { + return [ + 'price_without_currency' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('table_price_without_currency'), + $this->createSource(), + 'price', + 'Price', + 'multiselect', + 'static' + ) + ], + 'values' => ['price' => ['from' => 10, 'to' => 40]], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ], + 'price_without_to' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('price_without_to'), + $this->createSource(), + 'price', + 'Price', + 'multiselect', + 'static' + ) + ], + 'values' => ['price' => ['from' => 10, 'to' => '']], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ], + 'price_without_from' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('price_without_from'), + $this->createSource(), + 'price', + 'Price', + 'multiselect', + 'static' + ) + ], + 'values' => ['price' => ['from' => '', 'to' => 30]], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ], + 'price_empty' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('price_empty'), + $this->createSource(), + 'price', + 'Price', + 'multiselect', + 'static' + ) + ], + 'values' => ['price' => ['from' => '', 'to' => '']], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ], + 'price_with_currency' => [ + 'attributes' => [ + $this->createAttribute( + $this->createBackend('price_with_currency'), + $this->createSource(), + 'price', + 'Price', + 'multiselect', + 'static' + ) + ], + 'values' => ['price' => ['from' => 10, 'to' => 40, 'currency' => 'ASD']], + 'currentCurrencyCode' => 'GBP', + 'baseCurrencyCode' => 'USD' + ] + ]; + } + + + /** + * @param $backend + * @param null $source + * @param null $attributeCode + * @param null $storeLabel + * @param null $frontendInput + * @param null $backendType + * @return \Magento\Catalog\Model\Resource\Eav\Attribute|\PHPUnit_Framework_MockObject_MockObject + */ + private function createAttribute( + $backend, + $source = null, + $attributeCode = null, + $storeLabel = null, + $frontendInput = null, + $backendType = null + ) { + $attribute = $this->getMock( + 'Magento\Catalog\Model\Resource\Eav\Attribute', + [ + 'getAttributeCode', + 'getStoreLabel', + 'getFrontendInput', + 'getBackend', + 'getBackendType', + 'getSource', + '__wakeup' + ], + [], + '', + false + ); + $attribute->expects($this->any())->method('getBackend')->willReturn($backend); + $attribute->expects($this->any())->method('getSource')->willReturn($source); + $attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue($attributeCode)); + $attribute->expects($this->any())->method('getStoreLabel')->will($this->returnValue($storeLabel)); + $attribute->expects($this->any())->method('getFrontendInput')->will($this->returnValue($frontendInput)); + $attribute->expects($this->any())->method('getBackendType')->will($this->returnValue($backendType)); + return $attribute; + } } diff --git a/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Autocomplete/DataProviderTest.php b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Autocomplete/DataProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dc222c28bce98eaed736c2c927352902915faf17 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Autocomplete/DataProviderTest.php @@ -0,0 +1,119 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogSearch\Model\Autocomplete; + +use Magento\TestFramework\Helper\ObjectManager; + +class DataProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var DataProvider + */ + private $model; + + /** + * @var \Magento\Search\Model\Query |\PHPUnit_Framework_MockObject_MockObject + */ + private $query; + + /** + * @var \Magento\Search\Model\Autocomplete\ItemFactory |\PHPUnit_Framework_MockObject_MockObject + */ + private $itemFactory; + + /** + * @var \Magento\Search\Model\Resource\Query\Collection |\PHPUnit_Framework_MockObject_MockObject + */ + private $suggestCollection; + + protected function setUp() + { + $helper = new ObjectManager($this); + + $this->suggestCollection = $this->getMockBuilder('Magento\Search\Model\Resource\Query\Collection') + ->disableOriginalConstructor() + ->setMethods(['getIterator']) + ->getMock(); + + $this->query = $this->getMockBuilder('Magento\Search\Model\Query') + ->disableOriginalConstructor() + ->setMethods(['getQueryText', 'getSuggestCollection']) + ->getMock(); + $this->query->expects($this->any()) + ->method('getSuggestCollection') + ->willReturn($this->suggestCollection); + + $queryFactory = $this->getMockBuilder('Magento\Search\Model\QueryFactory') + ->disableOriginalConstructor() + ->setMethods(['get']) + ->getMock(); + $queryFactory->expects($this->any()) + ->method('get') + ->willReturn($this->query); + + $this->itemFactory = $this->getMockBuilder('Magento\Search\Model\Autocomplete\ItemFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->model = $helper->getObject( + '\Magento\CatalogSearch\Model\Autocomplete\DataProvider', + [ + 'queryFactory' => $queryFactory, + 'itemFactory' => $this->itemFactory + ] + ); + } + + public function testGetItems() + { + $queryString = 'string'; + $expected = ['title' => $queryString, 'num_results' => 100500]; + $collection = [ + ['query_text' => 'string1', 'num_results' => 1], + ['query_text' => 'string2', 'num_results' => 2], + ['query_text' => 'string11', 'num_results' => 11], + ['query_text' => 'string100', 'num_results' => 100], + ['query_text' => $queryString, 'num_results' => 100500] + ]; + $this->buildCollection($collection); + $this->query->expects($this->once()) + ->method('getQueryText') + ->willReturn($queryString); + + $itemMock = $this->getMockBuilder('Magento\Search\Model\Autocomplete\Item') + ->disableOriginalConstructor() + ->setMethods(['getTitle', 'toArray']) + ->getMock(); + $itemMock->expects($this->any()) + ->method('getTitle') + ->will($this->onConsecutiveCalls( + $queryString, + 'string1', + 'string2', + 'string11', + 'string100' + )); + $itemMock->expects($this->any()) + ->method('toArray') + ->will($this->returnValue($expected)); + + $this->itemFactory->expects($this->any())->method('create')->willReturn($itemMock); + $result = $this->model->getItems(); + $this->assertEquals($expected, $result[0]->toArray()); + } + + private function buildCollection(array $data) + { + $collectionData = []; + foreach ($data as $collectionItem) { + $collectionData[] = new \Magento\Framework\Object($collectionItem); + } + $this->suggestCollection->expects($this->any()) + ->method('getIterator') + ->will($this->returnValue(new \ArrayIterator($collectionData))); + } +} diff --git a/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Resource/AdvancedTest.php b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Resource/AdvancedTest.php index dd4284e6a4a5843fa1866e9d4410aae3f9fe99de..13de07168a3de6ddc96b5cbbf1fcf3036a72e609 100644 --- a/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Resource/AdvancedTest.php +++ b/dev/tests/unit/testsuite/Magento/CatalogSearch/Model/Resource/AdvancedTest.php @@ -5,6 +5,7 @@ */ namespace Magento\CatalogSearch\Model\Resource; +use Magento\Catalog\Model\Resource\Eav\Attribute; use PHPUnit_Framework_TestCase; class AdvancedTest extends PHPUnit_Framework_TestCase @@ -21,67 +22,44 @@ class AdvancedTest extends PHPUnit_Framework_TestCase { $helper = new \Magento\TestFramework\Helper\ObjectManager($this); - $storeManager = $this->getStoreManager(); - - $this->model = $helper->getObject( - 'Magento\CatalogSearch\Model\Resource\Advanced', - [ - 'storeManager' => $storeManager - ] - ); + $this->model = $helper->getObject('Magento\CatalogSearch\Model\Resource\Advanced'); } /** - * @dataProvider indexableAttributeDataProvider + * @dataProvider prepareConditionDataProvider */ - public function testAddIndexableAttributeModifiedFilter($indexType, $value, $expected) + public function testPrepareCondition($backendType, $value, $expected) { - $selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); - $collectionMock = $this->getMock('Magento\CatalogSearch\Model\Resource\Advanced\Collection', [], [], '', false); - $collectionMock->expects($this->once())->method('getSelect')->willReturn($selectMock); - - $attributeMock = $this->getMock('Magento\Catalog\Model\Resource\Eav\Attribute', [], [], '', false); - $attributeMock->expects($this->once())->method('getIndexType')->willReturn($indexType); - $attributeMock->expects($this->any())->method('getAttributeId')->willReturn(1); + /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $attributeMock */ + $attributeMock = $this->getMockBuilder('Magento\Catalog\Model\Resource\Eav\Attribute') + ->setMethods(['getBackendType']) + ->disableOriginalConstructor() + ->getMock(); + $attributeMock->expects($this->once()) + ->method('getBackendType') + ->willReturn($backendType); $this->assertEquals( $expected, - $this->model->addIndexableAttributeModifiedFilter($collectionMock, $attributeMock, $value) + $this->model->prepareCondition($attributeMock, $value) ); } - public function indexableAttributeDataProvider() - { - return [ - ['decimal', '', true], - ['source', ['from' => 0, 'to' => 0], false], - [false, ['from' => 0], true], - ['decimal', ['to' => 0], true], - ['source', ['from' => 1, 'to' => 1], true] - ]; - } - /** - * @return \PHPUnit_Framework_MockObject_MockObject + * Data provider for testPrepareCondition + * + * @return array */ - protected function getStoreManager() + public function prepareConditionDataProvider() { - $store = $this->getMockBuilder('Magento\Store\Model\Store') - ->setMethods(['getId']) - ->disableOriginalConstructor() - ->getMock(); - $store->expects($this->once()) - ->method('getId') - ->willReturn(1); - - $storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface') - ->setMethods(['getStore']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $storeManager->expects($this->once()) - ->method('getStore') - ->willReturn($store); - - return $storeManager; + return [ + ['string', 'string', 'string'], + ['varchar', 'string', ['like' => '%string%']], + ['varchar', ['test'], ['in_set' => ['test']]], + ['select', ['test'], ['in' => ['test']]], + ['range', ['from' => 1], ['from' => 1]], + ['range', ['to' => 3], ['to' => 3]], + ['range', ['from' => 1, 'to' => 3], ['from' => 1, 'to' => 3]] + ]; } } diff --git a/dev/tests/unit/testsuite/Magento/Checkout/Model/Layout/DepersonalizePluginTest.php b/dev/tests/unit/testsuite/Magento/Checkout/Model/Layout/DepersonalizePluginTest.php index b09e0f6a6867208536a7a0b226935a9f86cdb129..666740e8a0e2f119f9ba49af331337fc76604533 100644 --- a/dev/tests/unit/testsuite/Magento/Checkout/Model/Layout/DepersonalizePluginTest.php +++ b/dev/tests/unit/testsuite/Magento/Checkout/Model/Layout/DepersonalizePluginTest.php @@ -29,19 +29,9 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase protected $checkoutSessionMock; /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\PageCache\Model\DepersonalizeChecker|\PHPUnit_Framework_MockObject_MockObject */ - protected $requestMock; - - /** - * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $moduleManagerMock; - - /** - * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject - */ - protected $cacheConfigMock; + protected $depersonalizeCheckerMock; /** * SetUp @@ -65,12 +55,17 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); $this->moduleManagerMock = $this->getMock('Magento\Framework\Module\Manager', [], [], '', false); $this->cacheConfigMock = $this->getMock('Magento\PageCache\Model\Config', [], [], '', false); + $this->depersonalizeCheckerMock = $this->getMock( + 'Magento\PageCache\Model\DepersonalizeChecker', + [], + [], + '', + false + ); $this->plugin = new \Magento\Checkout\Model\Layout\DepersonalizePlugin( - $this->checkoutSessionMock, - $this->moduleManagerMock, - $this->requestMock, - $this->cacheConfigMock + $this->depersonalizeCheckerMock, + $this->checkoutSessionMock ); } @@ -80,21 +75,24 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase public function testAfterGenerateXml() { $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->will($this->returnValue(true)); - $this->cacheConfigMock->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->requestMock->expects($this->once($this->once())) - ->method('isAjax') - ->will($this->returnValue(false)); - $this->layoutMock->expects($this->once()) - ->method('isCacheable') - ->will($this->returnValue(true)); - $this->checkoutSessionMock->expects($this->once()) + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(true); + $this->checkoutSessionMock + ->expects($this->once()) + ->method('clearStorage') + ->will($this->returnValue($expectedResult)); + + $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $expectedResult); + $this->assertEquals($expectedResult, $actualResult); + } + + public function testAfterGenerateXmlNoDepersonalize() + { + $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); + + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(false); + $this->checkoutSessionMock + ->expects($this->never()) ->method('clearStorage') ->will($this->returnValue($expectedResult)); diff --git a/dev/tests/unit/testsuite/Magento/Customer/Model/Layout/DepersonalizePluginTest.php b/dev/tests/unit/testsuite/Magento/Customer/Model/Layout/DepersonalizePluginTest.php index 73c7315d9b953964f794eaf101b3393c6337d058..fd09caa0557437384ed179002e66f10e52d52cd3 100644 --- a/dev/tests/unit/testsuite/Magento/Customer/Model/Layout/DepersonalizePluginTest.php +++ b/dev/tests/unit/testsuite/Magento/Customer/Model/Layout/DepersonalizePluginTest.php @@ -37,30 +37,21 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase */ protected $customerFactoryMock; - /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - /** * @var \Magento\Customer\Model\Customer|\PHPUnit_Framework_MockObject_MockObject */ protected $customerMock; - /** - * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $moduleManagerMock; - /** * @var \Magento\Log\Model\Visitor|\PHPUnit_Framework_MockObject_MockObject */ protected $visitorMock; /** - * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\PageCache\Model\DepersonalizeChecker|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheConfigMock; + protected $depersonalizeCheckerMock; + /** * SetUp */ @@ -88,7 +79,6 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase '', false ); - $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); $this->customerMock = $this->getMock( 'Magento\Customer\Model\Customer', ['setGroupId', '__wakeup'], @@ -96,168 +86,60 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase '', false ); - $this->moduleManagerMock = $this->getMock('Magento\Framework\Module\Manager', [], [], '', false); $this->visitorMock = $this->getMock('Magento\Customer\Model\Visitor', [], [], '', false); $this->customerFactoryMock->expects($this->any()) ->method('create') ->will($this->returnValue($this->customerMock)); - $this->cacheConfigMock = $this->getMock('Magento\PageCache\Model\Config', [], [], '', false); + $this->depersonalizeCheckerMock = $this->getMock( + 'Magento\PageCache\Model\DepersonalizeChecker', + [], + [], + '', + false + ); $this->plugin = new DepersonalizePlugin( + $this->depersonalizeCheckerMock, $this->sessionMock, $this->customerSessionMock, $this->customerFactoryMock, - $this->requestMock, - $this->moduleManagerMock, - $this->visitorMock, - $this->cacheConfigMock + $this->visitorMock ); } - /** - * Test method beforeGenerateXml with enabled module PageCache - */ - public function testBeforeGenerateXmlPageCacheEnabled() + public function testBeforeGenerateXml() { - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with('Magento_PageCache') - ->will($this->returnValue(true)); - $this->cacheConfigMock - ->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->requestMock - ->expects($this->once()) - ->method('isAjax') - ->will($this->returnValue(false)); - $this->layoutMock + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(true); + $this->customerSessionMock->expects($this->once())->method('getCustomerGroupId'); + $this->sessionMock ->expects($this->once()) - ->method('isCacheable') - ->will($this->returnValue(true)); - $this->customerSessionMock->expects($this->once()) - ->method('getCustomerGroupId'); - $this->sessionMock->expects($this->once()) ->method('getData') ->with($this->equalTo(\Magento\Framework\Data\Form\FormKey::FORM_KEY)); $output = $this->plugin->beforeGenerateXml($this->layoutMock); $this->assertEquals([], $output); } - /** - * Test method beforeGenerateXml with disabled module PageCache - */ - public function testBeforeGenerateXmlPageCacheDisabled() + public function testBeforeGenerateXmlNoDepersonalize() { - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with('Magento_PageCache') - ->will($this->returnValue(false)); - $this->requestMock + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(false); + $this->customerSessionMock->expects($this->never())->method('getCustomerGroupId'); + $this->sessionMock ->expects($this->never()) - ->method('isAjax'); - $output = $this->plugin->beforeGenerateXml($this->layoutMock); - $this->assertEquals([], $output); - } - - /** - * Test beforeGenerateXml method with enabled module PageCache and request is Ajax - */ - public function testBeforeGenerateXmlRequestIsAjax() - { - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with('Magento_PageCache') - ->will($this->returnValue(true)); - $this->cacheConfigMock - ->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->requestMock - ->expects($this->once()) - ->method('isAjax') - ->will($this->returnValue(true)); - $this->layoutMock->expects($this->never()) - ->method('isCacheable'); - $output = $this->plugin->beforeGenerateXml($this->layoutMock); - $this->assertEquals([], $output); - } - - /** - * Test beforeGenerateXml method with enabled module PageCache and request is Ajax and Layout is not cacheable - */ - public function testBeforeGenerateXmlLayoutIsNotCacheable() - { - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with('Magento_PageCache') - ->will($this->returnValue(true)); - $this->cacheConfigMock - ->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->requestMock - ->expects($this->once()) - ->method('isAjax') - ->will($this->returnValue(false)); - $this->layoutMock->expects($this->once()) - ->method('isCacheable') - ->will($this->returnValue(false)); - $this->customerSessionMock->expects($this->never()) - ->method('getCustomerGroupId'); + ->method('getData'); $output = $this->plugin->beforeGenerateXml($this->layoutMock); $this->assertEquals([], $output); } - /** - * Test method afterGenerateXml with enabled module PageCache - */ - public function testAfterGenerateXmlPageCacheEnabled() + public function testAfterGenerateXml() { $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with('Magento_PageCache') - ->will($this->returnValue(true)); - $this->cacheConfigMock - ->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->requestMock - ->expects($this->once()) - ->method('isAjax') - ->will($this->returnValue(false)); - $this->layoutMock - ->expects($this->once()) - ->method('isCacheable') - ->will($this->returnValue(true)); - $this->visitorMock - ->expects($this->once()) - ->method('setSkipRequestLogging') - ->with($this->equalTo(true)); - $this->visitorMock - ->expects($this->once()) - ->method('unsetData'); - $this->sessionMock - ->expects($this->once()) - ->method('clearStorage'); - $this->customerSessionMock - ->expects($this->once()) - ->method('clearStorage'); - $this->customerSessionMock - ->expects($this->once()) - ->method('setCustomerGroupId') - ->with($this->equalTo(null)); - $this->customerMock - ->expects($this->once()) - ->method('setGroupId') - ->with($this->equalTo(null)) - ->willReturnSelf(); + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(true); + $this->visitorMock->expects($this->once())->method('setSkipRequestLogging')->with($this->equalTo(true)); + $this->visitorMock->expects($this->once())->method('unsetData'); + $this->sessionMock->expects($this->once())->method('clearStorage'); + $this->customerSessionMock->expects($this->once())->method('clearStorage'); + $this->customerSessionMock->expects($this->once())->method('setCustomerGroupId')->with($this->equalTo(null)); + $this->customerMock->expects($this->once())->method('setGroupId')->with($this->equalTo(null))->willReturnSelf(); $this->sessionMock ->expects($this->once()) ->method('setData') @@ -273,74 +155,18 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase $this->assertSame($expectedResult, $actualResult); } - /** - * Test afterGenerateXml method with disabled module PageCache - */ - public function testAfterGenerateXmlPageCacheDisabled() - { - $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with('Magento_PageCache') - ->will($this->returnValue(false)); - $this->requestMock - ->expects($this->never()) - ->method('isAjax'); - $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $expectedResult); - $this->assertSame($expectedResult, $actualResult); - } - - /** - * Test afterGenerateXml method with enabled module PageCache and request is Ajax - */ - public function testAfterGenerateXmlRequestIsAjax() + public function testAfterGenerateXmlNoDepersonalize() { $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->will($this->returnValue(true)); - $this->cacheConfigMock - ->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->requestMock - ->expects($this->once()) - ->method('isAjax') - ->will($this->returnValue(true)); - $this->layoutMock->expects($this->never()) - ->method('isCacheable'); - $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $expectedResult); - $this->assertSame($expectedResult, $actualResult); - } - - /** - * Test afterGenerateXml method with enabled module PageCache and request is Ajax and Layout is not cacheable - */ - public function testAfterGenerateXmlLayoutIsNotCacheable() - { - $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->moduleManagerMock - ->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->will($this->returnValue(true)); - $this->cacheConfigMock - ->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->requestMock - ->expects($this->once()) - ->method('isAjax') - ->will($this->returnValue(false)); - $this->layoutMock->expects($this->once()) - ->method('isCacheable') - ->will($this->returnValue(false)); - $this->visitorMock - ->expects($this->never()) - ->method('setSkipRequestLogging'); + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(false); + $this->visitorMock->expects($this->never())->method('setSkipRequestLogging'); + $this->visitorMock->expects($this->never())->method('unsetData'); + $this->sessionMock->expects($this->never())->method('clearStorage'); + $this->customerSessionMock->expects($this->never())->method('clearStorage'); + $this->customerSessionMock->expects($this->never())->method('setCustomerGroupId'); + $this->customerMock->expects($this->never())->method('setGroupId'); + $this->sessionMock->expects($this->never())->method('setData'); + $this->customerSessionMock->expects($this->never())->method('setCustomer'); $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $expectedResult); $this->assertSame($expectedResult, $actualResult); } diff --git a/dev/tests/unit/testsuite/Magento/Framework/DB/Helper/Mysql/FulltextTest.php b/dev/tests/unit/testsuite/Magento/Framework/DB/Helper/Mysql/FulltextTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2f7601adae102d13576c314fceaa53482e7c82d4 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Framework/DB/Helper/Mysql/FulltextTest.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\DB\Helper\Mysql; + +use Magento\Framework\DB\Select; +use Magento\TestFramework\Helper\ObjectManager; + +class FulltextTest extends \PHPUnit_Framework_TestCase +{ + public function testGetMatchQuery() + { + /** @var Fulltext $select */ + $select = (new ObjectManager($this))->getObject( + 'Magento\Framework\DB\Helper\Mysql\Fulltext', + ['resource' => $this->getAdapter()] + ); + + $result = $select->getMatchQuery( + ['title', 'description'], + 'some searchable text', + Fulltext::FULLTEXT_MODE_NATURAL + ); + $expectedResult = "MATCH (title, description) AGAINST ('some searchable text' IN NATURAL LANGUAGE MODE)"; + + $this->assertEquals($expectedResult, $result); + } + + /** + * @param $isCondition + * @dataProvider matchProvider + */ + public function testMatch($isCondition) + { + $fullCondition = "MATCH (title, description) AGAINST ('some searchable text' IN NATURAL LANGUAGE MODE)"; + + $resource = $this->getAdapter(); + + /** @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject $select */ + $select = $this->getMockBuilder('Magento\Framework\DB\Select') + ->disableOriginalConstructor() + ->getMock(); + $select->expects($this->once()) + ->method($isCondition ? 'where' : 'orWhere') + ->with($fullCondition); + + /** @var Fulltext $fulltext */ + $fulltext = (new ObjectManager($this))->getObject( + 'Magento\Framework\DB\Helper\Mysql\Fulltext', + ['resource' => $resource] + ); + + $result = $fulltext->match( + $select, + ['title', 'description'], + 'some searchable text', + $isCondition, + Fulltext::FULLTEXT_MODE_NATURAL + ); + + $this->assertEquals($select, $result); + } + + public function matchProvider() + { + return [[true], [false]]; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getAdapter() + { + $adapter = $this->getMockBuilder('Magento\Framework\DB\Adapter\AdapterInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $adapter->expects($this->at(0)) + ->method('quote') + ->with($this->equalTo('some searchable text')) + ->will($this->returnValue("'some searchable text'")); + + $resource = $this->getMockBuilder('Magento\Framework\App\Resource') + ->disableOriginalConstructor() + ->getMock(); + $resource->expects($this->any()) + ->method('getConnection') + ->willReturn($adapter); + + return $resource; + } +} diff --git a/dev/tests/unit/testsuite/Magento/Framework/DB/SelectTest.php b/dev/tests/unit/testsuite/Magento/Framework/DB/SelectTest.php index 7fd0bf862a69950272f0a85b3377af201ba5a56d..9efdd55c0107f101081e94ce68119d13a4d53fd5 100644 --- a/dev/tests/unit/testsuite/Magento/Framework/DB/SelectTest.php +++ b/dev/tests/unit/testsuite/Magento/Framework/DB/SelectTest.php @@ -9,52 +9,6 @@ use Magento\TestFramework\Helper\ObjectManager; class SelectTest extends \PHPUnit_Framework_TestCase { - public function testGetMatchQuery() - { - /** @var Select $select */ - $select = (new ObjectManager($this))->getObject('Magento\Framework\DB\Select'); - - $result = $select->getMatchQuery( - ['title', 'description'], - 'some searchable text', - Select::FULLTEXT_MODE_NATURAL - ); - $expectedResult = "MATCH (title, description) AGAINST ('some searchable text' IN NATURAL LANGUAGE MODE)"; - - $this->assertEquals($expectedResult, $result); - } - - public function testMatch() - { - $adapter = $this->getMock( - 'Zend_Db_Adapter_Pdo_Mysql', - ['supportStraightJoin', 'quote'], - [], - '', - false - ); - $adapter->expects($this->at(0))->method('quote') - ->with($this->equalTo('some searchable text')) - ->will($this->returnValue("'some searchable text'")); - $adapter->expects($this->at(1))->method('quote') - ->will($this->returnValue('')); - - /** @var Select $select */ - $select = (new ObjectManager($this))->getObject( - 'Magento\Framework\DB\Select', - ['adapter' => $adapter] - ); - - $select->from('test'); - $select->match(['title', 'description'], 'some searchable text', true, Select::FULLTEXT_MODE_NATURAL); - - $expectedResult = "SELECT `test`.* FROM `test` WHERE (MATCH (title, description) " . - "AGAINST ('some searchable text' IN NATURAL LANGUAGE MODE))"; - $result = $select->assemble(); - - $this->assertEquals($expectedResult, $result); - } - public function testWhere() { $select = new Select($this->_getAdapterMockWithMockedQuote(1, "'5'")); diff --git a/dev/tests/unit/testsuite/Magento/Framework/Module/ModuleList/LoaderTest.php b/dev/tests/unit/testsuite/Magento/Framework/Module/ModuleList/LoaderTest.php index 5fd6fa94551eb9708cffbccc15cd7be3edfc9b1d..59c449cf5d2f585cd6de81b6875aecdc4dd3fa1b 100644 --- a/dev/tests/unit/testsuite/Magento/Framework/Module/ModuleList/LoaderTest.php +++ b/dev/tests/unit/testsuite/Magento/Framework/Module/ModuleList/LoaderTest.php @@ -7,6 +7,7 @@ namespace Magento\Framework\Module\ModuleList; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Xml\Parser; class LoaderTest extends \PHPUnit_Framework_TestCase { @@ -32,6 +33,11 @@ class LoaderTest extends \PHPUnit_Framework_TestCase */ private $converter; + /* + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $parser; + protected function setUp() { $this->filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false); @@ -41,6 +47,7 @@ class LoaderTest extends \PHPUnit_Framework_TestCase ->with(DirectoryList::MODULES) ->willReturn($this->dir); $this->converter = $this->getMock('Magento\Framework\Module\Declaration\Converter\Dom', [], [], '', false); + $this->parser = $this->getMock('Magento\Framework\Xml\Parser', [], [], '', false); } public function testLoad() @@ -57,11 +64,13 @@ class LoaderTest extends \PHPUnit_Framework_TestCase ['b', null, null, self::$sampleXml], ['c', null, null, self::$sampleXml], ])); - $dom = new \PHPUnit_Framework_Constraint_IsInstanceOf('DOMDocument'); - $this->converter->expects($this->at(0))->method('convert')->with($dom)->willReturn(['a' => $fixture['a']]); - $this->converter->expects($this->at(1))->method('convert')->with($dom)->willReturn(['b' => $fixture['b']]); - $this->converter->expects($this->at(2))->method('convert')->with($dom)->willReturn(['c' => $fixture['c']]); - $object = new Loader($this->filesystem, $this->converter); + $this->converter->expects($this->at(0))->method('convert')->willReturn(['a' => $fixture['a']]); + $this->converter->expects($this->at(1))->method('convert')->willReturn(['b' => $fixture['b']]); + $this->converter->expects($this->at(2))->method('convert')->willReturn(['c' => $fixture['c']]); + $this->parser->expects($this->once())->method('initErrorHandler'); + $this->parser->expects($this->atLeastOnce())->method('loadXML'); + $this->parser->expects($this->atLeastOnce())->method('getDom'); + $object = new Loader($this->filesystem, $this->converter, $this->parser); $result = $object->load(); $this->assertSame(['a', 'c', 'b'], array_keys($result)); $this->assertSame($fixture['a'], $result['a']); @@ -84,10 +93,9 @@ class LoaderTest extends \PHPUnit_Framework_TestCase ['a', null, null, self::$sampleXml], ['b', null, null, self::$sampleXml], ])); - $dom = new \PHPUnit_Framework_Constraint_IsInstanceOf('DOMDocument'); - $this->converter->expects($this->at(0))->method('convert')->with($dom)->willReturn(['a' => $fixture['a']]); - $this->converter->expects($this->at(1))->method('convert')->with($dom)->willReturn(['b' => $fixture['b']]); - $object = new Loader($this->filesystem, $this->converter); + $this->converter->expects($this->at(0))->method('convert')->willReturn(['a' => $fixture['a']]); + $this->converter->expects($this->at(1))->method('convert')->willReturn(['b' => $fixture['b']]); + $object = new Loader($this->filesystem, $this->converter, $this->parser); $object->load(); } } diff --git a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php index be2470d2c75337f111ab9142d3b99affe45c9510..4791db45aba046c3000c63fe0d738b1101e82a96 100644 --- a/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php +++ b/dev/tests/unit/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Adapter\Mysql\Builder\Query; +use Magento\Framework\DB\Helper\Mysql\Fulltext; use Magento\Framework\DB\Select; use Magento\Framework\Search\Request\Query\Bool; use Magento\TestFramework\Helper\ObjectManager; @@ -26,6 +27,11 @@ class MatchTest extends \PHPUnit_Framework_TestCase */ private $match; + /** + * @var \Magento\Framework\DB\Helper\Mysql\Fulltext|\PHPUnit_Framework_MockObject_MockObject + */ + private $fulltextHelper; + protected function setUp() { $helper = new ObjectManager($this); @@ -40,9 +46,13 @@ class MatchTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMockForAbstractClass(); + $this->fulltextHelper = $this->getMockBuilder('Magento\Framework\DB\Helper\Mysql\Fulltext') + ->disableOriginalConstructor() + ->getMock(); + $this->match = $helper->getObject( 'Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match', - ['resolver' => $this->resolver] + ['resolver' => $this->resolver, 'fulltextHelper' => $this->fulltextHelper] ); } @@ -55,33 +65,36 @@ class MatchTest extends \PHPUnit_Framework_TestCase ->setMethods(['getMatchQuery', 'match']) ->disableOriginalConstructor() ->getMock(); - $select->expects($this->once())->method('getMatchQuery') + $this->fulltextHelper->expects($this->once()) + ->method('getMatchQuery') ->with($this->equalTo(['some_field']), $this->equalTo('-some_value*')) ->will($this->returnValue('matchedQuery')); - $select->expects($this->once())->method('match') - ->with( - $this->equalTo(['some_field']), - $this->equalTo('-some_value*'), - $this->equalTo(true), - $this->equalTo(Select::FULLTEXT_MODE_BOOLEAN) - ); + $this->fulltextHelper->expects($this->once()) + ->method('match') + ->withConsecutive([$select, ['some_field'], '-some_value*', true, Fulltext::FULLTEXT_MODE_BOOLEAN]) + ->willReturn($select); - $this->resolver->expects($this->once())->method('resolve')->willReturnArgument(0); + $this->resolver->expects($this->once()) + ->method('resolve') + ->willReturnArgument(0); /** @var \Magento\Framework\Search\Request\Query\Match|\PHPUnit_Framework_MockObject_MockObject $query */ $query = $this->getMockBuilder('Magento\Framework\Search\Request\Query\Match') ->setMethods(['getMatches', 'getValue', 'getBoost']) ->disableOriginalConstructor() ->getMock(); - $query->expects($this->once())->method('getValue')->willReturn('some_value '); - $query->expects($this->once())->method('getBoost')->willReturn($boost); - $query->expects($this->once())->method('getMatches')->willReturn([['field' => 'some_field']]); - - $this->scoreBuilder->expects($this->once())->method('addCondition') - ->with( - $this->equalTo('matchedQuery'), - $this->equalTo($boost) - ); + $query->expects($this->once()) + ->method('getValue') + ->willReturn('some_value '); + $query->expects($this->once()) + ->method('getBoost') + ->willReturn($boost); + $query->expects($this->once()) + ->method('getMatches') + ->willReturn([['field' => 'some_field']]); + + $this->scoreBuilder->expects($this->once()) + ->method('addCondition'); $result = $this->match->build($this->scoreBuilder, $select, $query, Bool::QUERY_CONDITION_NOT); diff --git a/dev/tests/unit/testsuite/Magento/Framework/Xml/ParserTest.php b/dev/tests/unit/testsuite/Magento/Framework/Xml/ParserTest.php index 683e5499dc35d408a3f93569599bb2898766f664..ff512cf3b74edfec86092d234e4367001d5fe91c 100644 --- a/dev/tests/unit/testsuite/Magento/Framework/Xml/ParserTest.php +++ b/dev/tests/unit/testsuite/Magento/Framework/Xml/ParserTest.php @@ -31,4 +31,15 @@ class ParserTest extends \PHPUnit_Framework_TestCase $this->parser->load(__DIR__ . '/_files/data.xml')->xmlToArray() ); } + + /** + * @expectedException \Magento\Framework\Exception + * @expectedExceptionMessage DOMDocument::loadXML(): Opening and ending tag mismatch + */ + public function testLoadXmlInvalid() + { + $sampleInvalidXml = '<?xml version="1.0"?><config></onfig>'; + $this->parser->initErrorHandler(); + $this->parser->loadXML($sampleInvalidXml); + } } diff --git a/dev/tests/unit/testsuite/Magento/PageCache/Model/DepersonalizeCheckerTest.php b/dev/tests/unit/testsuite/Magento/PageCache/Model/DepersonalizeCheckerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..51e314e51699e85b8229e249b0e95715fb33152a --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/PageCache/Model/DepersonalizeCheckerTest.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\PageCache\Model; + +class DepersonalizeCheckerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject + */ + private $requestMock; + + /** + * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject + */ + private $moduleManagerMock; + + /** + * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheConfigMock; + + public function setup() + { + $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); + $this->moduleManagerMock = $this->getMock('Magento\Framework\Module\Manager', [], [], '', false); + $this->cacheConfigMock = $this->getMock('Magento\PageCache\Model\Config', [], [], '', false); + } + + /** + * @param array $requestResult + * @param bool $moduleManagerResult + * @param bool $cacheConfigResult + * @param bool $layoutResult + * @param bool $can Depersonalize + * @dataProvider checkIfDepersonalizeDataProvider + */ + public function testCheckIfDepersonalize( + array $requestResult, + $moduleManagerResult, + $cacheConfigResult, + $layoutResult, + $canDepersonalize + ) { + $this->requestMock->expects($this->any())->method('isAjax')->willReturn($requestResult['ajax']); + $this->requestMock->expects($this->any())->method('isGet')->willReturn($requestResult['get']); + $this->requestMock->expects($this->any())->method('isHead')->willReturn($requestResult['head']); + $this->moduleManagerMock + ->expects($this->any()) + ->method('isEnabled') + ->with('Magento_PageCache') + ->willReturn($moduleManagerResult); + + $this->cacheConfigMock->expects($this->any())->method('isEnabled')->willReturn($cacheConfigResult); + $layoutMock = $this->getMockForAbstractClass('Magento\Framework\View\LayoutInterface', [], '', false); + $layoutMock->expects($this->any())->method('isCacheable')->willReturn($layoutResult); + + $object = new DepersonalizeChecker($this->requestMock, $this->moduleManagerMock, $this->cacheConfigMock); + $this->assertEquals($canDepersonalize, $object->checkIfDepersonalize($layoutMock)); + } + + /** + * return array + */ + public function checkIfDepersonalizeDataProvider() + { + return [ + [['ajax' => false, 'get' => true, 'head' => false], true, true, true, true], + [['ajax' => false, 'get' => false, 'head' => true], true, true, true, true], + [['ajax' => false, 'get' => false, 'head' => false], true, true, true, false], + [['ajax' => true, 'get' => true, 'head' => false], true, true, true, false], + [['ajax' => false, 'get' => true, 'head' => false], false, true, true, false], + [['ajax' => false, 'get' => true, 'head' => false], true, false, true, false], + [['ajax' => false, 'get' => true, 'head' => false], true, true, false, false], + ]; + } +} diff --git a/dev/tests/unit/testsuite/Magento/PageCache/Model/Layout/DepersonalizePluginTest.php b/dev/tests/unit/testsuite/Magento/PageCache/Model/Layout/DepersonalizePluginTest.php index c3630097d53cdb59f4e1fa64d948fd0edb12b7ae..4e0db0bd6ceb6728bba5023e200de6b377c00e73 100644 --- a/dev/tests/unit/testsuite/Magento/PageCache/Model/Layout/DepersonalizePluginTest.php +++ b/dev/tests/unit/testsuite/Magento/PageCache/Model/Layout/DepersonalizePluginTest.php @@ -23,30 +23,20 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase */ protected $layoutMock; - /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - - /** - * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $moduleManagerMock; - /** * @var \Magento\Framework\Event\Manager|\PHPUnit_Framework_MockObject_MockObject */ protected $eventManagerMock; /** - * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Message\Session|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheConfigMock; + protected $messageSessionMock; /** - * @var \Magento\Framework\Message\Session|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\PageCache\Model\DepersonalizeChecker|\PHPUnit_Framework_MockObject_MockObject */ - protected $messageSessionMock; + protected $depersonalizeCheckerMock; /** * SetUp @@ -54,68 +44,49 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase public function setUp() { $this->layoutMock = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); - $this->moduleManagerMock = $this->getMock('Magento\Framework\Module\Manager', [], [], '', false); $this->eventManagerMock = $this->getMock('Magento\Framework\Event\Manager', [], [], '', false); - $this->cacheConfigMock = $this->getMock('Magento\PageCache\Model\Config', [], [], '', false); $this->messageSessionMock = $this->getMock('Magento\Framework\Message\Session', ['clearStorage'], [], '', false ); + $this->depersonalizeCheckerMock = $this->getMock( + 'Magento\PageCache\Model\DepersonalizeChecker', + [], + [], + '', + false + ); $this->plugin = new DepersonalizePlugin( - $this->requestMock, - $this->moduleManagerMock, + $this->depersonalizeCheckerMock, $this->eventManagerMock, - $this->cacheConfigMock, $this->messageSessionMock ); } - /** - * Test method afterGenerateXml with enabled module PageCache - */ - public function testAfterGenerateXmlPageCacheEnabled() + public function testAfterGenerateXml() { $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->cacheConfigMock->expects($this->once()) - ->method('isEnabled') - ->will($this->returnValue(true)); - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->will($this->returnValue(true)); - $this->requestMock->expects($this->once($this->once())) - ->method('isAjax') - ->will($this->returnValue(false)); - $this->layoutMock->expects($this->once()) - ->method('isCacheable') - ->will($this->returnValue(true)); $this->eventManagerMock->expects($this->once()) ->method('dispatch') ->with($this->equalTo('depersonalize_clear_session')); - $this->messageSessionMock->expects($this->once()) - ->method('clearStorage'); + $this->messageSessionMock->expects($this->once())->method('clearStorage'); + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(true); $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $expectedResult); $this->assertEquals($expectedResult, $actualResult); } - /** - * Test method afterGenerateXml with disabled module PageCache - */ - public function testAfterGenerateXmlPageCacheDisabled() + public function testAfterGenerateXmlNoDepersonalize() { + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(false); + $this->eventManagerMock->expects($this->never()) + ->method('dispatch'); + $this->messageSessionMock->expects($this->never())->method('clearStorage'); + $expectedResult = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with($this->equalTo('Magento_PageCache')) - ->will($this->returnValue(false)); - $this->requestMock->expects($this->never()) - ->method('isAjax') - ->will($this->returnValue(false)); $actualResult = $this->plugin->afterGenerateXml($this->layoutMock, $expectedResult); $this->assertEquals($expectedResult, $actualResult); } diff --git a/dev/tests/unit/testsuite/Magento/PageCache/Model/Observer/InvalidateCacheIfChangedTest.php b/dev/tests/unit/testsuite/Magento/PageCache/Model/Observer/InvalidateCacheIfChangedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..02492793b992328d184ec45879fc57f3bf1c38be --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/PageCache/Model/Observer/InvalidateCacheIfChangedTest.php @@ -0,0 +1,86 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\PageCache\Model\Observer; + +class InvalidateCacheIfChangedTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\PageCache\Model\Observer\InvalidateCacheIfChanged */ + protected $model; + + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\PageCache\Model\Config */ + protected $configMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\Cache\TypeListInterface */ + protected $typeListMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Event\Observer */ + protected $observerMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Object\IdentityInterface */ + protected $objectMock; + + /** + * Set up all mocks and data for test + */ + public function setUp() + { + $this->configMock = $this->getMock( + 'Magento\PageCache\Model\Config', + ['getType', 'isEnabled'], + [], + '', + false + ); + $this->typeListMock = $this->getMock('Magento\Framework\App\Cache\TypeList', [], [], '', false); + + $this->model = new \Magento\PageCache\Model\Observer\InvalidateCacheIfChanged( + $this->configMock, + $this->typeListMock + ); + + $this->observerMock = $this->getMock('Magento\Framework\Event\Observer', [], [], '', false); + $eventMock = $this->getMock('Magento\Framework\Event', ['getObject'], [], '', false); + $this->objectMock = $this->getMockForAbstractClass('Magento\Framework\Object\IdentityInterface', [], '', false); + $eventMock->expects($this->any())->method('getObject')->willReturn($this->objectMock); + $this->observerMock->expects($this->any())->method('getEvent')->willReturn($eventMock); + } + + /** + * @dataProvider invalidateCacheDataProvider + * @param bool $cacheState + */ + public function testExecuteChanged($cacheState) + { + $this->configMock->expects($this->once())->method('isEnabled')->will($this->returnValue($cacheState)); + + if ($cacheState) { + $this->typeListMock->expects($this->once())->method('invalidate')->with($this->equalTo('full_page')); + $this->objectMock->expects($this->once())->method('getIdentities')->will($this->returnValue(['tag_1'])); + } + $this->model->execute($this->observerMock); + } + + /** + * @dataProvider invalidateCacheDataProvider + * @param bool $cacheState + */ + public function testExecuteNoChanged($cacheState) + { + $this->configMock->expects($this->once())->method('isEnabled')->will($this->returnValue($cacheState)); + $this->typeListMock->expects($this->never())->method('invalidate'); + + if ($cacheState) { + $this->objectMock->expects($this->once())->method('getIdentities')->will($this->returnValue([])); + } + $this->model->execute($this->observerMock); + } + + public function invalidateCacheDataProvider() + { + return [[true], [false]]; + } +} diff --git a/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php b/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php index d48959f5885a3fa4ffee2844509746fa461b10d4..ae84619750d39fbab7bd3132451f61f181aa05d6 100644 --- a/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php +++ b/dev/tests/unit/testsuite/Magento/Persistent/Model/Layout/DepersonalizePluginTest.php @@ -15,21 +15,6 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase */ protected $persistentSessionMock; - /** - * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - - /** - * @var \Magento\Framework\Module\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $moduleManagerMock; - - /** - * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject - */ - protected $cacheConfigMock; - /** * @var \Magento\TestFramework\Helper\ObjectManager */ @@ -40,6 +25,11 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase */ protected $plugin; + /** + * @var \Magento\PageCache\Model\DepersonalizeChecker|\PHPUnit_Framework_MockObject_MockObject + */ + protected $depersonalizeCheckerMock; + /** * Set up * @@ -57,25 +47,13 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase false ); - $this->requestMock = $this->getMockForAbstractClass( - 'Magento\Framework\App\RequestInterface', - [], - '', - false, - true, - true, - ['isAjax'] - ); - $this->moduleManagerMock = $this->getMock( - 'Magento\Framework\Module\Manager', - ['isEnabled'], + $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); + + $this->moduleManagerMock = $this->getMock('Magento\Framework\Module\Manager', ['isEnabled'], [], '', false); + $this->cacheConfigMock = $this->getMock('Magento\PageCache\Model\Config', ['isEnabled'], [], '', false); + $this->depersonalizeCheckerMock = $this->getMock( + 'Magento\PageCache\Model\DepersonalizeChecker', [], - '', - false - ); - $this->cacheConfigMock = $this->getMock( - 'Magento\PageCache\Model\Config', - ['isEnabled'], [], '', false @@ -85,21 +63,12 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase 'Magento\Persistent\Model\Layout\DepersonalizePlugin', [ 'persistentSession' => $this->persistentSessionMock, - 'request' => $this->requestMock, - 'moduleManager' => $this->moduleManagerMock, - 'cacheConfig' => $this->cacheConfigMock + 'depersonalizeChecker' => $this->depersonalizeCheckerMock, ] ); } - /** - * Run test afterGenerateXml method - * - * @param bool $result - * - * @dataProvider dataProviderAfterGenerateXml - */ - public function testAfterGenerateXml($result) + public function testAfterGenerateXml() { /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $subjectMock */ $subjectMock = $this->getMockForAbstractClass( @@ -122,43 +91,38 @@ class DepersonalizePluginTest extends \PHPUnit_Framework_TestCase [] ); - $this->moduleManagerMock->expects($this->once()) - ->method('isEnabled') - ->with('Magento_PageCache') - ->willReturn($result); - $this->cacheConfigMock->expects($this->any()) - ->method('isEnabled') - ->willReturn($result); - $this->requestMock->expects($this->any()) - ->method('isAjax') - ->willReturn(!$result); - $subjectMock->expects($this->any()) - ->method('isCacheable') - ->willReturn($result); - - if ($result) { - $this->persistentSessionMock->expects($this->once()) - ->method('setCustomerId') - ->with(null); - } else { - $this->persistentSessionMock->expects($this->never()) - ->method('setCustomerId') - ->with(null); - } + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(true); + $this->persistentSessionMock->expects($this->once())->method('setCustomerId')->with(null); $this->assertEquals($resultMock, $this->plugin->afterGenerateXml($subjectMock, $resultMock)); } - /** - * Data provider for testAfterGenerateXml - * - * @return array - */ - public function dataProviderAfterGenerateXml() + public function testAfterGenerateXmlNoDepersonalize() { - return [ - ['result' => true], - ['result' => false] - ]; + /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $subjectMock */ + $subjectMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\LayoutInterface', + [], + '', + false, + true, + true, + ['isCacheable'] + ); + /** @var \Magento\Framework\View\LayoutInterface|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockForAbstractClass( + 'Magento\Framework\View\LayoutInterface', + [], + '', + false, + true, + true, + [] + ); + + $this->depersonalizeCheckerMock->expects($this->once())->method('checkIfDepersonalize')->willReturn(false); + $this->persistentSessionMock->expects($this->never())->method('setCustomerId'); + + $this->assertEquals($resultMock, $this->plugin->afterGenerateXml($subjectMock, $resultMock)); } } diff --git a/dev/tests/unit/testsuite/Magento/Search/Controller/Adminhtml/Ajax/SuggestTest.php b/dev/tests/unit/testsuite/Magento/Search/Controller/Adminhtml/Ajax/SuggestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0c74fd02428226911b6ca32ec5a9a34e3359cd0b --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Search/Controller/Adminhtml/Ajax/SuggestTest.php @@ -0,0 +1,117 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Search\Controller\Adminhtml\Ajax; + +use Magento\TestFramework\Helper\ObjectManager as ObjectManagerHelper; + +class SuggestTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Search\Controller\Ajax\Suggest */ + private $controller; + + /** @var ObjectManagerHelper */ + private $objectManagerHelper; + + /** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $response; + + /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $request; + + /** @var \Magento\Framework\UrlInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $url; + + /** @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject */ + private $context; + + /** @var \Magento\Search\Model\AutocompleteInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $autocomplete; + + protected function setUp() + { + $this->autocomplete = $this->getMockBuilder('Magento\Search\Model\AutocompleteInterface') + ->disableOriginalConstructor() + ->setMethods(['getItems']) + ->getMockForAbstractClass(); + $this->request = $this->getMockBuilder('\Magento\Framework\App\RequestInterface') + ->disableOriginalConstructor() + ->setMethods([]) + ->getMockForAbstractClass(); + $this->response = $this->getMockBuilder('\Magento\Framework\App\ResponseInterface') + ->disableOriginalConstructor() + ->setMethods(['representJson', 'setRedirect']) + ->getMockForAbstractClass(); + $this->url = $this->getMockBuilder('Magento\Framework\UrlInterface') + ->disableOriginalConstructor() + ->setMethods(['getBaseUrl']) + ->getMockForAbstractClass(); + $this->context = $this->getMockBuilder('Magento\Framework\App\Action\Context') + ->setMethods(['getRequest', 'getResponse', 'getUrl']) + ->disableOriginalConstructor() + ->getMock(); + $this->context->expects($this->atLeastOnce()) + ->method('getRequest') + ->will($this->returnValue($this->request)); + $this->context->expects($this->atLeastOnce()) + ->method('getResponse') + ->will($this->returnValue($this->response)); + $this->context->expects($this->any()) + ->method('getUrl') + ->will($this->returnValue($this->url)); + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->controller = $this->objectManagerHelper->getObject( + 'Magento\Search\Controller\Ajax\Suggest', + [ + 'context' => $this->context, + 'autocomplete' => $this->autocomplete + ] + ); + } + + public function testExecute() + { + $searchString = "simple"; + $firstItemMock = $this->getMockBuilder('Magento\Search\Model\Autocomplete\Item') + ->disableOriginalConstructor() + ->setMockClassName('FirstItem') + ->setMethods(['toArray']) + ->getMock(); + $secondItemMock = $this->getMockBuilder('Magento\Search\Model\Autocomplete\Item') + ->disableOriginalConstructor() + ->setMockClassName('SecondItem') + ->setMethods(['toArray']) + ->getMock(); + + $this->request->expects($this->once()) + ->method('getParam') + ->with('q') + ->will($this->returnValue($searchString)); + + $this->autocomplete->expects($this->once()) + ->method('getItems') + ->will($this->returnValue([$firstItemMock, $secondItemMock])); + + $this->response->expects($this->once()) + ->method('representJson'); + $this->controller->execute(); + } + + public function testExecuteEmptyQuery() + { + $searchString = ""; + + $this->request->expects($this->once()) + ->method('getParam') + ->with('q') + ->will($this->returnValue($searchString)); + $this->url->expects($this->once()) + ->method('getBaseUrl'); + $this->response->expects($this->once()) + ->method('setRedirect'); + $this->controller->execute(); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Search/Model/AdapterFactoryTest.php b/dev/tests/unit/testsuite/Magento/Search/Model/AdapterFactoryTest.php index a227f02f1f02d867c84b775abc55f791ddfda6cd..a72db4367feb84ed48343e227bb704836d26b576 100644 --- a/dev/tests/unit/testsuite/Magento/Search/Model/AdapterFactoryTest.php +++ b/dev/tests/unit/testsuite/Magento/Search/Model/AdapterFactoryTest.php @@ -19,33 +19,44 @@ class AdapterFactoryTest extends \PHPUnit_Framework_TestCase */ private $objectManager; + /** + * @var \Magento\TestFramework\Helper\ObjectManager + */ + private $helper; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeConfig; + protected function setUp() { - $helper = new ObjectManager($this); + $this->helper = new ObjectManager($this); - $scopeConfig = $this->getMockBuilder('\Magento\Framework\App\Config\ScopeConfigInterface') + $this->scopeConfig = $this->getMockBuilder('\Magento\Framework\App\Config\ScopeConfigInterface') ->disableOriginalConstructor() ->getMock(); - $scopeConfig->expects($this->once())->method('getValue') - ->with($this->equalTo('some_path'), $this->equalTo('some_scopeType')) - ->will($this->returnValue('ClassName')); - $this->objectManager = $this->getMock('Magento\Framework\ObjectManagerInterface'); - $this->adapterFactory = $helper->getObject( + $this->adapterFactory = $this->helper->getObject( '\Magento\Search\Model\AdapterFactory', [ 'objectManager' => $this->objectManager, - 'scopeConfig' => $scopeConfig, + 'scopeConfig' => $this->scopeConfig, 'path' => 'some_path', - 'scopeType' => 'some_scopeType' + 'scopeType' => 'some_scopeType', + 'adapters' => ['ClassName' => 'ClassName'] ] ); } public function testCreate() { + $this->scopeConfig->expects($this->once())->method('getValue') + ->with($this->equalTo('some_path'), $this->equalTo('some_scopeType')) + ->will($this->returnValue('ClassName')); + $adapter = $this->getMockBuilder('\Magento\Framework\Search\AdapterInterface') ->disableOriginalConstructor() ->getMock(); @@ -63,11 +74,25 @@ class AdapterFactoryTest extends \PHPUnit_Framework_TestCase */ public function testCreateExceptionThrown() { - $adapter = $this->getMock('Magento\Framework\ObjectManagerInterface'); + $this->scopeConfig->expects($this->once())->method('getValue') + ->with($this->equalTo('some_path'), $this->equalTo('some_scopeType')) + ->will($this->returnValue('ClassName')); $this->objectManager->expects($this->once())->method('create') ->with($this->equalTo('ClassName'), $this->equalTo(['input'])) - ->will($this->returnValue($adapter)); + ->will($this->returnValue('t')); + + $this->adapterFactory->create(['input']); + } + + /** + * @expectedException \LogicException + */ + public function testCreateLogicException() + { + $this->scopeConfig->expects($this->once())->method('getValue') + ->with($this->equalTo('some_path'), $this->equalTo('some_scopeType')) + ->will($this->returnValue('Class')); $this->adapterFactory->create(['input']); } diff --git a/dev/tests/unit/testsuite/Magento/Search/Model/AutocompleteTest.php b/dev/tests/unit/testsuite/Magento/Search/Model/AutocompleteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6d941a62edcc75766324c5a564bf04066eb914fa --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Search/Model/AutocompleteTest.php @@ -0,0 +1,71 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Search\Model; + +use Magento\TestFramework\Helper\ObjectManager; +use Magento\Search\Model\Autocomplete\DataProviderInterface; + +class AutocompleteTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Autocomplete + */ + private $model; + + /** + * @var DataProviderInterface |\PHPUnit_Framework_MockObject_MockObject + */ + private $firstDataProvider; + + /** + * @var DataProviderInterface |\PHPUnit_Framework_MockObject_MockObject + */ + private $secondDataProvider; + + protected function setUp() + { + $helper = new ObjectManager($this); + + $this->firstDataProvider = $this->getMockBuilder('Magento\Search\Model\DataProviderInterface') + ->disableOriginalConstructor() + ->setMethods(['getItems']) + ->getMock(); + $this->secondDataProvider = $this->getMockBuilder('Magento\Search\Model\DataProviderInterface') + ->disableOriginalConstructor() + ->setMethods(['getItems']) + ->getMock(); + $dataProviders = [ + '20' => $this->firstDataProvider, + '10' => $this->secondDataProvider + ]; + + $this->model = $helper->getObject( + 'Magento\Search\Model\Autocomplete', + ['dataProviders' => $dataProviders] + ); + } + + public function testGetItems() + { + $firstItemMock = $this->getMockBuilder('Magento\Search\Model\Autocomplete\Item') + ->disableOriginalConstructor() + ->setMockClassName('FirstItem') + ->getMock(); + $secondItemMock = $this->getMockBuilder('Magento\Search\Model\Autocomplete\Item') + ->disableOriginalConstructor() + ->setMockClassName('SecondItem') + ->getMock(); + + $this->firstDataProvider->expects($this->once()) + ->method('getItems') + ->willReturn([$firstItemMock]); + $this->secondDataProvider->expects($this->once()) + ->method('getItems') + ->willReturn([$secondItemMock]); + + $this->assertEquals([$secondItemMock, $firstItemMock], $this->model->getItems()); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Setup/Controller/DatabaseCheckTest.php b/dev/tests/unit/testsuite/Magento/Setup/Controller/DatabaseCheckTest.php index 3c062e1406134de1e4a165f2c04f62f0825f8630..e1306a04448d6114f95dc1c88e6498004d9e25fa 100644 --- a/dev/tests/unit/testsuite/Magento/Setup/Controller/DatabaseCheckTest.php +++ b/dev/tests/unit/testsuite/Magento/Setup/Controller/DatabaseCheckTest.php @@ -53,4 +53,10 @@ class DatabaseCheckTest extends \PHPUnit_Framework_TestCase $this->assertArrayHasKey('error', $variables); $this->assertFalse($variables['success']); } + + public function testIndexActionCheckPrefix() + { + $this->installer->expects($this->once())->method('checkDatabaseTablePrefix'); + $this->controller->indexAction(); + } } diff --git a/lib/internal/Magento/Framework/App/ObjectManagerFactory.php b/lib/internal/Magento/Framework/App/ObjectManagerFactory.php index 1ebedf86043fd2307a83ac3f35830afeb1f8de5a..8c777c869e82417a90e684ed24db56a204feac2e 100644 --- a/lib/internal/Magento/Framework/App/ObjectManagerFactory.php +++ b/lib/internal/Magento/Framework/App/ObjectManagerFactory.php @@ -127,6 +127,19 @@ class ObjectManagerFactory } } + // set cache profiler decorator if enabled + if (\Magento\Framework\Profiler::isEnabled()) { + $cacheFactoryArguments = $diConfig->getArguments('Magento\Framework\App\Cache\Frontend\Factory'); + $cacheFactoryArguments['decorators'][] = [ + 'class' => 'Magento\Framework\Cache\Frontend\Decorator\Profiler', + 'parameters' => ['backendPrefixes' => ['Zend_Cache_Backend_', 'Cm_Cache_Backend_']], + ]; + $cacheFactoryConfig = [ + 'Magento\Framework\App\Cache\Frontend\Factory' => ['arguments' => $cacheFactoryArguments] + ]; + $diConfig->extend($cacheFactoryConfig); + } + $sharedInstances = [ 'Magento\Framework\App\DeploymentConfig' => $deploymentConfig, 'Magento\Framework\App\Filesystem\DirectoryList' => $this->directoryList, diff --git a/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php new file mode 100644 index 0000000000000000000000000000000000000000..97f9476c4765e2f21b4661e7c2ecf32b1bf71bd4 --- /dev/null +++ b/lib/internal/Magento/Framework/DB/Helper/Mysql/Fulltext.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\DB\Helper\Mysql; + +use Magento\Framework\App\Resource; + +class Fulltext +{ + /** + * FULLTEXT search in MySQL search mode "natural language" + */ + const FULLTEXT_MODE_NATURAL = 'IN NATURAL LANGUAGE MODE'; + + /** + * FULLTEXT search in MySQL search mode "natural language with query expansion" + */ + const FULLTEXT_MODE_NATURAL_QUERY = 'IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION'; + + /** + * FULLTEXT search in MySQL search mode "boolean" + */ + const FULLTEXT_MODE_BOOLEAN = 'IN BOOLEAN MODE'; + + /** + * FULLTEXT search in MySQL search mode "query expansion" + */ + const FULLTEXT_MODE_QUERY = 'WITH QUERY EXPANSION'; + + /** + * FULLTEXT search in MySQL MATCH method + */ + const MATCH = 'MATCH'; + + /** + * FULLTEXT search in MySQL AGAINST method + */ + const AGAINST = 'AGAINST'; + + /** + * @var \Magento\Framework\DB\Adapter\AdapterInterface + */ + private $adapter; + + /** + * @param Resource $resource + */ + public function __construct(Resource $resource) + { + $this->adapter = $resource->getConnection(Resource::DEFAULT_READ_RESOURCE); + } + + /** + * Method for FULLTEXT search in Mysql, will generated MATCH ($columns) AGAINST ('$expression' $mode) + * + * @param string|string[] $columns Columns which add to MATCH () + * @param string $expression Expression which add to AGAINST () + * @param string $mode + * @return string + */ + public function getMatchQuery($columns, $expression, $mode = self::FULLTEXT_MODE_NATURAL) + { + if (is_array($columns)) { + $columns = implode(', ', $columns); + } + + $expression = $this->adapter->quote($expression); + + $condition = self::MATCH . " ({$columns}) " . self::AGAINST . " ({$expression} {$mode})"; + return $condition; + } + + /** + * Method for FULLTEXT search in Mysql, will added generated + * MATCH ($columns) AGAINST ('$expression' $mode) to where clause + * + * @param \Magento\Framework\DB\Select $select + * @param string|string[] $columns Columns which add to MATCH () + * @param string $expression Expression which add to AGAINST () + * @param bool $isCondition true=AND, false=OR + * @param string $mode + * @return \Magento\Framework\DB\Select + */ + public function match($select, $columns, $expression, $isCondition = true, $mode = self::FULLTEXT_MODE_NATURAL) + { + $fullCondition = $this->getMatchQuery($columns, $expression, $mode); + + if ($isCondition) { + $select->where($fullCondition); + } else { + $select->orWhere($fullCondition); + } + + return $select; + } +} diff --git a/lib/internal/Magento/Framework/DB/Select.php b/lib/internal/Magento/Framework/DB/Select.php index 41e87249ca198f4abecd7d2b42ef0a2d74b6fc94..48a8840de83dbdb082628f89df6e3eab0dc5c71f 100644 --- a/lib/internal/Magento/Framework/DB/Select.php +++ b/lib/internal/Magento/Framework/DB/Select.php @@ -46,36 +46,6 @@ class Select extends \Zend_Db_Select */ const SQL_STRAIGHT_JOIN = 'STRAIGHT_JOIN'; - /** - * FULLTEXT search in MySQL search mode "natural language" - */ - const FULLTEXT_MODE_NATURAL = 'IN NATURAL LANGUAGE MODE'; - - /** - * FULLTEXT search in MySQL search mode "natural language with query expansion" - */ - const FULLTEXT_MODE_NATURAL_QUERY = 'IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION'; - - /** - * FULLTEXT search in MySQL search mode "boolean" - */ - const FULLTEXT_MODE_BOOLEAN = 'IN BOOLEAN MODE'; - - /** - * FULLTEXT search in MySQL search mode "query expansion" - */ - const FULLTEXT_MODE_QUERY = 'WITH QUERY EXPANSION'; - - /** - * FULLTEXT search in MySQL MATCH method - */ - const MATCH = 'MATCH'; - - /** - * FULLTEXT search in MySQL AGAINST method - */ - const AGAINST = 'AGAINST'; - /** * Class constructor * Add straight join support @@ -137,49 +107,6 @@ class Select extends \Zend_Db_Select return parent::where($cond, $value, $type); } - /** - * Method for FULLTEXT search in Mysql, will generated MATCH ($columns) AGAINST ('$expression' $mode) - * - * @param string|string[] $columns Columns which add to MATCH () - * @param string $expression Expression which add to AGAINST () - * @param string $mode - * @return string - */ - public function getMatchQuery($columns, $expression, $mode = self::FULLTEXT_MODE_NATURAL) - { - if (is_array($columns)) { - $columns = implode(', ', $columns); - } - - $expression = $this->getAdapter()->quote($expression); - - $condition = self::MATCH . " ({$columns}) " . self::AGAINST . " ({$expression} {$mode})"; - return $condition; - } - - /** - * Method for FULLTEXT search in Mysql, will added generated - * MATCH ($columns) AGAINST ('$expression' $mode) to where clause - * - * @param string|string[] $columns Columns which add to MATCH () - * @param string $expression Expression which add to AGAINST () - * @param bool $isCondition true=AND, false=OR - * @param string $mode - * @return $this - */ - public function match($columns, $expression, $isCondition = true, $mode = self::FULLTEXT_MODE_NATURAL) - { - $fullCondition = $this->getMatchQuery($columns, $expression, $mode); - - if ($isCondition) { - $this->where($fullCondition); - } else { - $this->orWhere($fullCondition); - } - - return $this; - } - /** * Reset unused LEFT JOIN(s) * diff --git a/lib/internal/Magento/Framework/Module/ModuleList/Loader.php b/lib/internal/Magento/Framework/Module/ModuleList/Loader.php index 6c5697243d8647a82de5e655a8b10b22677fe5cd..943ed35520cbc0406eb694274fc8143147cc9d93 100644 --- a/lib/internal/Magento/Framework/Module/ModuleList/Loader.php +++ b/lib/internal/Magento/Framework/Module/ModuleList/Loader.php @@ -9,6 +9,7 @@ namespace Magento\Framework\Module\ModuleList; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; use Magento\Framework\Module\Declaration\Converter\Dom; +use Magento\Framework\Xml\Parser; /** * Loader of module list information from the filesystem @@ -29,21 +30,32 @@ class Loader */ private $converter; + /** + * Parser + * + * @var \Magento\Framework\Xml\Parser + */ + private $parser; + /** * Constructor * * @param Filesystem $filesystem * @param Dom $converter + * @param Parser $parser */ - public function __construct(Filesystem $filesystem, Dom $converter) + public function __construct(Filesystem $filesystem, Dom $converter, Parser $parser) { $this->filesystem = $filesystem; $this->converter = $converter; + $this->parser = $parser; + $this->parser->initErrorHandler(); } /** * Loads the full module list information * + * @throws \Magento\Framework\Exception * @return array */ public function load() @@ -52,9 +64,18 @@ class Loader $dir = $this->filesystem->getDirectoryRead(DirectoryList::MODULES); foreach ($dir->search('*/*/etc/module.xml') as $file) { $contents = $dir->readFile($file); - $dom = new \DOMDocument(); - $dom->loadXML($contents); - $data = $this->converter->convert($dom); + + try { + $this->parser->loadXML($contents); + } catch (\Magento\Framework\Exception $e) { + throw new \Magento\Framework\Exception( + 'Invalid Document: ' . $file . PHP_EOL . ' Error: ' . $e->getMessage(), + $e->getCode(), + $e + ); + } + + $data = $this->converter->convert($this->parser->getDom()); $name = key($data); $result[$name] = $data[$name]; } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/IntervalFactory.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/IntervalFactory.php deleted file mode 100644 index 0a3756aee24a06e389db8190bdcc8bc5e147ff13..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/IntervalFactory.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\Search\Adapter\Mysql\Aggregation; - -/** - * Factory class for Magento\Framework\Search\Adapter\Mysql\Aggregation\Interval - */ -class IntervalFactory -{ - /** - * Object Manager instance - * - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $_objectManager = null; - - /** - * Instance name to create - * - * @var string - */ - protected $_instanceName = 'Magento\Framework\Search\Adapter\Mysql\Aggregation\Interval'; - - /** - * Factory constructor - * - * @param \Magento\Framework\ObjectManagerInterface $objectManager - */ - public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager) - { - $this->_objectManager = $objectManager; - } - - /** - * Create class instance with specified parameters - * - * @param array $data - * @return \Magento\Framework\Search\Adapter\Mysql\Aggregation\Interval - */ - public function create(array $data = []) - { - return $this->_objectManager->create($this->_instanceName, $data); - } -} diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php index d5b870c4be3fe164ffe505158c29b4e3295e6941..ced123772efa9e62a017b7b73b1af3e4170c75ce 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Adapter\Mysql\Query\Builder; +use Magento\Framework\DB\Helper\Mysql\Fulltext; use Magento\Framework\DB\Select; use Magento\Framework\Search\Adapter\Mysql\Field\ResolverInterface; use Magento\Framework\Search\Adapter\Mysql\ScoreBuilder; @@ -27,13 +28,20 @@ class Match implements QueryInterface */ private $resolver; + /** + * @var Fulltext + */ + private $fulltextHelper; + /** * @param ResolverInterface $resolver + * @param Fulltext $fulltextHelper */ - public function __construct(ResolverInterface $resolver) + public function __construct(ResolverInterface $resolver, Fulltext $fulltextHelper) { $this->resolver = $resolver; $this->replaceSymbols = str_split(self::SPECIAL_CHARACTERS, 1); + $this->fulltextHelper = $fulltextHelper; } /** @@ -56,10 +64,16 @@ class Match implements QueryInterface $queryBoost = $query->getBoost(); $scoreBuilder->addCondition( - $select->getMatchQuery($resolvedFieldList, $queryValue, Select::FULLTEXT_MODE_BOOLEAN), + $this->fulltextHelper->getMatchQuery($resolvedFieldList, $queryValue, Fulltext::FULLTEXT_MODE_BOOLEAN), !is_null($queryBoost) ? $queryBoost : 1 ); - $select->match($resolvedFieldList, $queryValue, true, Select::FULLTEXT_MODE_BOOLEAN); + $select = $this->fulltextHelper->match( + $select, + $resolvedFieldList, + $queryValue, + true, + Fulltext::FULLTEXT_MODE_BOOLEAN + ); return $select; } diff --git a/lib/internal/Magento/Framework/Search/Adapter/OptionsInterface.php b/lib/internal/Magento/Framework/Search/Adapter/OptionsInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d3795424ccb215edc69f3283a18304877d4ffeda --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Adapter/OptionsInterface.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Search\Adapter; + +interface OptionsInterface +{ + /** + * Get all options + * + * @return array + */ + public function get(); +} diff --git a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Auto.php b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Auto.php index 61badd04e04ac5f784ba5aae15d72fa3d7959106..8a1950281d70ea84517d60876141d7f5ed66203e 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Auto.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Auto.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Dynamic\Algorithm; +use Magento\Framework\Search\Adapter\OptionsInterface; use Magento\Framework\Search\Dynamic\DataProviderInterface; use Magento\Framework\Search\Request\BucketInterface; @@ -15,12 +16,19 @@ class Auto implements AlgorithmInterface */ private $dataProvider; + /** + * @var OptionsInterface + */ + private $options; + /** * @param DataProviderInterface $dataProvider + * @param OptionsInterface $options */ - public function __construct(DataProviderInterface $dataProvider) + public function __construct(DataProviderInterface $dataProvider, OptionsInterface $options) { $this->dataProvider = $dataProvider; + $this->options = $options; } /** @@ -30,7 +38,7 @@ class Auto implements AlgorithmInterface { $data = []; $range = $this->dataProvider->getRange(); - if (!$range) { + if (!$range && !empty($entityIds)) { $range = $this->getRange($bucket, $dimensions, $entityIds); $dbRanges = $this->dataProvider->getAggregation($bucket, $dimensions, $range, $entityIds, 'count'); $data = $this->dataProvider->prepareData($range, $dbRanges); @@ -79,7 +87,7 @@ class Auto implements AlgorithmInterface */ private function getMinRangePower() { - $options = $this->dataProvider->getOptions(); + $options = $this->options->get(); return $options['min_range_power']; } diff --git a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Improved.php b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Improved.php index 77edb421e141469c3b105a8bafb16fc7643f1b9c..f27f9fc96c56e15aefa8732900297f19c4b76e04 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Improved.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Improved.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Dynamic\Algorithm; +use Magento\Framework\Search\Adapter\OptionsInterface; use Magento\Framework\Search\Dynamic\Algorithm; use Magento\Framework\Search\Dynamic\DataProviderInterface; use Magento\Framework\Search\Request\BucketInterface; @@ -21,16 +22,24 @@ class Improved implements AlgorithmInterface */ private $dataProvider; + /** + * @var OptionsInterface + */ + private $options; + /** * @param DataProviderInterface $dataProvider * @param Algorithm $algorithm + * @param OptionsInterface $options */ public function __construct( DataProviderInterface $dataProvider, - Algorithm $algorithm + Algorithm $algorithm, + OptionsInterface $options ) { $this->algorithm = $algorithm; $this->dataProvider = $dataProvider; + $this->options = $options; } /** @@ -40,7 +49,7 @@ class Improved implements AlgorithmInterface { $aggregations = $this->dataProvider->getAggregations($entityIds); - $options = $this->dataProvider->getOptions(); + $options = $this->options->get(); if ($aggregations['count'] < $options['interval_division_limit']) { return []; } @@ -65,6 +74,7 @@ class Improved implements AlgorithmInterface $data[$key]['to'] = $data[$key + 1]['from']; } } + return $data; } } diff --git a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Manual.php b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Manual.php index 52a5d208a53b6d732d1b56ffc7db1a3cfa762d17..3bacc28cbeae9a269d24a1dd28e4d7083128fcae 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Manual.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/Algorithm/Manual.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Dynamic\Algorithm; +use Magento\Framework\Search\Adapter\OptionsInterface; use Magento\Framework\Search\Dynamic\DataProviderInterface; use Magento\Framework\Search\Request\BucketInterface; @@ -15,12 +16,19 @@ class Manual implements AlgorithmInterface */ private $dataProvider; + /** + * @var OptionsInterface + */ + private $options; + /** * @param DataProviderInterface $dataProvider + * @param OptionsInterface $options */ - public function __construct(DataProviderInterface $dataProvider) + public function __construct(DataProviderInterface $dataProvider, OptionsInterface $options) { $this->dataProvider = $dataProvider; + $this->options = $options; } /** @@ -29,7 +37,7 @@ class Manual implements AlgorithmInterface public function getItems(BucketInterface $bucket, array $dimensions, array $entityIds) { $range = $this->dataProvider->getRange(); - $options = $this->dataProvider->getOptions(); + $options = $this->options->get(); if (!$range) { $range = $options['range_step']; } diff --git a/lib/internal/Magento/Framework/Search/Dynamic/DataProviderFactory.php b/lib/internal/Magento/Framework/Search/Dynamic/DataProviderFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..1cfc1477a7957b46fe1f58f752749b3d8a4193a2 --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Dynamic/DataProviderFactory.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Search\Dynamic; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ScopeInterface; +use Magento\Framework\ObjectManagerInterface; + +class DataProviderFactory +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var string + */ + private $dataProvider; + + /** + * @param ObjectManagerInterface $objectManager + * @param ScopeConfigInterface $scopeConfig + * @param string $configPath + * @param string[] $dataProviders + * @param string $scope + */ + public function __construct( + ObjectManagerInterface $objectManager, + ScopeConfigInterface $scopeConfig, + $configPath, + $dataProviders, + $scope = ScopeInterface::SCOPE_DEFAULT + ) { + $this->objectManager = $objectManager; + $configValue = $scopeConfig->getValue($configPath, $scope); + if (isset($dataProviders[$configValue])) { + $this->dataProvider = $dataProviders[$configValue]; + } else { + throw new \LogicException("DataProvider not found by config {$configValue}"); + } + } + + /** + * Create data provider + * + * @param array $data + * @return DataProviderInterface + */ + public function create(array $data = []) + { + $dataProvider = $this->objectManager->create($this->dataProvider, $data); + if (!$dataProvider instanceof DataProviderInterface) { + throw new \LogicException( + 'DataProvider not instance of interface \Magento\Framework\Search\Dynamic\DataProviderInterface' + ); + } + return $dataProvider; + } +} diff --git a/lib/internal/Magento/Framework/Search/Dynamic/DataProviderInterface.php b/lib/internal/Magento/Framework/Search/Dynamic/DataProviderInterface.php index da65f43c05c794fe3bd0f48ef002e0d117302612..264f5dbd7dd9d93bed53c326fbf2e266aba5dc76 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/DataProviderInterface.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/DataProviderInterface.php @@ -22,13 +22,6 @@ interface DataProviderInterface */ public function getAggregations(array $entityIds); - /** - * Get all options - * - * @return array - */ - public function getOptions(); - /** * @param BucketInterface $bucket * @param array $dimensions diff --git a/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php b/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php index 912a406e30c240da7813b5bb99dbc8cd4d4e199c..bba9824e19083f82aa5c249338bf16d2d4da5575 100644 --- a/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php +++ b/lib/internal/Magento/Framework/Search/Dynamic/IntervalFactory.php @@ -47,11 +47,12 @@ class IntervalFactory /** * Create interval * + * @param array $data * @return IntervalInterface */ - public function create() + public function create(array $data = []) { - $interval = $this->objectManager->create($this->interval); + $interval = $this->objectManager->create($this->interval, $data); if (!$interval instanceof IntervalInterface) { throw new \LogicException( 'Interval not instance of interface \Magento\Framework\Search\Dynamic\IntervalInterface' diff --git a/lib/internal/Magento/Framework/Search/Request/Builder.php b/lib/internal/Magento/Framework/Search/Request/Builder.php index 997f2415b5e33011aac4a58a45d654d06b63b98e..0f281b89d748ac21f0984bcf21fa2e0e16de2ccf 100644 --- a/lib/internal/Magento/Framework/Search/Request/Builder.php +++ b/lib/internal/Magento/Framework/Search/Request/Builder.php @@ -107,7 +107,7 @@ class Builder * Bind data to placeholder * * @param string $placeholder - * @param string $value + * @param mixed $value * @return $this */ public function bind($placeholder, $value) diff --git a/lib/internal/Magento/Framework/Search/Response/Aggregation.php b/lib/internal/Magento/Framework/Search/Response/Aggregation.php index cb22e177fb23e30e50ac976c4ec17ef9f17ebb30..7b6bb6d685e512800a061982e355ba54bc6ea5bc 100644 --- a/lib/internal/Magento/Framework/Search/Response/Aggregation.php +++ b/lib/internal/Magento/Framework/Search/Response/Aggregation.php @@ -43,7 +43,7 @@ class Aggregation implements \IteratorAggregate */ public function getBucket($bucketName) { - return $this->buckets[$bucketName]; + return isset($this->buckets[$bucketName]) ? $this->buckets[$bucketName] : null; } /** diff --git a/lib/internal/Magento/Framework/Xml/Parser.php b/lib/internal/Magento/Framework/Xml/Parser.php index 46e1303d39fa481cb9420d620d939a06945bd878..02c762922afb447497dc935f649a783a024150d9 100644 --- a/lib/internal/Magento/Framework/Xml/Parser.php +++ b/lib/internal/Magento/Framework/Xml/Parser.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\Xml; +use \Magento\Framework\Exception; + class Parser { /** @@ -22,6 +24,11 @@ class Parser */ protected $_content = []; + /** + * @var boolean + */ + protected $errorHandlerIsActive = false; + /** * */ @@ -32,6 +39,16 @@ class Parser return $this; } + /** + * Initializes error handler + * + * @return void + */ + public function initErrorHandler() + { + $this->errorHandlerIsActive = true; + } + /** * @return \DOMDocument|null */ @@ -135,7 +152,39 @@ class Parser */ public function loadXML($string) { - $this->getDom()->loadXML($string); + if ($this->errorHandlerIsActive) { + set_error_handler([$this, 'errorHandler']); + } + + try { + $this->getDom()->loadXML($string); + } catch (\Magento\Framework\Exception $e) { + restore_error_handler(); + throw new \Magento\Framework\Exception($e->getMessage(), $e->getCode(), $e); + } + + if ($this->errorHandlerIsActive) { + restore_error_handler(); + } + return $this; } + + /** + * Custom XML lib error handler + * + * @param int $errorNo + * @param string $errorStr + * @param string $errorFile + * @param int $errorLine + * @throws \Magento\Framework\Exception + * @return void + */ + public function errorHandler($errorNo, $errorStr, $errorFile, $errorLine) + { + if ($errorNo != 0) { + $message = "{$errorStr} in {$errorFile} on line {$errorLine}"; + throw new \Magento\Framework\Exception($message); + } + } } diff --git a/setup/pub/magento/setup/create-admin-account.js b/setup/pub/magento/setup/create-admin-account.js index c2cabdb63cffcf9c966bc6b657730f8331a9ff8d..423ef0a341f8e86db3bc7c91e2427725054c2f10 100644 --- a/setup/pub/magento/setup/create-admin-account.js +++ b/setup/pub/magento/setup/create-admin-account.js @@ -18,21 +18,21 @@ angular.module('create-admin-account', ['ngStorage']) return; } var p = $scope.admin.password; - if (p.length > 6 && p.match(/[\d]+/) && p.match(/[a-z]+/) && p.match(/[A-Z]+/) && p.match(/[!@#$%^*()_\/\\\-\+=]+/)) { + if (p.length >= 6 && p.match(/[\d]+/) && p.match(/[a-z]+/) && p.match(/[A-Z]+/) && p.match(/[!@#$%^*()_\/\\\-\+=]+/)) { $scope.admin.passwordStatus.class = 'strong'; $scope.admin.passwordStatus.label = 'Strong'; - } else if (p.length > 6 && p.match(/[\d]+/) && p.match(/[a-z]+/) && p.match(/[A-Z]+/)) { + } else if (p.length >= 6 && p.match(/[\d]+/) && p.match(/[a-z]+/) && p.match(/[A-Z]+/)) { $scope.admin.passwordStatus.class = 'good'; $scope.admin.passwordStatus.label = 'Good'; - } else if (p.length > 6 && p.match(/[\d]+/) && p.match(/[a-zA-Z]+/)) { + } else if (p.length >= 6 && p.match(/[\d]+/) && p.match(/[a-zA-Z]+/)) { + $scope.admin.passwordStatus.class = 'fair'; + $scope.admin.passwordStatus.label = 'Fair'; + } else if (p.length >= 6) { $scope.admin.passwordStatus.class = 'weak'; $scope.admin.passwordStatus.label = 'Weak'; - } else if (p.length > 6) { - $scope.admin.passwordStatus.class = 'to-short'; - $scope.admin.passwordStatus.label = 'Too Short'; } else { - $scope.admin.passwordStatus.class = 'none'; - $scope.admin.passwordStatus.label = 'None'; + $scope.admin.passwordStatus.class = 'too-short'; + $scope.admin.passwordStatus.label = 'Too Short'; } }; @@ -71,7 +71,7 @@ angular.module('create-admin-account', ['ngStorage']) require: "ngModel", link: function(scope, elm, attrs, ctrl){ var validator = function(value){ - var minReg = /^(?=.*\d)(?=.*[a-zA-Z])[a-zA-Z0-9]{6,}$/, + var minReg = /^(?=.*\d)(?=.*[a-zA-Z]).{6,}$/, isValid = typeof value === 'string' && minReg.test(value); ctrl.$setValidity('checkPassword', isValid); diff --git a/setup/pub/styles/setup.css b/setup/pub/styles/setup.css index e1cc3503329982b2dafb64e3a809772ce1747e47..2b738d61e6ee37fd1d75260db370b4e012fae368 100644 --- a/setup/pub/styles/setup.css +++ b/setup/pub/styles/setup.css @@ -3,4 +3,4 @@ * See COPYING.txt for license details. */ -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{box-sizing:border-box}:focus{box-shadow:none;outline:0}.keyfocus :focus{box-shadow:0 0 0 1px #008bdb}embed,img,object,video{max-width:100%}.abs-clearer:after,.form-row:after,.header:after,.ie9 .alert:after,.nav:after,.row:after{content:"";display:table;clear:both}.ng-cloak{display:none!important}.hide.hide{display:none}.show.show{display:block}.text-center{text-align:center}.text-right{text-align:right}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/light/opensans-300.eot);src:url(../../pub/fonts/opensans/light/opensans-300.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/light/opensans-300.woff2) format('woff2'),url(../../pub/fonts/opensans/light/opensans-300.woff) format('woff'),url(../../pub/fonts/opensans/light/opensans-300.ttf) format('truetype'),url('../../pub/fonts/opensans/light/opensans-300.svg#Open Sans') format('svg');font-weight:300;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/regular/opensans-400.eot);src:url(../../pub/fonts/opensans/regular/opensans-400.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/regular/opensans-400.woff2) format('woff2'),url(../../pub/fonts/opensans/regular/opensans-400.woff) format('woff'),url(../../pub/fonts/opensans/regular/opensans-400.ttf) format('truetype'),url('../../pub/fonts/opensans/regular/opensans-400.svg#Open Sans') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/semibold/opensans-600.eot);src:url(../../pub/fonts/opensans/semibold/opensans-600.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/semibold/opensans-600.woff2) format('woff2'),url(../../pub/fonts/opensans/semibold/opensans-600.woff) format('woff'),url(../../pub/fonts/opensans/semibold/opensans-600.ttf) format('truetype'),url('../../pub/fonts/opensans/semibold/opensans-600.svg#Open Sans') format('svg');font-weight:600;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/bold/opensans-700.eot);src:url(../../pub/fonts/opensans/bold/opensans-700.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/bold/opensans-700.woff2) format('woff2'),url(../../pub/fonts/opensans/bold/opensans-700.woff) format('woff'),url(../../pub/fonts/opensans/bold/opensans-700.ttf) format('truetype'),url('../../pub/fonts/opensans/bold/opensans-700.svg#Open Sans') format('svg');font-weight:700;font-style:normal}html{font-size:62.5%}body{color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:400;line-height:1.4}h1,h2,h3,h4,h5,h6{font-weight:400;margin-top:0}p{margin:0 0 1em}a{color:#008bdb;text-decoration:none}a:hover{color:#0fa7ff;text-decoration:underline}@font-face{font-family:Icons;src:url(../../pub/fonts/icons/icons.eot);src:url(../../pub/fonts/icons/icons.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/icons/icons.woff2) format('woff2'),url(../../pub/fonts/icons/icons.woff) format('woff'),url(../../pub/fonts/icons/icons.ttf) format('truetype'),url(../../pub/fonts/icons/icons.svg#Icons) format('svg');font-weight:400;font-style:normal}[class*=icon-]{display:inline-block;line-height:1}[class*=icon-]:after{font-family:Icons}.icon-success-thick:after{content:'\e600'}.icon-success:after{content:'\e601'}.icon-collapse:after{content:'\e602'}.icon-failed-thick:after{content:'\e603'}.icon-failed:after{content:'\e604'}.icon-expand:after{content:'\e605'}.icon-warning:after{content:'\e606'}.icon-failed-round,.icon-success-round{border-radius:100%;color:#fff;font-size:2.5rem;height:1em;position:relative;text-align:center;width:1em}.icon-failed-round:after,.icon-success-round:after{bottom:0;font-size:.8em;left:0;position:absolute;right:0;top:.15em}.icon-success-round{background-color:#79a22e}.icon-success-round:after{content:'\e600'}.icon-failed-round{background-color:#e22626}.icon-failed-round:after{content:'\e603'}dl,ol,ul{margin-top:0}.list{margin-bottom:1em;padding-left:0}.list>li{display:block;margin-bottom:.75em;position:relative}.list>li>.icon-failed,.list>li>.icon-success{font-size:1.6em;left:-.1em;position:absolute;top:0}.list>li>.icon-success{color:#79a22e}.list>li>.icon-failed{color:#e22626}.list-item-failed,.list-item-icon,.list-item-success{padding-left:3.5rem}.list-item-failed:before,.list-item-success:before{font-family:Icons;font-size:1.6em;left:-.1em;position:absolute;top:-.2em}.list-item-success:before{color:#79a22e;content:'\e601'}.list-item-failed:before{color:#e22626;content:'\e604'}.list-definition{margin:0 0 3rem;padding:0}.list-definition>dt{clear:left;float:left}.list-definition>dd{margin-bottom:1em;margin-left:20rem}.btn-wrap{margin:0 auto}.btn-wrap .btn{width:100%}.btn{background:#e3e3e3;border:none;color:#514943;display:inline-block;font-size:1.6rem;font-weight:600;padding:.45em .5em;text-align:center}.btn:hover{background-color:#dbdbdb;color:#514943;text-decoration:none}.btn:active{background-color:#d6d6d6}.btn.disabled,.btn[disabled]{cursor:default;opacity:.5;pointer-events:none}.ie9 .btn.disabled,.ie9 .btn[disabled]{background-color:#f0f0f0;opacity:1;text-shadow:none}.btn-large{padding:.75em 1.25em}.btn-link{background-color:transparent;border:none;color:#008bdb;font-family:1.6rem;font-size:1.5rem}.btn-link:hover{background-color:transparent;color:#0fa7ff}.btn-prime{background-color:#eb5202;color:#fff;text-shadow:1px 1px 0 rgba(0,0,0,.25)}.btn-prime:hover{background-color:#f65405;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,color-stop(#e04f00 0),color-stop(#f65405 100%));background-image:linear-gradient(to right,#e04f00 0,#f65405 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e04f00', endColorstr='#f65405', GradientType=1);color:#fff}.btn-prime:active{background-color:#e04f00;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,color-stop(#f65405 0),color-stop(#e04f00 100%));background-image:linear-gradient(to right,#f65405 0,#e04f00 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f65405', endColorstr='#e04f00', GradientType=1)}.ie9 .btn-prime.disabled,.ie9 .btn-prime[disabled]{background-color:#fd6e23}.ie9 .btn-prime.disabled:active,.ie9 .btn-prime.disabled:hover,.ie9 .btn-prime[disabled]:active,.ie9 .btn-prime[disabled]:hover{background-color:#fd6e23;filter:none}.btn-secondary{background-color:#514943;color:#fff}.btn-secondary:hover{background-color:#5f564f;color:#fff}.btn-secondary:active{background-color:#574e48}.ie9 .btn-secondary.disabled,.ie9 .btn-secondary[disabled]{background-color:#514943}.ie9 .btn-secondary.disabled:active,.ie9 .btn-secondary.disabled:hover,.ie9 .btn-secondary[disabled]:active,.ie9 .btn-secondary[disabled]:hover{background-color:#514943;filter:none}[class*=btn-wrap-triangle]{overflow:hidden;position:relative}[class*=btn-wrap-triangle] .btn:after{border-style:solid;content:'';height:0;position:absolute;top:0;width:0}.btn-wrap-triangle-right{display:inline-block;padding-right:1.74rem;position:relative}.btn-wrap-triangle-right .btn{text-indent:.92rem}.btn-wrap-triangle-right .btn:after{border-color:transparent transparent transparent #e3e3e3;border-width:1.84rem 0 1.84rem 1.84rem;left:100%;margin-left:-1.74rem}.btn-wrap-triangle-right .btn:hover:after{border-left-color:#dbdbdb}.btn-wrap-triangle-right .btn:active:after{border-left-color:#d6d6d6}.btn-wrap-triangle-right .btn:not(.disabled):active,.btn-wrap-triangle-right .btn:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn.disabled:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:after{border-color:transparent transparent transparent #f0f0f0}.ie9 .btn-wrap-triangle-right .btn.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:hover:after{border-left-color:#f0f0f0}.btn-wrap-triangle-right .btn-prime:after{border-color:transparent transparent transparent #eb5202}.btn-wrap-triangle-right .btn-prime:hover:after{border-left-color:#f65405}.btn-wrap-triangle-right .btn-prime:active:after{border-left-color:#e04f00}.btn-wrap-triangle-right .btn-prime:not(.disabled):active,.btn-wrap-triangle-right .btn-prime:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:after{border-color:transparent transparent transparent #fd6e23}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:hover:after{border-left-color:#fd6e23}.btn-wrap-triangle-left{display:inline-block;padding-left:1.74rem}.btn-wrap-triangle-left .btn{text-indent:-.92rem}.btn-wrap-triangle-left .btn:after{border-color:transparent #e3e3e3 transparent transparent;border-width:1.84rem 1.84rem 1.84rem 0;margin-right:-1.74rem;right:100%}.btn-wrap-triangle-left .btn:hover:after{border-right-color:#dbdbdb}.btn-wrap-triangle-left .btn:active:after{border-right-color:#d6d6d6}.btn-wrap-triangle-left .btn:not(.disabled):active,.btn-wrap-triangle-left .btn:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn.disabled:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:after{border-color:transparent #f0f0f0 transparent transparent}.ie9 .btn-wrap-triangle-left .btn.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:hover:after{border-right-color:#f0f0f0}.btn-wrap-triangle-left .btn-prime:after{border-color:transparent #eb5202 transparent transparent}.btn-wrap-triangle-left .btn-prime:hover:after{border-right-color:#e04f00}.btn-wrap-triangle-left .btn-prime:active:after{border-right-color:#f65405}.btn-wrap-triangle-left .btn-prime:not(.disabled):active,.btn-wrap-triangle-left .btn-prime:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:after{border-color:transparent #fd6e23 transparent transparent}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:hover:after{border-right-color:#fd6e23}.btn-expand{background-color:transparent;border:none;color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;padding:0;position:relative}.btn-expand.expanded:after{border-color:transparent transparent #303030;border-width:0 .285em .36em}.btn-expand.expanded:hover:after{border-color:transparent transparent #3d3d3d}.btn-expand:hover{background-color:transparent;border:none;color:#3d3d3d}.btn-expand:hover:after{border-color:#3d3d3d transparent transparent}.btn-expand:after{border-color:#303030 transparent transparent;border-style:solid;border-width:.36em .285em 0;content:'';height:0;left:100%;margin-left:.5em;margin-top:-.18em;position:absolute;top:50%;width:0}[class*=col-] .form-el-input,[class*=col-] .form-el-select{width:100%}.form-fieldset{border:none;margin:0 0 1em;padding:0}.form-row{margin-bottom:2.2rem}.form-row .form-row{margin-bottom:.4rem}.form-row .form-label{display:block;font-weight:600;padding:.6rem 2.1em 0 0;text-align:right}.form-row .form-label.required{position:relative}.form-row .form-label.required:after{color:#eb5202;content:'*';font-size:1.15em;position:absolute;right:.7em;top:.5em}.form-row .form-el-checkbox+.form-label:before,.form-row .form-el-radio+.form-label:before{top:.7rem}.form-row .form-el-checkbox+.form-label:after,.form-row .form-el-radio+.form-label:after{top:1.1rem}input:not([disabled]):focus,textarea:not([disabled]):focus{box-shadow:none}.form-el-input{border:1px solid #adadad;border-radius:2px;color:#303030;padding:.35em .55em .5em}.form-el-input:hover{border-color:#949494}.form-el-input:focus{border-color:#008bdb}.form-label{margin-bottom:.5em}[class*=form-label][for]{cursor:pointer}.form-el-insider-wrap{display:table;width:100%}.form-el-insider-input{display:table-cell;width:100%}.form-el-insider{border-radius:2px;display:table-cell;vertical-align:top;padding:.43em .55em .5em 0}.form-legend,.form-legend-expand,.form-legend-light{display:block;margin:0}.form-legend,.form-legend-expand{margin-bottom:2.5em;padding-top:1.5em;font-weight:600;font-size:1.25em}.form-legend{width:100%;border-top:1px solid #ccc}.form-legend-light{margin-bottom:1.5em;font-size:1em}.form-legend-expand{transition:opacity .2s linear;cursor:pointer}.form-legend-expand:hover{opacity:.85}.form-legend-expand.expanded:after{content:'\e602'}.form-legend-expand:after{margin-left:.5em;font-weight:400;font-size:1.15em;font-family:Icons;content:'\e605';vertical-align:sub}.form-el-checkbox,.form-el-radio{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.form-el-checkbox.disabled+.form-label,.form-el-checkbox.disabled+.form-label:before,.form-el-checkbox[disabled]+.form-label,.form-el-checkbox[disabled]+.form-label:before,.form-el-radio.disabled+.form-label,.form-el-radio.disabled+.form-label:before,.form-el-radio[disabled]+.form-label,.form-el-radio[disabled]+.form-label:before{cursor:default;opacity:.5;pointer-events:none}.form-el-checkbox:not(.disabled)+.form-label:hover:before,.form-el-checkbox:not([disabled])+.form-label:hover:before,.form-el-radio:not(.disabled)+.form-label:hover:before,.form-el-radio:not([disabled])+.form-label:hover:before{border-color:#514943}.form-el-checkbox+.form-label,.form-el-radio+.form-label{font-weight:400;padding-left:2em;padding-right:0;position:relative;text-align:left;transition:border-color .1s linear}.form-el-checkbox+.form-label:before,.form-el-radio+.form-label:before{border:1px solid;content:'';left:0;position:absolute;top:.1rem;transition:border-color .1s linear}.form-el-checkbox+.form-label:before{border-color:#adadad;border-radius:2px;height:1.4rem;line-height:1;width:1.4rem}.form-el-checkbox:checked+.form-label::before{content:'\e600';font-family:Icons}.form-el-radio+.form-label:before{background-color:#fff;border:1px solid #adadad;border-radius:100%;height:1.6rem;width:1.6rem}.form-el-radio+.form-label:after{background:0 0;border:.5rem solid transparent;border-radius:100%;content:'';height:0;left:.4rem;position:absolute;top:.5rem;transition:background .3s linear;width:0}.form-el-radio:checked+.form-label{cursor:default}.form-el-radio:checked+.form-label:after{border-color:#514943}.form-select-label{border:1px solid #adadad;border-radius:2px;color:#303030;cursor:pointer;display:block;overflow:hidden;position:relative}.form-select-label:hover,.form-select-label:hover:after{border-color:#949494}.form-select-label:active,.form-select-label:active:after,.form-select-label:focus,.form-select-label:focus:after{border-color:#008bdb}.form-select-label:after{background:#e3e3e3;border-left:1px solid #adadad;bottom:0;content:'';position:absolute;right:0;top:0;width:2.36em;z-index:-2}.ie9 .form-select-label:after{display:none}.form-select-label:before{border-color:#303030 transparent transparent;border-style:solid;border-width:5px 4px 0;content:'';height:0;margin-right:-4px;margin-top:-2.5px;position:absolute;right:1.18em;top:50%;width:0;z-index:-1}.ie9 .form-select-label:before{display:none}.form-select-label .form-el-select{background:0 0;border:none;border-radius:0;content:'';display:block;margin:0;padding:.35em calc(2.36em + 10%) .5em .55em;width:110%}.ie9 .form-select-label .form-el-select{padding-right:.55em;width:100%}.form-el-select{background:#fff;border:1px solid #adadad;border-radius:2px;color:#303030;display:block;padding:.35em .55em}.multiselect-custom{position:relative;height:45.2rem;border:1px solid #adadad;overflow:auto;margin:0 0 1.5rem}.multiselect-custom ul{margin:0;padding:0;list-style:none;min-width:29rem}.multiselect-custom .item{padding:1rem 1.4rem}.multiselect-custom .selected{background-color:#e0f6fe}.multiselect-custom .form-label{margin-bottom:0}[class*=form-el-].invalid{border-color:#e22626}[class*=form-el-].invalid+.error-container{display:block}.error-container{background-color:#fff8d6;border:1px solid #ee7d7d;border-radius:2px;color:#514943;display:none;font-size:1.19rem;margin-top:.2rem;padding:.4235em .6655em .605em}.check-result-message{margin-left:.5em;min-height:3.68rem;-webkit-align-items:center;-ms-align-items:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.check-result-text{margin-left:.5em}.pseudo-table{display:table}.pseudo-td{display:table-cell}.alert{margin-bottom:3.5rem;padding:2.5rem;-webkit-align-items:center;-ms-align-items:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.alert .spinner{min-width:1em}.ie9 .alert .spinner{float:left}.alert p:last-child{margin-bottom:0}.alert-info{background-color:#fafafa;border:1px solid #ccc}.alert-warning{background-color:#fff8d6;border:1px solid #fff8d6}.alert-icon{margin-right:1.5rem}.ie9 .alert-icon{float:left}[class*=icon-].alert-icon{font-size:3.8rem;min-width:3.8rem}.alert-text{margin-bottom:0}.alert-text~.alert-text{margin-top:1em}.ie9 .alert-text{display:block;margin-left:5.3rem;margin-top:1rem}.container{display:block;margin:0 auto 4rem;max-width:100rem;padding:0 2rem}.row{margin-left:0;margin-right:0}.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9,.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{min-height:1px;padding-left:0;padding-right:0;position:relative}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}.nav{background-color:#f8f8f8;border-bottom:1px solid #e3e3e3;border-top:1px solid #e3e3e3;display:none;padding:2.2rem 1.5rem 0 0}.nav .btn-group,.nav-bar-outer-actions{float:right;margin-bottom:1.7rem}.nav .btn-group .btn-wrap,.nav-bar-outer-actions .btn-wrap{float:right;margin-left:.5rem;margin-right:.5rem}.nav-bar-outer-actions{margin-top:-10.6rem;padding-right:1.5rem}.btn-wrap-try-again{width:9.5rem}.btn-wrap-next,.btn-wrap-prev{width:8.5rem}.nav-bar{counter-reset:i;float:left;margin:0 1rem 1.7rem 0;padding:0;position:relative;white-space:nowrap}.nav-bar:before{background-color:#d4d4d4;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top,#d1d1d1 0,#d4d4d4 100%);background-image:linear-gradient(to bottom,#d1d1d1 0,#d4d4d4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d1d1d1', endColorstr='#d4d4d4', GradientType=0);border-bottom:1px solid #d9d9d9;border-top:1px solid #bfbfbf;content:'';height:.8rem;left:5.15rem;position:absolute;right:5.15rem;top:.7rem}.nav-bar>li{display:inline-block;font-size:0;position:relative;vertical-align:top;width:10.3rem}.nav-bar>li:first-child:after{display:none}.nav-bar>li:after{background-color:#514943;content:'';height:.5rem;left:calc(-50% + .25rem);position:absolute;right:calc(50% + .7rem);top:.9rem}.nav-bar>li.disabled:before{bottom:0;content:'';left:0;position:absolute;right:0;top:0;z-index:1}.nav-bar>li.active~li:after{display:none}.nav-bar>li.active~li a:after{background-color:transparent;border-color:transparent;color:#a6a6a6}.nav-bar>li.active a{color:#000}.nav-bar>li.active a:hover{cursor:default}.nav-bar>li.active a:after{background-color:#fff;content:''}.nav-bar a{color:#514943;display:block;font-size:1.2rem;font-weight:600;line-height:1.2;overflow:hidden;padding:3rem .5em 0;position:relative;text-align:center;text-overflow:ellipsis}.nav-bar a:hover{text-decoration:none}.nav-bar a:after{background-color:#514943;border:.4rem solid #514943;border-radius:100%;color:#fff;content:counter(i);counter-increment:i;height:.7rem;left:50%;line-height:.6;margin-left:-.8rem;position:absolute;right:auto;text-align:center;top:.4rem;width:.7rem}.nav-bar a:before{background-color:#d6d6d6;border:1px solid transparent;border-bottom-color:#d9d9d9;border-radius:100%;border-top-color:#bfbfbf;content:'';height:2.1rem;left:50%;line-height:1;margin-left:-1.2rem;position:absolute;top:0;width:2.1rem}.tooltip{display:block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.19rem;font-weight:400;line-height:1.4;opacity:0;position:absolute;visibility:visible;z-index:10}.tooltip.in{opacity:.9}.tooltip.top{margin-top:-4px;padding:8px 0}.tooltip.right{margin-left:4px;padding:0 8px}.tooltip.bottom{margin-top:4px;padding:8px 0}.tooltip.left{margin-left:-4px;padding:0 8px}.tooltip-inner{background-color:#fff;border:1px solid #adadad;border-radius:0;box-shadow:1px 1px 1px #ccc;color:#41362f;max-width:20rem;padding:.5em 1em;text-decoration:none}.tooltip-arrow,.tooltip-arrow:after{border:solid transparent;height:0;position:absolute;width:0}.tooltip-arrow:after{content:'';position:absolute}.tooltip.top .tooltip-arrow,.tooltip.top .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:50%;margin-left:-8px}.tooltip.top-left .tooltip-arrow,.tooltip.top-left .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;margin-bottom:-8px;right:8px}.tooltip.top-right .tooltip-arrow,.tooltip.top-right .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:8px;margin-bottom:-8px}.tooltip.right .tooltip-arrow,.tooltip.right .tooltip-arrow:after{border-right-color:#949494;border-width:8px 8px 8px 0;left:1px;margin-top:-8px;top:50%}.tooltip.right .tooltip-arrow:after{border-right-color:#fff;border-width:6px 7px 6px 0;margin-left:0;margin-top:-6px}.tooltip.left .tooltip-arrow,.tooltip.left .tooltip-arrow:after{border-left-color:#949494;border-width:8px 0 8px 8px;margin-top:-8px;right:0;top:50%}.tooltip.bottom .tooltip-arrow,.tooltip.bottom .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:50%;margin-left:-8px;top:0}.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;margin-top:-8px;right:8px;top:0}.tooltip.bottom-right .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:8px;margin-top:-8px;top:0}.password-strength{display:block;margin:0 -.3rem 1em;white-space:nowrap}.password-strength.password-strength-to-short .password-strength-item:first-child{background-color:#e22626}.password-strength.password-strength-weak .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child+.password-strength-item{background-color:#ef672f}.password-strength.password-strength-good .password-strength-item:first-child,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item,.password-strength.password-strength-strong .password-strength-item{background-color:#79a22e}.password-strength .password-strength-item{background-color:#ccc;display:inline-block;font-size:0;height:1.4rem;margin-right:.3rem;width:calc(25% - .6rem)}@-webkit-keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}.progress{background-color:#fafafa;border:1px solid #ccc;height:3rem;margin-bottom:3rem;overflow:hidden}.progress-bar{background-color:#79a22e;color:#fff;float:left;font-size:1.19rem;height:100%;line-height:3rem;text-align:center;transition:width .6s ease;width:0}.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.spinner{display:inline-block;font-size:4rem;height:1em;margin-right:1.5rem;position:relative;width:1em}@-moz-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@-webkit-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@-ms-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}.spinner>span:nth-child(1){-webkit-animation-delay:.27s;-moz-animation-delay:.27s;-ms-animation-delay:.27s;animation-delay:.27s;-webkit-transform:rotate(-315deg);-moz-transform:rotate(-315deg);-ms-transform:rotate(-315deg);transform:rotate(-315deg)}.spinner>span:nth-child(2){-webkit-animation-delay:.36s;-moz-animation-delay:.36s;-ms-animation-delay:.36s;animation-delay:.36s;-webkit-transform:rotate(-270deg);-moz-transform:rotate(-270deg);-ms-transform:rotate(-270deg);transform:rotate(-270deg)}.spinner>span:nth-child(3){-webkit-animation-delay:.45s;-moz-animation-delay:.45s;-ms-animation-delay:.45s;animation-delay:.45s;-webkit-transform:rotate(-225deg);-moz-transform:rotate(-225deg);-ms-transform:rotate(-225deg);transform:rotate(-225deg)}.spinner>span:nth-child(4){-webkit-animation-delay:.54s;-moz-animation-delay:.54s;-ms-animation-delay:.54s;animation-delay:.54s;-webkit-transform:rotate(-180deg);-moz-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.spinner>span:nth-child(5){-webkit-animation-delay:.63s;-moz-animation-delay:.63s;-ms-animation-delay:.63s;animation-delay:.63s;-webkit-transform:rotate(-135deg);-moz-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.spinner>span:nth-child(6){-webkit-animation-delay:.72s;-moz-animation-delay:.72s;-ms-animation-delay:.72s;animation-delay:.72s;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.spinner>span:nth-child(7){-webkit-animation-delay:.81s;-moz-animation-delay:.81s;-ms-animation-delay:.81s;animation-delay:.81s;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.spinner>span:nth-child(8){-webkit-animation-delay:.9;-moz-animation-delay:.9;-ms-animation-delay:.9;animation-delay:.9;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}.spinner>span{-webkit-animation-direction:linear;-moz-animation-direction:linear;-ms-animation-direction:linear;animation-direction:linear;-webkit-animation-duration:.72s;-moz-animation-duration:.72s;-ms-animation-duration:.72s;animation-duration:.72s;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fade;-moz-animation-name:fade;-ms-animation-name:fade;animation-name:fade;-webkit-transform:scale(0.4);-moz-transform:scale(0.4);-ms-transform:scale(0.4);transform:scale(0.4);background-color:#fff;border-radius:6px;clip:rect(0 .28571429em .1em 0);height:.1em;margin-top:.5em;position:absolute;width:1em}.ie9 .spinner{background:url(../../pub/images/ajax-loader.gif) center no-repeat}.ie9 .spinner>span{display:none}.main{padding-bottom:2rem;padding-top:3rem}.header{display:none}.header .logo{float:left;height:4.1rem;width:3.5rem}.header-title{font-size:2.8rem;letter-spacing:.02em;margin:2.5rem 0 3.5rem 5rem}.page-title{font-size:2rem;margin-bottom:1.3em}.accent-box{margin-bottom:2rem}.accent-box .btn-prime{margin-top:1.5rem}.page-landing{margin:7.6% auto 0;max-width:44rem;text-align:center}.page-landing .logo{height:5.6rem;margin-bottom:2rem;width:19.2rem}.page-landing .text-version{margin-bottom:3rem}.page-landing .text-welcome{margin-bottom:6.5rem}.page-landing .text-terms{margin-bottom:2.5rem;text-align:center}.page-landing .btn-submit{margin-bottom:20px}.page-license .license-text{margin-bottom:2rem}.page-license .page-license-footer{text-align:right}.rediness-check-item{margin-bottom:4rem}.readiness-check-title{font-size:1.4rem;font-weight:700;margin-bottom:.1rem;margin-left:7.5rem}.readiness-check-content{margin-left:7.5rem;margin-right:22rem}.readiness-check-content .readiness-check-title{margin-left:0}.readiness-check-content .list{margin-top:-.3rem}.rediness-check-side{float:right;padding-left:2.4rem;width:22rem}.rediness-check-side .side-title{margin-bottom:0}.readiness-check-icon{float:left;margin-left:2rem;margin-top:.7rem}.page-web-configuration .form-el-insider-wrap{width:auto}.page-web-configuration .form-el-insider{width:15.4rem}.page-web-configuration .form-el-insider-input .form-el-input{width:16.5rem}.customize-your-store .customize-your-store-default .legend{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.customize-your-store .advanced-modules-count,.customize-your-store .advanced-modules-select{padding-left:1.5rem}.customize-your-store .customize-your-store-advanced{min-width:0}.content-install{margin-bottom:2rem}.console{border:1px solid #ccc;font-family:'Courier New',Courier,monospace;font-weight:300;margin:1rem 0 2rem;max-height:20rem;overflow-y:auto;padding:1.5rem 2rem 2rem}.console .text-danger{color:#e22626}.console .text-success{color:#090}.console .hidden{display:none}.content-success .btn-prime{margin-top:1.5rem}.jumbo-title{font-size:3.6rem}.jumbo-title .jumbo-icon{font-size:3.8rem;margin-right:.25em;position:relative;top:.15em}@media all and (max-width:1047px){.nav{padding-bottom:5.38rem;padding-left:1.5rem;text-align:center}.nav-bar{display:inline-block;float:none;margin-right:0;vertical-align:top}.nav .btn-group,.nav-bar-outer-actions{display:inline-block;float:none;margin-top:-8.48rem;text-align:center;vertical-align:top;width:100%}.nav-bar-outer-actions{padding-right:0}.nav-bar-outer-actions .outer-actions-inner-wrap{display:inline-block}}@media all and (min-width:768px){html{margin-left:calc(100vw - 100%);margin-right:0;overflow:auto}.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9{float:left}.col-m-12{width:100%}.col-m-11{width:91.66666667%}.col-m-10{width:83.33333333%}.col-m-9{width:75%}.col-m-8{width:66.66666667%}.col-m-7{width:58.33333333%}.col-m-6{width:50%}.col-m-5{width:41.66666667%}.col-m-4{width:33.33333333%}.col-m-3{width:25%}.col-m-2{width:16.66666667%}.col-m-1{width:8.33333333%}.col-m-pull-12{right:100%}.col-m-pull-11{right:91.66666667%}.col-m-pull-10{right:83.33333333%}.col-m-pull-9{right:75%}.col-m-pull-8{right:66.66666667%}.col-m-pull-7{right:58.33333333%}.col-m-pull-6{right:50%}.col-m-pull-5{right:41.66666667%}.col-m-pull-4{right:33.33333333%}.col-m-pull-3{right:25%}.col-m-pull-2{right:16.66666667%}.col-m-pull-1{right:8.33333333%}.col-m-pull-0{right:auto}.col-m-push-12{left:100%}.col-m-push-11{left:91.66666667%}.col-m-push-10{left:83.33333333%}.col-m-push-9{left:75%}.col-m-push-8{left:66.66666667%}.col-m-push-7{left:58.33333333%}.col-m-push-6{left:50%}.col-m-push-5{left:41.66666667%}.col-m-push-4{left:33.33333333%}.col-m-push-3{left:25%}.col-m-push-2{left:16.66666667%}.col-m-push-1{left:8.33333333%}.col-m-push-0{left:auto}.col-m-offset-12{margin-left:100%}.col-m-offset-11{margin-left:91.66666667%}.col-m-offset-10{margin-left:83.33333333%}.col-m-offset-9{margin-left:75%}.col-m-offset-8{margin-left:66.66666667%}.col-m-offset-7{margin-left:58.33333333%}.col-m-offset-6{margin-left:50%}.col-m-offset-5{margin-left:41.66666667%}.col-m-offset-4{margin-left:33.33333333%}.col-m-offset-3{margin-left:25%}.col-m-offset-2{margin-left:16.66666667%}.col-m-offset-1{margin-left:8.33333333%}.col-m-offset-0{margin-left:0}}@media all and (min-width:1048px){.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9{float:left}.col-l-12{width:100%}.col-l-11{width:91.66666667%}.col-l-10{width:83.33333333%}.col-l-9{width:75%}.col-l-8{width:66.66666667%}.col-l-7{width:58.33333333%}.col-l-6{width:50%}.col-l-5{width:41.66666667%}.col-l-4{width:33.33333333%}.col-l-3{width:25%}.col-l-2{width:16.66666667%}.col-l-1{width:8.33333333%}.col-l-pull-12{right:100%}.col-l-pull-11{right:91.66666667%}.col-l-pull-10{right:83.33333333%}.col-l-pull-9{right:75%}.col-l-pull-8{right:66.66666667%}.col-l-pull-7{right:58.33333333%}.col-l-pull-6{right:50%}.col-l-pull-5{right:41.66666667%}.col-l-pull-4{right:33.33333333%}.col-l-pull-3{right:25%}.col-l-pull-2{right:16.66666667%}.col-l-pull-1{right:8.33333333%}.col-l-pull-0{right:auto}.col-l-push-12{left:100%}.col-l-push-11{left:91.66666667%}.col-l-push-10{left:83.33333333%}.col-l-push-9{left:75%}.col-l-push-8{left:66.66666667%}.col-l-push-7{left:58.33333333%}.col-l-push-6{left:50%}.col-l-push-5{left:41.66666667%}.col-l-push-4{left:33.33333333%}.col-l-push-3{left:25%}.col-l-push-2{left:16.66666667%}.col-l-push-1{left:8.33333333%}.col-l-push-0{left:auto}.col-l-offset-12{margin-left:100%}.col-l-offset-11{margin-left:91.66666667%}.col-l-offset-10{margin-left:83.33333333%}.col-l-offset-9{margin-left:75%}.col-l-offset-8{margin-left:66.66666667%}.col-l-offset-7{margin-left:58.33333333%}.col-l-offset-6{margin-left:50%}.col-l-offset-5{margin-left:41.66666667%}.col-l-offset-4{margin-left:33.33333333%}.col-l-offset-3{margin-left:25%}.col-l-offset-2{margin-left:16.66666667%}.col-l-offset-1{margin-left:8.33333333%}.col-l-offset-0{margin-left:0}}@media all and (min-width:1440px){.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{float:left}.col-xl-12{width:100%}.col-xl-11{width:91.66666667%}.col-xl-10{width:83.33333333%}.col-xl-9{width:75%}.col-xl-8{width:66.66666667%}.col-xl-7{width:58.33333333%}.col-xl-6{width:50%}.col-xl-5{width:41.66666667%}.col-xl-4{width:33.33333333%}.col-xl-3{width:25%}.col-xl-2{width:16.66666667%}.col-xl-1{width:8.33333333%}.col-xl-pull-12{right:100%}.col-xl-pull-11{right:91.66666667%}.col-xl-pull-10{right:83.33333333%}.col-xl-pull-9{right:75%}.col-xl-pull-8{right:66.66666667%}.col-xl-pull-7{right:58.33333333%}.col-xl-pull-6{right:50%}.col-xl-pull-5{right:41.66666667%}.col-xl-pull-4{right:33.33333333%}.col-xl-pull-3{right:25%}.col-xl-pull-2{right:16.66666667%}.col-xl-pull-1{right:8.33333333%}.col-xl-pull-0{right:auto}.col-xl-push-12{left:100%}.col-xl-push-11{left:91.66666667%}.col-xl-push-10{left:83.33333333%}.col-xl-push-9{left:75%}.col-xl-push-8{left:66.66666667%}.col-xl-push-7{left:58.33333333%}.col-xl-push-6{left:50%}.col-xl-push-5{left:41.66666667%}.col-xl-push-4{left:33.33333333%}.col-xl-push-3{left:25%}.col-xl-push-2{left:16.66666667%}.col-xl-push-1{left:8.33333333%}.col-xl-push-0{left:auto}.col-xl-offset-12{margin-left:100%}.col-xl-offset-11{margin-left:91.66666667%}.col-xl-offset-10{margin-left:83.33333333%}.col-xl-offset-9{margin-left:75%}.col-xl-offset-8{margin-left:66.66666667%}.col-xl-offset-7{margin-left:58.33333333%}.col-xl-offset-6{margin-left:50%}.col-xl-offset-5{margin-left:41.66666667%}.col-xl-offset-4{margin-left:33.33333333%}.col-xl-offset-3{margin-left:25%}.col-xl-offset-2{margin-left:16.66666667%}.col-xl-offset-1{margin-left:8.33333333%}.col-xl-offset-0{margin-left:0}}@media all and (max-width:767px){.list-definition>dt{float:none}.list-definition>dd{margin-left:0}.form-row .form-label{text-align:left}.form-row .form-label.required:after{position:static}.nav{padding-bottom:0;padding-left:0;padding-right:0}.nav-bar-outer-actions{margin-top:0}.nav-bar{display:block;margin-bottom:0;margin-left:auto;margin-right:auto;width:30.9rem}.nav-bar:before{display:none}.nav-bar>li{float:left;min-height:9rem}.nav-bar>li:after{display:none}.nav-bar>li:nth-child(4n){clear:both}.nav-bar a{line-height:1.4}.tooltip{display:none!important}.readiness-check-content{margin-right:2rem}.form-el-insider,.form-el-insider-wrap,.page-web-configuration .form-el-insider-input,.page-web-configuration .form-el-insider-input .form-el-input{display:block;width:100%}}@media all and (max-width:479px){.nav-bar{width:23.175rem}.nav-bar>li{width:7.725rem}.nav .btn-group .btn-wrap-try-again,.nav-bar-outer-actions .btn-wrap-try-again{clear:both;display:block;float:none;margin-left:auto;margin-right:auto;margin-top:1rem;padding-top:1rem}} \ No newline at end of file +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{box-sizing:border-box}:focus{box-shadow:none;outline:0}.keyfocus :focus{box-shadow:0 0 0 1px #008bdb}embed,img,object,video{max-width:100%}.abs-clearer:after,.form-row:after,.header:after,.ie9 .alert:after,.nav:after,.row:after{content:"";display:table;clear:both}.ng-cloak{display:none!important}.hide.hide{display:none}.show.show{display:block}.text-center{text-align:center}.text-right{text-align:right}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/light/opensans-300.eot);src:url(../../pub/fonts/opensans/light/opensans-300.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/light/opensans-300.woff2) format('woff2'),url(../../pub/fonts/opensans/light/opensans-300.woff) format('woff'),url(../../pub/fonts/opensans/light/opensans-300.ttf) format('truetype'),url('../../pub/fonts/opensans/light/opensans-300.svg#Open Sans') format('svg');font-weight:300;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/regular/opensans-400.eot);src:url(../../pub/fonts/opensans/regular/opensans-400.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/regular/opensans-400.woff2) format('woff2'),url(../../pub/fonts/opensans/regular/opensans-400.woff) format('woff'),url(../../pub/fonts/opensans/regular/opensans-400.ttf) format('truetype'),url('../../pub/fonts/opensans/regular/opensans-400.svg#Open Sans') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/semibold/opensans-600.eot);src:url(../../pub/fonts/opensans/semibold/opensans-600.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/semibold/opensans-600.woff2) format('woff2'),url(../../pub/fonts/opensans/semibold/opensans-600.woff) format('woff'),url(../../pub/fonts/opensans/semibold/opensans-600.ttf) format('truetype'),url('../../pub/fonts/opensans/semibold/opensans-600.svg#Open Sans') format('svg');font-weight:600;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/bold/opensans-700.eot);src:url(../../pub/fonts/opensans/bold/opensans-700.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/bold/opensans-700.woff2) format('woff2'),url(../../pub/fonts/opensans/bold/opensans-700.woff) format('woff'),url(../../pub/fonts/opensans/bold/opensans-700.ttf) format('truetype'),url('../../pub/fonts/opensans/bold/opensans-700.svg#Open Sans') format('svg');font-weight:700;font-style:normal}html{font-size:62.5%}body{color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:400;line-height:1.4}h1,h2,h3,h4,h5,h6{font-weight:400;margin-top:0}p{margin:0 0 1em}a{color:#008bdb;text-decoration:none}a:hover{color:#0fa7ff;text-decoration:underline}@font-face{font-family:Icons;src:url(../../pub/fonts/icons/icons.eot);src:url(../../pub/fonts/icons/icons.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/icons/icons.woff2) format('woff2'),url(../../pub/fonts/icons/icons.woff) format('woff'),url(../../pub/fonts/icons/icons.ttf) format('truetype'),url(../../pub/fonts/icons/icons.svg#Icons) format('svg');font-weight:400;font-style:normal}[class*=icon-]{display:inline-block;line-height:1}[class*=icon-]:after{font-family:Icons}.icon-success-thick:after{content:'\e600'}.icon-success:after{content:'\e601'}.icon-collapse:after{content:'\e602'}.icon-failed-thick:after{content:'\e603'}.icon-failed:after{content:'\e604'}.icon-expand:after{content:'\e605'}.icon-warning:after{content:'\e606'}.icon-failed-round,.icon-success-round{border-radius:100%;color:#fff;font-size:2.5rem;height:1em;position:relative;text-align:center;width:1em}.icon-failed-round:after,.icon-success-round:after{bottom:0;font-size:.8em;left:0;position:absolute;right:0;top:.15em}.icon-success-round{background-color:#79a22e}.icon-success-round:after{content:'\e600'}.icon-failed-round{background-color:#e22626}.icon-failed-round:after{content:'\e603'}dl,ol,ul{margin-top:0}.list{margin-bottom:1em;padding-left:0}.list>li{display:block;margin-bottom:.75em;position:relative}.list>li>.icon-failed,.list>li>.icon-success{font-size:1.6em;left:-.1em;position:absolute;top:0}.list>li>.icon-success{color:#79a22e}.list>li>.icon-failed{color:#e22626}.list-item-failed,.list-item-icon,.list-item-success{padding-left:3.5rem}.list-item-failed:before,.list-item-success:before{font-family:Icons;font-size:1.6em;left:-.1em;position:absolute;top:-.2em}.list-item-success:before{color:#79a22e;content:'\e601'}.list-item-failed:before{color:#e22626;content:'\e604'}.list-definition{margin:0 0 3rem;padding:0}.list-definition>dt{clear:left;float:left}.list-definition>dd{margin-bottom:1em;margin-left:20rem}.btn-wrap{margin:0 auto}.btn-wrap .btn{width:100%}.btn{background:#e3e3e3;border:none;color:#514943;display:inline-block;font-size:1.6rem;font-weight:600;padding:.45em .5em;text-align:center}.btn:hover{background-color:#dbdbdb;color:#514943;text-decoration:none}.btn:active{background-color:#d6d6d6}.btn.disabled,.btn[disabled]{cursor:default;opacity:.5;pointer-events:none}.ie9 .btn.disabled,.ie9 .btn[disabled]{background-color:#f0f0f0;opacity:1;text-shadow:none}.btn-large{padding:.75em 1.25em}.btn-link{background-color:transparent;border:none;color:#008bdb;font-family:1.6rem;font-size:1.5rem}.btn-link:hover{background-color:transparent;color:#0fa7ff}.btn-prime{background-color:#eb5202;color:#fff;text-shadow:1px 1px 0 rgba(0,0,0,.25)}.btn-prime:hover{background-color:#f65405;background-repeat:repeat-x;background-image:linear-gradient(to right,#e04f00 0,#f65405 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e04f00', endColorstr='#f65405', GradientType=1);color:#fff}.btn-prime:active{background-color:#e04f00;background-repeat:repeat-x;background-image:linear-gradient(to right,#f65405 0,#e04f00 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f65405', endColorstr='#e04f00', GradientType=1)}.ie9 .btn-prime.disabled,.ie9 .btn-prime[disabled]{background-color:#fd6e23}.ie9 .btn-prime.disabled:active,.ie9 .btn-prime.disabled:hover,.ie9 .btn-prime[disabled]:active,.ie9 .btn-prime[disabled]:hover{background-color:#fd6e23;-webkit-filter:none;filter:none}.btn-secondary{background-color:#514943;color:#fff}.btn-secondary:hover{background-color:#5f564f;color:#fff}.btn-secondary:active{background-color:#574e48}.ie9 .btn-secondary.disabled,.ie9 .btn-secondary[disabled]{background-color:#514943}.ie9 .btn-secondary.disabled:active,.ie9 .btn-secondary.disabled:hover,.ie9 .btn-secondary[disabled]:active,.ie9 .btn-secondary[disabled]:hover{background-color:#514943;-webkit-filter:none;filter:none}[class*=btn-wrap-triangle]{overflow:hidden;position:relative}[class*=btn-wrap-triangle] .btn:after{border-style:solid;content:'';height:0;position:absolute;top:0;width:0}.btn-wrap-triangle-right{display:inline-block;padding-right:1.74rem;position:relative}.btn-wrap-triangle-right .btn{text-indent:.92rem}.btn-wrap-triangle-right .btn:after{border-color:transparent transparent transparent #e3e3e3;border-width:1.84rem 0 1.84rem 1.84rem;left:100%;margin-left:-1.74rem}.btn-wrap-triangle-right .btn:hover:after{border-left-color:#dbdbdb}.btn-wrap-triangle-right .btn:active:after{border-left-color:#d6d6d6}.btn-wrap-triangle-right .btn:not(.disabled):active,.btn-wrap-triangle-right .btn:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn.disabled:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:after{border-color:transparent transparent transparent #f0f0f0}.ie9 .btn-wrap-triangle-right .btn.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:hover:after{border-left-color:#f0f0f0}.btn-wrap-triangle-right .btn-prime:after{border-color:transparent transparent transparent #eb5202}.btn-wrap-triangle-right .btn-prime:hover:after{border-left-color:#f65405}.btn-wrap-triangle-right .btn-prime:active:after{border-left-color:#e04f00}.btn-wrap-triangle-right .btn-prime:not(.disabled):active,.btn-wrap-triangle-right .btn-prime:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:after{border-color:transparent transparent transparent #fd6e23}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:hover:after{border-left-color:#fd6e23}.btn-wrap-triangle-left{display:inline-block;padding-left:1.74rem}.btn-wrap-triangle-left .btn{text-indent:-.92rem}.btn-wrap-triangle-left .btn:after{border-color:transparent #e3e3e3 transparent transparent;border-width:1.84rem 1.84rem 1.84rem 0;margin-right:-1.74rem;right:100%}.btn-wrap-triangle-left .btn:hover:after{border-right-color:#dbdbdb}.btn-wrap-triangle-left .btn:active:after{border-right-color:#d6d6d6}.btn-wrap-triangle-left .btn:not(.disabled):active,.btn-wrap-triangle-left .btn:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn.disabled:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:after{border-color:transparent #f0f0f0 transparent transparent}.ie9 .btn-wrap-triangle-left .btn.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:hover:after{border-right-color:#f0f0f0}.btn-wrap-triangle-left .btn-prime:after{border-color:transparent #eb5202 transparent transparent}.btn-wrap-triangle-left .btn-prime:hover:after{border-right-color:#e04f00}.btn-wrap-triangle-left .btn-prime:active:after{border-right-color:#f65405}.btn-wrap-triangle-left .btn-prime:not(.disabled):active,.btn-wrap-triangle-left .btn-prime:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:after{border-color:transparent #fd6e23 transparent transparent}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:hover:after{border-right-color:#fd6e23}.btn-expand{background-color:transparent;border:none;color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;padding:0;position:relative}.btn-expand.expanded:after{border-color:transparent transparent #303030;border-width:0 .285em .36em}.btn-expand.expanded:hover:after{border-color:transparent transparent #3d3d3d}.btn-expand:hover{background-color:transparent;border:none;color:#3d3d3d}.btn-expand:hover:after{border-color:#3d3d3d transparent transparent}.btn-expand:after{border-color:#303030 transparent transparent;border-style:solid;border-width:.36em .285em 0;content:'';height:0;left:100%;margin-left:.5em;margin-top:-.18em;position:absolute;top:50%;width:0}[class*=col-] .form-el-input,[class*=col-] .form-el-select{width:100%}.form-fieldset{border:none;margin:0 0 1em;padding:0}.form-row{margin-bottom:2.2rem}.form-row .form-row{margin-bottom:.4rem}.form-row .form-label{display:block;font-weight:600;padding:.6rem 2.1em 0 0;text-align:right}.form-row .form-label.required{position:relative}.form-row .form-label.required:after{color:#eb5202;content:'*';font-size:1.15em;position:absolute;right:.7em;top:.5em}.form-row .form-el-checkbox+.form-label:before,.form-row .form-el-radio+.form-label:before{top:.7rem}.form-row .form-el-checkbox+.form-label:after,.form-row .form-el-radio+.form-label:after{top:1.1rem}input:not([disabled]):focus,textarea:not([disabled]):focus{box-shadow:none}.form-el-input{border:1px solid #adadad;border-radius:2px;color:#303030;padding:.35em .55em .5em}.form-el-input:hover{border-color:#949494}.form-el-input:focus{border-color:#008bdb}.form-label{margin-bottom:.5em}[class*=form-label][for]{cursor:pointer}.form-el-insider-wrap{display:table;width:100%}.form-el-insider-input{display:table-cell;width:100%}.form-el-insider{border-radius:2px;display:table-cell;vertical-align:top;padding:.43em .55em .5em 0}.form-legend,.form-legend-expand,.form-legend-light{display:block;margin:0}.form-legend,.form-legend-expand{margin-bottom:2.5em;padding-top:1.5em;font-weight:600;font-size:1.25em}.form-legend{width:100%;border-top:1px solid #ccc}.form-legend-light{margin-bottom:1.5em;font-size:1em}.form-legend-expand{transition:opacity .2s linear;cursor:pointer}.form-legend-expand:hover{opacity:.85}.form-legend-expand.expanded:after{content:'\e602'}.form-legend-expand:after{margin-left:.5em;font-weight:400;font-size:1.15em;font-family:Icons;content:'\e605';vertical-align:sub}.form-el-checkbox,.form-el-radio{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.form-el-checkbox.disabled+.form-label,.form-el-checkbox.disabled+.form-label:before,.form-el-checkbox[disabled]+.form-label,.form-el-checkbox[disabled]+.form-label:before,.form-el-radio.disabled+.form-label,.form-el-radio.disabled+.form-label:before,.form-el-radio[disabled]+.form-label,.form-el-radio[disabled]+.form-label:before{cursor:default;opacity:.5;pointer-events:none}.form-el-checkbox:not(.disabled)+.form-label:hover:before,.form-el-checkbox:not([disabled])+.form-label:hover:before,.form-el-radio:not(.disabled)+.form-label:hover:before,.form-el-radio:not([disabled])+.form-label:hover:before{border-color:#514943}.form-el-checkbox+.form-label,.form-el-radio+.form-label{font-weight:400;padding-left:2em;padding-right:0;position:relative;text-align:left;transition:border-color .1s linear}.form-el-checkbox+.form-label:before,.form-el-radio+.form-label:before{border:1px solid;content:'';left:0;position:absolute;top:.1rem;transition:border-color .1s linear}.form-el-checkbox+.form-label:before{border-color:#adadad;border-radius:2px;height:1.4rem;line-height:1;width:1.4rem}.form-el-checkbox:checked+.form-label::before{content:'\e600';font-family:Icons}.form-el-radio+.form-label:before{background-color:#fff;border:1px solid #adadad;border-radius:100%;height:1.6rem;width:1.6rem}.form-el-radio+.form-label:after{background:0 0;border:.5rem solid transparent;border-radius:100%;content:'';height:0;left:.4rem;position:absolute;top:.5rem;transition:background .3s linear;width:0}.form-el-radio:checked+.form-label{cursor:default}.form-el-radio:checked+.form-label:after{border-color:#514943}.form-select-label{border:1px solid #adadad;border-radius:2px;color:#303030;cursor:pointer;display:block;overflow:hidden;position:relative}.form-select-label:hover,.form-select-label:hover:after{border-color:#949494}.form-select-label:active,.form-select-label:active:after,.form-select-label:focus,.form-select-label:focus:after{border-color:#008bdb}.form-select-label:after{background:#e3e3e3;border-left:1px solid #adadad;bottom:0;content:'';position:absolute;right:0;top:0;width:2.36em;z-index:-2}.ie9 .form-select-label:after{display:none}.form-select-label:before{border-color:#303030 transparent transparent;border-style:solid;border-width:5px 4px 0;content:'';height:0;margin-right:-4px;margin-top:-2.5px;position:absolute;right:1.18em;top:50%;width:0;z-index:-1}.ie9 .form-select-label:before{display:none}.form-select-label .form-el-select{background:0 0;border:none;border-radius:0;content:'';display:block;margin:0;padding:.35em calc(2.36em + 10%) .5em .55em;width:110%}.ie9 .form-select-label .form-el-select{padding-right:.55em;width:100%}.form-el-select{background:#fff;border:1px solid #adadad;border-radius:2px;color:#303030;display:block;padding:.35em .55em}.multiselect-custom{position:relative;height:45.2rem;border:1px solid #adadad;overflow:auto;margin:0 0 1.5rem}.multiselect-custom ul{margin:0;padding:0;list-style:none;min-width:29rem}.multiselect-custom .item{padding:1rem 1.4rem}.multiselect-custom .selected{background-color:#e0f6fe}.multiselect-custom .form-label{margin-bottom:0}[class*=form-el-].invalid{border-color:#e22626}[class*=form-el-].invalid+.error-container{display:block}.error-container{background-color:#fff8d6;border:1px solid #ee7d7d;border-radius:2px;color:#514943;display:none;font-size:1.19rem;margin-top:.2rem;padding:.4235em .6655em .605em}.check-result-message{margin-left:.5em;min-height:3.68rem;-webkit-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.check-result-text{margin-left:.5em}.pseudo-table{display:table}.pseudo-td{display:table-cell}.alert{margin-bottom:3.5rem;padding:2.5rem;-webkit-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.alert .spinner{min-width:1em}.ie9 .alert .spinner{float:left}.alert p:last-child{margin-bottom:0}.alert-info{background-color:#fafafa;border:1px solid #ccc}.alert-warning{background-color:#fff8d6;border:1px solid #fff8d6}.alert-icon{margin-right:1.5rem}.ie9 .alert-icon{float:left}[class*=icon-].alert-icon{font-size:3.8rem;min-width:3.8rem}.alert-text{margin-bottom:0}.alert-text~.alert-text{margin-top:1em}.ie9 .alert-text{display:block;margin-left:5.3rem;margin-top:1rem}.container{display:block;margin:0 auto 4rem;max-width:100rem;padding:0 2rem}.row{margin-left:0;margin-right:0}.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9,.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{min-height:1px;padding-left:0;padding-right:0;position:relative}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}.nav{background-color:#f8f8f8;border-bottom:1px solid #e3e3e3;border-top:1px solid #e3e3e3;display:none;padding:2.2rem 1.5rem 0 0}.nav .btn-group,.nav-bar-outer-actions{float:right;margin-bottom:1.7rem}.nav .btn-group .btn-wrap,.nav-bar-outer-actions .btn-wrap{float:right;margin-left:.5rem;margin-right:.5rem}.nav-bar-outer-actions{margin-top:-10.6rem;padding-right:1.5rem}.btn-wrap-try-again{width:9.5rem}.btn-wrap-next,.btn-wrap-prev{width:8.5rem}.nav-bar{counter-reset:i;float:left;margin:0 1rem 1.7rem 0;padding:0;position:relative;white-space:nowrap}.nav-bar:before{background-color:#d4d4d4;background-repeat:repeat-x;background-image:linear-gradient(to bottom,#d1d1d1 0,#d4d4d4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d1d1d1', endColorstr='#d4d4d4', GradientType=0);border-bottom:1px solid #d9d9d9;border-top:1px solid #bfbfbf;content:'';height:.8rem;left:5.15rem;position:absolute;right:5.15rem;top:.7rem}.nav-bar>li{display:inline-block;font-size:0;position:relative;vertical-align:top;width:10.3rem}.nav-bar>li:first-child:after{display:none}.nav-bar>li:after{background-color:#514943;content:'';height:.5rem;left:calc(-50% + .25rem);position:absolute;right:calc(50% + .7rem);top:.9rem}.nav-bar>li.disabled:before{bottom:0;content:'';left:0;position:absolute;right:0;top:0;z-index:1}.nav-bar>li.active~li:after{display:none}.nav-bar>li.active~li a:after{background-color:transparent;border-color:transparent;color:#a6a6a6}.nav-bar>li.active a{color:#000}.nav-bar>li.active a:hover{cursor:default}.nav-bar>li.active a:after{background-color:#fff;content:''}.nav-bar a{color:#514943;display:block;font-size:1.2rem;font-weight:600;line-height:1.2;overflow:hidden;padding:3rem .5em 0;position:relative;text-align:center;text-overflow:ellipsis}.nav-bar a:hover{text-decoration:none}.nav-bar a:after{background-color:#514943;border:.4rem solid #514943;border-radius:100%;color:#fff;content:counter(i);counter-increment:i;height:.7rem;left:50%;line-height:.6;margin-left:-.8rem;position:absolute;right:auto;text-align:center;top:.4rem;width:.7rem}.nav-bar a:before{background-color:#d6d6d6;border:1px solid transparent;border-bottom-color:#d9d9d9;border-radius:100%;border-top-color:#bfbfbf;content:'';height:2.1rem;left:50%;line-height:1;margin-left:-1.2rem;position:absolute;top:0;width:2.1rem}.tooltip{display:block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.19rem;font-weight:400;line-height:1.4;opacity:0;position:absolute;visibility:visible;z-index:10}.tooltip.in{opacity:.9}.tooltip.top{margin-top:-4px;padding:8px 0}.tooltip.right{margin-left:4px;padding:0 8px}.tooltip.bottom{margin-top:4px;padding:8px 0}.tooltip.left{margin-left:-4px;padding:0 8px}.tooltip-inner{background-color:#fff;border:1px solid #adadad;border-radius:0;box-shadow:1px 1px 1px #ccc;color:#41362f;max-width:20rem;padding:.5em 1em;text-decoration:none}.tooltip-arrow,.tooltip-arrow:after{border:solid transparent;height:0;position:absolute;width:0}.tooltip-arrow:after{content:'';position:absolute}.tooltip.top .tooltip-arrow,.tooltip.top .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:50%;margin-left:-8px}.tooltip.top-left .tooltip-arrow,.tooltip.top-left .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;margin-bottom:-8px;right:8px}.tooltip.top-right .tooltip-arrow,.tooltip.top-right .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:8px;margin-bottom:-8px}.tooltip.right .tooltip-arrow,.tooltip.right .tooltip-arrow:after{border-right-color:#949494;border-width:8px 8px 8px 0;left:1px;margin-top:-8px;top:50%}.tooltip.right .tooltip-arrow:after{border-right-color:#fff;border-width:6px 7px 6px 0;margin-left:0;margin-top:-6px}.tooltip.left .tooltip-arrow,.tooltip.left .tooltip-arrow:after{border-left-color:#949494;border-width:8px 0 8px 8px;margin-top:-8px;right:0;top:50%}.tooltip.bottom .tooltip-arrow,.tooltip.bottom .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:50%;margin-left:-8px;top:0}.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;margin-top:-8px;right:8px;top:0}.tooltip.bottom-right .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:8px;margin-top:-8px;top:0}.password-strength{display:block;margin:0 -.3rem 1em;white-space:nowrap}.password-strength.password-strength-too-short .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child+.password-strength-item{background-color:#e22626}.password-strength.password-strength-fair .password-strength-item:first-child,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item+.password-strength-item{background-color:#ef672f}.password-strength.password-strength-good .password-strength-item:first-child,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item+.password-strength-item,.password-strength.password-strength-strong .password-strength-item{background-color:#79a22e}.password-strength .password-strength-item{background-color:#ccc;display:inline-block;font-size:0;height:1.4rem;margin-right:.3rem;width:calc(20% - .6rem)}@-webkit-keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}.progress{background-color:#fafafa;border:1px solid #ccc;height:3rem;margin-bottom:3rem;overflow:hidden}.progress-bar{background-color:#79a22e;color:#fff;float:left;font-size:1.19rem;height:100%;line-height:3rem;text-align:center;transition:width .6s ease;width:0}.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.spinner{display:inline-block;font-size:4rem;height:1em;margin-right:1.5rem;position:relative;width:1em}@-webkit-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}.spinner>span:nth-child(1){-webkit-animation-delay:.27s;animation-delay:.27s;-webkit-transform:rotate(-315deg);-ms-transform:rotate(-315deg);transform:rotate(-315deg)}.spinner>span:nth-child(2){-webkit-animation-delay:.36s;animation-delay:.36s;-webkit-transform:rotate(-270deg);-ms-transform:rotate(-270deg);transform:rotate(-270deg)}.spinner>span:nth-child(3){-webkit-animation-delay:.45s;animation-delay:.45s;-webkit-transform:rotate(-225deg);-ms-transform:rotate(-225deg);transform:rotate(-225deg)}.spinner>span:nth-child(4){-webkit-animation-delay:.54s;animation-delay:.54s;-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.spinner>span:nth-child(5){-webkit-animation-delay:.63s;animation-delay:.63s;-webkit-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.spinner>span:nth-child(6){-webkit-animation-delay:.72s;animation-delay:.72s;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.spinner>span:nth-child(7){-webkit-animation-delay:.81s;animation-delay:.81s;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.spinner>span:nth-child(8){-webkit-animation-delay:.9;animation-delay:.9;-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}.spinner>span{-webkit-animation-direction:linear;animation-direction:linear;-webkit-animation-duration:.72s;animation-duration:.72s;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fade;animation-name:fade;-webkit-transform:scale(0.4);-ms-transform:scale(0.4);transform:scale(0.4);background-color:#fff;border-radius:6px;clip:rect(0 .28571429em .1em 0);height:.1em;margin-top:.5em;position:absolute;width:1em}.ie9 .spinner{background:url(../../pub/images/ajax-loader.gif) center no-repeat}.ie9 .spinner>span{display:none}.main{padding-bottom:2rem;padding-top:3rem}.header{display:none}.header .logo{float:left;height:4.1rem;width:3.5rem}.header-title{font-size:2.8rem;letter-spacing:.02em;margin:2.5rem 0 3.5rem 5rem}.page-title{font-size:2rem;margin-bottom:1.3em}.accent-box{margin-bottom:2rem}.accent-box .btn-prime{margin-top:1.5rem}.page-landing{margin:7.6% auto 0;max-width:44rem;text-align:center}.page-landing .logo{height:5.6rem;margin-bottom:2rem;width:19.2rem}.page-landing .text-version{margin-bottom:3rem}.page-landing .text-welcome{margin-bottom:6.5rem}.page-landing .text-terms{margin-bottom:2.5rem;text-align:center}.page-landing .btn-submit{margin-bottom:20px}.page-license .license-text{margin-bottom:2rem}.page-license .page-license-footer{text-align:right}.rediness-check-item{margin-bottom:4rem}.readiness-check-title{font-size:1.4rem;font-weight:700;margin-bottom:.1rem;margin-left:7.5rem}.readiness-check-content{margin-left:7.5rem;margin-right:22rem}.readiness-check-content .readiness-check-title{margin-left:0}.readiness-check-content .list{margin-top:-.3rem}.rediness-check-side{float:right;padding-left:2.4rem;width:22rem}.rediness-check-side .side-title{margin-bottom:0}.readiness-check-icon{float:left;margin-left:2rem;margin-top:.7rem}.page-web-configuration .form-el-insider-wrap{width:auto}.page-web-configuration .form-el-insider{width:15.4rem}.page-web-configuration .form-el-insider-input .form-el-input{width:16.5rem}.customize-your-store .customize-your-store-default .legend{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.customize-your-store .advanced-modules-count,.customize-your-store .advanced-modules-select{padding-left:1.5rem}.customize-your-store .customize-your-store-advanced{min-width:0}.content-install{margin-bottom:2rem}.console{border:1px solid #ccc;font-family:'Courier New',Courier,monospace;font-weight:300;margin:1rem 0 2rem;max-height:20rem;overflow-y:auto;padding:1.5rem 2rem 2rem}.console .text-danger{color:#e22626}.console .text-success{color:#090}.console .hidden{display:none}.content-success .btn-prime{margin-top:1.5rem}.jumbo-title{font-size:3.6rem}.jumbo-title .jumbo-icon{font-size:3.8rem;margin-right:.25em;position:relative;top:.15em}@media all and (max-width:1047px){.nav{padding-bottom:5.38rem;padding-left:1.5rem;text-align:center}.nav-bar{display:inline-block;float:none;margin-right:0;vertical-align:top}.nav .btn-group,.nav-bar-outer-actions{display:inline-block;float:none;margin-top:-8.48rem;text-align:center;vertical-align:top;width:100%}.nav-bar-outer-actions{padding-right:0}.nav-bar-outer-actions .outer-actions-inner-wrap{display:inline-block}}@media all and (min-width:768px){html{margin-left:calc(100vw - 100%);margin-right:0;overflow:auto}.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9{float:left}.col-m-12{width:100%}.col-m-11{width:91.66666667%}.col-m-10{width:83.33333333%}.col-m-9{width:75%}.col-m-8{width:66.66666667%}.col-m-7{width:58.33333333%}.col-m-6{width:50%}.col-m-5{width:41.66666667%}.col-m-4{width:33.33333333%}.col-m-3{width:25%}.col-m-2{width:16.66666667%}.col-m-1{width:8.33333333%}.col-m-pull-12{right:100%}.col-m-pull-11{right:91.66666667%}.col-m-pull-10{right:83.33333333%}.col-m-pull-9{right:75%}.col-m-pull-8{right:66.66666667%}.col-m-pull-7{right:58.33333333%}.col-m-pull-6{right:50%}.col-m-pull-5{right:41.66666667%}.col-m-pull-4{right:33.33333333%}.col-m-pull-3{right:25%}.col-m-pull-2{right:16.66666667%}.col-m-pull-1{right:8.33333333%}.col-m-pull-0{right:auto}.col-m-push-12{left:100%}.col-m-push-11{left:91.66666667%}.col-m-push-10{left:83.33333333%}.col-m-push-9{left:75%}.col-m-push-8{left:66.66666667%}.col-m-push-7{left:58.33333333%}.col-m-push-6{left:50%}.col-m-push-5{left:41.66666667%}.col-m-push-4{left:33.33333333%}.col-m-push-3{left:25%}.col-m-push-2{left:16.66666667%}.col-m-push-1{left:8.33333333%}.col-m-push-0{left:auto}.col-m-offset-12{margin-left:100%}.col-m-offset-11{margin-left:91.66666667%}.col-m-offset-10{margin-left:83.33333333%}.col-m-offset-9{margin-left:75%}.col-m-offset-8{margin-left:66.66666667%}.col-m-offset-7{margin-left:58.33333333%}.col-m-offset-6{margin-left:50%}.col-m-offset-5{margin-left:41.66666667%}.col-m-offset-4{margin-left:33.33333333%}.col-m-offset-3{margin-left:25%}.col-m-offset-2{margin-left:16.66666667%}.col-m-offset-1{margin-left:8.33333333%}.col-m-offset-0{margin-left:0}}@media all and (min-width:1048px){.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9{float:left}.col-l-12{width:100%}.col-l-11{width:91.66666667%}.col-l-10{width:83.33333333%}.col-l-9{width:75%}.col-l-8{width:66.66666667%}.col-l-7{width:58.33333333%}.col-l-6{width:50%}.col-l-5{width:41.66666667%}.col-l-4{width:33.33333333%}.col-l-3{width:25%}.col-l-2{width:16.66666667%}.col-l-1{width:8.33333333%}.col-l-pull-12{right:100%}.col-l-pull-11{right:91.66666667%}.col-l-pull-10{right:83.33333333%}.col-l-pull-9{right:75%}.col-l-pull-8{right:66.66666667%}.col-l-pull-7{right:58.33333333%}.col-l-pull-6{right:50%}.col-l-pull-5{right:41.66666667%}.col-l-pull-4{right:33.33333333%}.col-l-pull-3{right:25%}.col-l-pull-2{right:16.66666667%}.col-l-pull-1{right:8.33333333%}.col-l-pull-0{right:auto}.col-l-push-12{left:100%}.col-l-push-11{left:91.66666667%}.col-l-push-10{left:83.33333333%}.col-l-push-9{left:75%}.col-l-push-8{left:66.66666667%}.col-l-push-7{left:58.33333333%}.col-l-push-6{left:50%}.col-l-push-5{left:41.66666667%}.col-l-push-4{left:33.33333333%}.col-l-push-3{left:25%}.col-l-push-2{left:16.66666667%}.col-l-push-1{left:8.33333333%}.col-l-push-0{left:auto}.col-l-offset-12{margin-left:100%}.col-l-offset-11{margin-left:91.66666667%}.col-l-offset-10{margin-left:83.33333333%}.col-l-offset-9{margin-left:75%}.col-l-offset-8{margin-left:66.66666667%}.col-l-offset-7{margin-left:58.33333333%}.col-l-offset-6{margin-left:50%}.col-l-offset-5{margin-left:41.66666667%}.col-l-offset-4{margin-left:33.33333333%}.col-l-offset-3{margin-left:25%}.col-l-offset-2{margin-left:16.66666667%}.col-l-offset-1{margin-left:8.33333333%}.col-l-offset-0{margin-left:0}}@media all and (min-width:1440px){.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{float:left}.col-xl-12{width:100%}.col-xl-11{width:91.66666667%}.col-xl-10{width:83.33333333%}.col-xl-9{width:75%}.col-xl-8{width:66.66666667%}.col-xl-7{width:58.33333333%}.col-xl-6{width:50%}.col-xl-5{width:41.66666667%}.col-xl-4{width:33.33333333%}.col-xl-3{width:25%}.col-xl-2{width:16.66666667%}.col-xl-1{width:8.33333333%}.col-xl-pull-12{right:100%}.col-xl-pull-11{right:91.66666667%}.col-xl-pull-10{right:83.33333333%}.col-xl-pull-9{right:75%}.col-xl-pull-8{right:66.66666667%}.col-xl-pull-7{right:58.33333333%}.col-xl-pull-6{right:50%}.col-xl-pull-5{right:41.66666667%}.col-xl-pull-4{right:33.33333333%}.col-xl-pull-3{right:25%}.col-xl-pull-2{right:16.66666667%}.col-xl-pull-1{right:8.33333333%}.col-xl-pull-0{right:auto}.col-xl-push-12{left:100%}.col-xl-push-11{left:91.66666667%}.col-xl-push-10{left:83.33333333%}.col-xl-push-9{left:75%}.col-xl-push-8{left:66.66666667%}.col-xl-push-7{left:58.33333333%}.col-xl-push-6{left:50%}.col-xl-push-5{left:41.66666667%}.col-xl-push-4{left:33.33333333%}.col-xl-push-3{left:25%}.col-xl-push-2{left:16.66666667%}.col-xl-push-1{left:8.33333333%}.col-xl-push-0{left:auto}.col-xl-offset-12{margin-left:100%}.col-xl-offset-11{margin-left:91.66666667%}.col-xl-offset-10{margin-left:83.33333333%}.col-xl-offset-9{margin-left:75%}.col-xl-offset-8{margin-left:66.66666667%}.col-xl-offset-7{margin-left:58.33333333%}.col-xl-offset-6{margin-left:50%}.col-xl-offset-5{margin-left:41.66666667%}.col-xl-offset-4{margin-left:33.33333333%}.col-xl-offset-3{margin-left:25%}.col-xl-offset-2{margin-left:16.66666667%}.col-xl-offset-1{margin-left:8.33333333%}.col-xl-offset-0{margin-left:0}}@media all and (max-width:767px){.list-definition>dt{float:none}.list-definition>dd{margin-left:0}.form-row .form-label{text-align:left}.form-row .form-label.required:after{position:static}.nav{padding-bottom:0;padding-left:0;padding-right:0}.nav-bar-outer-actions{margin-top:0}.nav-bar{display:block;margin-bottom:0;margin-left:auto;margin-right:auto;width:30.9rem}.nav-bar:before{display:none}.nav-bar>li{float:left;min-height:9rem}.nav-bar>li:after{display:none}.nav-bar>li:nth-child(4n){clear:both}.nav-bar a{line-height:1.4}.tooltip{display:none!important}.readiness-check-content{margin-right:2rem}.form-el-insider,.form-el-insider-wrap,.page-web-configuration .form-el-insider-input,.page-web-configuration .form-el-insider-input .form-el-input{display:block;width:100%}}@media all and (max-width:479px){.nav-bar{width:23.175rem}.nav-bar>li{width:7.725rem}.nav .btn-group .btn-wrap-try-again,.nav-bar-outer-actions .btn-wrap-try-again{clear:both;display:block;float:none;margin-left:auto;margin-right:auto;margin-top:1rem;padding-top:1rem}} \ No newline at end of file diff --git a/setup/src/Magento/Setup/Controller/DatabaseCheck.php b/setup/src/Magento/Setup/Controller/DatabaseCheck.php index 0f5f911bd16268575ecd44f9e5a3408d705347aa..809496c9a6a0304f12bfc5d5a9b4cd11c221d8df 100644 --- a/setup/src/Magento/Setup/Controller/DatabaseCheck.php +++ b/setup/src/Magento/Setup/Controller/DatabaseCheck.php @@ -47,10 +47,13 @@ class DatabaseCheck extends AbstractActionController public function indexAction() { $params = Json::decode($this->getRequest()->getContent(), Json::TYPE_ARRAY); + try { $installer = $this->installerFactory->create($this->webLogger); $password = isset($params['password']) ? $params['password'] : ''; $installer->checkDatabaseConnection($params['name'], $params['host'], $params['user'], $password); + $tablePrefix = isset($params['tablePrefix']) ? $params['tablePrefix'] : ''; + $installer->checkDatabaseTablePrefix($tablePrefix); return new JsonModel(['success' => true]); } catch (\Exception $e) { return new JsonModel(['success' => false, 'error' => $e->getMessage()]); diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 6e4ed5761aa0807670519790364e68ceff0d3634..aaac7d81ac2e8f9fd85973faaa53170d317df449 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -875,6 +875,24 @@ class Installer return true; } + /** + * Check if database table prefix is valid + * + * @param string $prefix + * @return boolean + * @throws \InvalidArgumentException + */ + public function checkDatabaseTablePrefix($prefix) + { + //The table prefix should contain only letters (a-z), numbers (0-9) or underscores (_); + // the first character should be a letter. + if ($prefix !== '' && !preg_match('/^([a-zA-Z])([[:alnum:]_]+)$/', $prefix)) { + throw new \InvalidArgumentException('Please correct the table prefix format.'); + } + + return true; + } + /** * Return messages * @@ -994,6 +1012,9 @@ class Installer $config[DbConfig::KEY_USER], $config[DbConfig::KEY_PASS] ); + if (isset($config[DbConfig::KEY_PREFIX])) { + $this->checkDatabaseTablePrefix($config[DbConfig::KEY_PREFIX]); + } } /** diff --git a/setup/view/magento/setup/add-database.phtml b/setup/view/magento/setup/add-database.phtml index 7f6c7e68d8fa6f6b51134429ed79a92c93b1b40e..797ba456e7882c1f889385f7463fdfdc2b809698 100644 --- a/setup/view/magento/setup/add-database.phtml +++ b/setup/view/magento/setup/add-database.phtml @@ -337,7 +337,7 @@ id="dbTablePrefix" class="form-el-input" tooltip-placement="right" - tooltip="Enter a tracking prefix to be used for database tables created for this Magento installation. (ex: 'mg1_' )." + tooltip="Enter a prefix for database tables created in this installation. Use letters, numbers or underscores, and begin with a letter (Ex: ‘mg1_’)" tooltip-trigger="focus" tooltip-append-to-body="true" type="text" diff --git a/setup/view/magento/setup/create-admin-account.phtml b/setup/view/magento/setup/create-admin-account.phtml index 14ffe9061f505af3662035080142413cc50f0483..cb6b54e2c631d1b13a4bf2a181e2bf8522804275 100644 --- a/setup/view/magento/setup/create-admin-account.phtml +++ b/setup/view/magento/setup/create-admin-account.phtml @@ -15,10 +15,11 @@ $passwordWizard = sprintf( <div class=\'password-strength-item\'></div> <div class=\'password-strength-item\'></div> <div class=\'password-strength-item\'></div> + <div class=\'password-strength-item\'></div> </div> <p>%s</p>', 'Password Strength:', - 'Must be a mix of at least 7 alpha and numeric characters.(Ex.: BuyIt54).' + 'Enter a mix of 6 or more numbers and letters. For a stronger password, include at least one small letter, big letter, and symbol (Ex: BuyIt$54).' ); ?> @@ -144,7 +145,7 @@ $passwordWizard = sprintf( > <div class="error-container"> <span ng-show="account.adminPassword.$error.checkPassword"> - Please enter at least 7 alpha-numeric characters. + Please enter a mix of at least 6 alpha-numeric characters. </span> <span ng-show="account.adminPassword.$error.required"> Please enter your new password. diff --git a/setup/view/styles/components/tooltips/_password-strength.less b/setup/view/styles/components/tooltips/_password-strength.less index 9f77e70ef6ea06ec64658afff53083d2d6e35f39..1d80388483533f0f9a3f349a5a8c0fe6fb1fed6b 100644 --- a/setup/view/styles/components/tooltips/_password-strength.less +++ b/setup/view/styles/components/tooltips/_password-strength.less @@ -7,7 +7,7 @@ display: block; margin: 0 -.3rem 1em; white-space: nowrap; - &.password-strength-to-short { + &.password-strength-too-short { .password-strength-item { &:first-child { background-color: @color-failed; @@ -17,13 +17,22 @@ &.password-strength-weak { .password-strength-item:first-child, .password-strength-item:first-child + .password-strength-item { + background-color: @color-failed; + } + } + &.password-strength-fair { + .password-strength-item:first-child, + .password-strength-item:first-child + .password-strength-item, + .password-strength-item:first-child + .password-strength-item + .password-strength-item { background-color: @color-warning; } } &.password-strength-good { .password-strength-item:first-child, .password-strength-item:first-child + .password-strength-item, - .password-strength-item:first-child + .password-strength-item + .password-strength-item { + .password-strength-item:first-child + .password-strength-item + .password-strength-item, + .password-strength-item:first-child + .password-strength-item + .password-strength-item + + .password-strength-item { background-color: @color-success; } } @@ -38,6 +47,6 @@ font-size: 0; height: 1.4rem; margin-right: .3rem; - width: ~'calc(25% - .6rem)'; + width: ~'calc(20% - .6rem)'; } }