diff --git a/app/code/Magento/AdminNotification/i18n/zh_CN.csv b/app/code/Magento/AdminNotification/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/AdminNotification/i18n/zh_CN.csv rename to app/code/Magento/AdminNotification/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Authorizenet/i18n/zh_CN.csv b/app/code/Magento/Authorizenet/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Authorizenet/i18n/zh_CN.csv rename to app/code/Magento/Authorizenet/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Backend/Block/Dashboard/Orders/Grid.php b/app/code/Magento/Backend/Block/Dashboard/Orders/Grid.php index 4d47f0a1a862b..86152d6e38ccb 100644 --- a/app/code/Magento/Backend/Block/Dashboard/Orders/Grid.php +++ b/app/code/Magento/Backend/Block/Dashboard/Orders/Grid.php @@ -84,6 +84,19 @@ protected function _prepareCollection() return parent::_prepareCollection(); } + /** + * Process collection after loading + * + * @return $this + */ + protected function _afterLoadCollection() + { + foreach ($this->getCollection() as $item) { + $item->getCustomer() ?: $item->setCustomer('Guest'); + } + return $this; + } + /** * Prepares page sizes for dashboard grid with las 5 orders * diff --git a/app/code/Magento/Backend/Block/Store/Switcher.php b/app/code/Magento/Backend/Block/Store/Switcher.php index cd5c0a2247f10..5933b7431973f 100644 --- a/app/code/Magento/Backend/Block/Store/Switcher.php +++ b/app/code/Magento/Backend/Block/Store/Switcher.php @@ -211,7 +211,7 @@ public function isWebsiteSelected(\Magento\Store\Model\Website $website) public function getWebsiteId() { if (!$this->hasData('website_id')) { - $this->setData('website_id', $this->getRequest()->getParam($this->getWebsiteVarName())); + $this->setData('website_id', (int)$this->getRequest()->getParam($this->getWebsiteVarName())); } return $this->getData('website_id'); } @@ -289,7 +289,7 @@ public function isStoreGroupSelected(\Magento\Store\Model\Group $group) public function getStoreGroupId() { if (!$this->hasData('store_group_id')) { - $this->setData('store_group_id', $this->getRequest()->getParam($this->getStoreGroupVarName())); + $this->setData('store_group_id', (int)$this->getRequest()->getParam($this->getStoreGroupVarName())); } return $this->getData('store_group_id'); } @@ -339,7 +339,7 @@ public function getStores($group) public function getStoreId() { if (!$this->hasData('store_id')) { - $this->setData('store_id', $this->getRequest()->getParam($this->getStoreVarName())); + $this->setData('store_id', (int)$this->getRequest()->getParam($this->getStoreVarName())); } return $this->getData('store_id'); } diff --git a/app/code/Magento/Backend/i18n/zh_CN.csv b/app/code/Magento/Backend/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Backend/i18n/zh_CN.csv rename to app/code/Magento/Backend/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Backend/view/adminhtml/templates/store/switcher.phtml b/app/code/Magento/Backend/view/adminhtml/templates/store/switcher.phtml index f43b8f6bf691d..ad46dbeec25be 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/store/switcher.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/store/switcher.phtml @@ -174,7 +174,7 @@ require(['jquery'], function(jQuery){ if (confirm("")) { reload(); } else { - obj.value = 'getStoreId() ?>'; + obj.value = 'escapeHtml($block->getStoreId()) ?>'; } reload(); diff --git a/app/code/Magento/Backup/i18n/zh_CN.csv b/app/code/Magento/Backup/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Backup/i18n/zh_CN.csv rename to app/code/Magento/Backup/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Bundle/i18n/zh_CN.csv b/app/code/Magento/Bundle/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Bundle/i18n/zh_CN.csv rename to app/code/Magento/Bundle/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Captcha/i18n/zh_CN.csv b/app/code/Magento/Captcha/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Captcha/i18n/zh_CN.csv rename to app/code/Magento/Captcha/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Catalog/Api/CategoryManagementInterface.php b/app/code/Magento/Catalog/Api/CategoryManagementInterface.php index 8671e9ea0b9f5..fbc619955b08a 100644 --- a/app/code/Magento/Catalog/Api/CategoryManagementInterface.php +++ b/app/code/Magento/Catalog/Api/CategoryManagementInterface.php @@ -33,4 +33,11 @@ public function getTree($rootCategoryId = null, $depth = null); * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function move($categoryId, $parentId, $afterId = null); + + /** + * Provide the number of category count + * + * @return int + */ + public function getCount(); } diff --git a/app/code/Magento/Catalog/Api/ProductManagementInterface.php b/app/code/Magento/Catalog/Api/ProductManagementInterface.php new file mode 100644 index 0000000000000..a0a46774de43b --- /dev/null +++ b/app/code/Magento/Catalog/Api/ProductManagementInterface.php @@ -0,0 +1,20 @@ +_postDataHelper->getPostData( - $this->getPagerUrl(), - [\Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => $this->getPagerEncodedUrl()] - ); + $defaultMode = $this->_productListHelper->getDefaultViewMode($this->getModes()); $options = [ - 'modeCookie' => ToolbarModel::MODE_COOKIE_NAME, - 'directionCookie' => ToolbarModel::DIRECTION_COOKIE_NAME, - 'orderCookie' => ToolbarModel::ORDER_COOKIE_NAME, - 'limitCookie' => ToolbarModel::LIMIT_COOKIE_NAME + 'mode' => ToolbarModel::MODE_PARAM_NAME, + 'direction' => ToolbarModel::DIRECTION_PARAM_NAME, + 'order' => ToolbarModel::ORDER_PARAM_NAME, + 'limit' => ToolbarModel::LIMIT_PARAM_NAME, + 'modeDefault' => $defaultMode, + 'directionDefault' => \Magento\Catalog\Helper\Product\ProductList::DEFAULT_SORT_DIRECTION, + 'orderDefault' => $this->_productListHelper->getDefaultSortField(), + 'limitDefault' => $this->_productListHelper->getDefaultLimitPerPageValue($defaultMode), + 'url' => $this->getPagerUrl(), ]; - if ($postData) { - $options['postData'] = json_decode($postData); - } $options = array_replace_recursive($options, $customOptions); return json_encode(['productListToolbarForm' => $options]); } diff --git a/app/code/Magento/Catalog/Block/Product/View/Gallery.php b/app/code/Magento/Catalog/Block/Product/View/Gallery.php index f8b77d46d3ca7..e7817243ac2a7 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Gallery.php +++ b/app/code/Magento/Catalog/Block/Product/View/Gallery.php @@ -12,6 +12,7 @@ namespace Magento\Catalog\Block\Product\View; use Magento\Framework\Data\Collection; +use Magento\Catalog\Helper\Image; class Gallery extends \Magento\Catalog\Block\Product\View\AbstractView { @@ -112,7 +113,8 @@ public function isMainImage($image) */ public function getImageAttribute($imageId, $attributeName, $default = null) { - $attributes = $this->getConfigView()->getImageAttributes('Magento_Catalog', $imageId); + $attributes = + $this->getConfigView()->getMediaAttributes('Magento_Catalog', Image::MEDIA_TYPE_CONFIG_NODE, $imageId); return isset($attributes[$attributeName]) ? $attributes[$attributeName] : $default; } diff --git a/app/code/Magento/Catalog/Helper/Image.php b/app/code/Magento/Catalog/Helper/Image.php index 00ab3f634498c..c4ceb6bea1f0d 100644 --- a/app/code/Magento/Catalog/Helper/Image.php +++ b/app/code/Magento/Catalog/Helper/Image.php @@ -14,6 +14,11 @@ */ class Image extends AbstractHelper { + /** + * Media config node + */ + const MEDIA_TYPE_CONFIG_NODE = 'images'; + /** * Current model * @@ -172,7 +177,7 @@ public function init($product, $imageId, $attributes = []) $this->attributes = array_merge( $attributes, - $this->getConfigView()->getImageAttributes('Magento_Catalog', $imageId) + $this->getConfigView()->getMediaAttributes('Magento_Catalog', self::MEDIA_TYPE_CONFIG_NODE, $imageId) ); $this->setProduct($product); @@ -425,13 +430,14 @@ public function placeholder($fileName) /** * Get Placeholder + * * @param null|string $placeholder * @return string */ public function getPlaceholder($placeholder = null) { if (!$this->_placeholder) { - $placeholder = $placeholder?: $this->_getModel()->getDestinationSubdir(); + $placeholder = $placeholder ? : $this->_getModel()->getDestinationSubdir(); $this->_placeholder = 'Magento_Catalog::images/product/placeholder/' . $placeholder . '.jpg'; } return $this->_placeholder; @@ -810,7 +816,7 @@ public function getWidth() */ public function getHeight() { - return $this->getAttribute('height') ?: $this->getAttribute('width'); + return $this->getAttribute('height') ? : $this->getAttribute('width'); } /** diff --git a/app/code/Magento/Catalog/Model/App/Action/ContextPlugin.php b/app/code/Magento/Catalog/Model/App/Action/ContextPlugin.php deleted file mode 100644 index 962a2b9ee538d..0000000000000 --- a/app/code/Magento/Catalog/Model/App/Action/ContextPlugin.php +++ /dev/null @@ -1,80 +0,0 @@ -toolbarModel = $toolbarModel; - $this->httpContext = $httpContext; - $this->productListHelper = $productListHelper; - } - - /** - * @param \Magento\Framework\App\ActionInterface $subject - * @param callable $proceed - * @param \Magento\Framework\App\RequestInterface $request - * @return mixed - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function aroundDispatch( - \Magento\Framework\App\ActionInterface $subject, - \Closure $proceed, - \Magento\Framework\App\RequestInterface $request - ) { - $this->httpContext->setValue( - Data::CONTEXT_CATALOG_SORT_DIRECTION, - $this->toolbarModel->getDirection(), - \Magento\Catalog\Helper\Product\ProductList::DEFAULT_SORT_DIRECTION - ); - $this->httpContext->setValue( - Data::CONTEXT_CATALOG_SORT_ORDER, - $this->toolbarModel->getOrder(), - $this->productListHelper->getDefaultSortField() - ); - $this->httpContext->setValue( - Data::CONTEXT_CATALOG_DISPLAY_MODE, - $this->toolbarModel->getMode(), - $this->productListHelper->getDefaultViewMode() - ); - $this->httpContext->setValue( - Data::CONTEXT_CATALOG_LIMIT, - $this->toolbarModel->getLimit(), - $this->productListHelper->getDefaultLimitPerPageValue($this->productListHelper->getDefaultViewMode()) - ); - return $proceed($request); - } -} diff --git a/app/code/Magento/Catalog/Model/CategoryManagement.php b/app/code/Magento/Catalog/Model/CategoryManagement.php index 53f92b0d46373..d6b83501c0731 100644 --- a/app/code/Magento/Catalog/Model/CategoryManagement.php +++ b/app/code/Magento/Catalog/Model/CategoryManagement.php @@ -7,6 +7,8 @@ namespace Magento\Catalog\Model; +use Magento\Catalog\Model\Resource\Category\CollectionFactory; + class CategoryManagement implements \Magento\Catalog\Api\CategoryManagementInterface { /** @@ -22,13 +24,16 @@ class CategoryManagement implements \Magento\Catalog\Api\CategoryManagementInter /** * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository * @param Category\Tree $categoryTree + * @param CollectionFactory $categoriesFactory */ public function __construct( \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Catalog\Model\Category\Tree $categoryTree + \Magento\Catalog\Model\Category\Tree $categoryTree, + \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoriesFactory ) { $this->categoryRepository = $categoryRepository; $this->categoryTree = $categoryTree; + $this->categoriesFactory = $categoriesFactory; } /** @@ -72,4 +77,15 @@ public function move($categoryId, $parentId, $afterId = null) } return true; } + + /** + * {@inheritdoc} + */ + public function getCount() + { + $categories = $this->categoriesFactory->create(); + /** @var \Magento\Catalog\Model\Resource\Category\Collection $categories */ + $categories->addAttributeToFilter('parent_id', ['gt' => 0]); + return $categories->getSize(); + } } diff --git a/app/code/Magento/Catalog/Model/ImageExtractor.php b/app/code/Magento/Catalog/Model/ImageExtractor.php new file mode 100644 index 0000000000000..2b1da2384809b --- /dev/null +++ b/app/code/Magento/Catalog/Model/ImageExtractor.php @@ -0,0 +1,41 @@ +getAttribute('module'); + foreach ($mediaNode->getElementsByTagName(ImageEntryConverter::MEDIA_TYPE_CODE) as $node) { + $imageId = $node->getAttribute('id'); + $result[$mediaParentTag][$moduleNameImage][Image::MEDIA_TYPE_CONFIG_NODE][$imageId]['type'] + = $node->getAttribute('type'); + foreach ($node->childNodes as $attribute) { + if ($attribute->nodeType != XML_ELEMENT_NODE) { + continue; + } + $nodeValue = $attribute->nodeValue; + $result[$mediaParentTag][$moduleNameImage][Image::MEDIA_TYPE_CONFIG_NODE][$imageId][$attribute->tagName] + = $nodeValue; + } + } + + return $result; + } +} diff --git a/app/code/Magento/Catalog/Model/Product/Image/Cache.php b/app/code/Magento/Catalog/Model/Product/Image/Cache.php index b1578af8a8c40..946d307e67a63 100644 --- a/app/code/Magento/Catalog/Model/Product/Image/Cache.php +++ b/app/code/Magento/Catalog/Model/Product/Image/Cache.php @@ -64,7 +64,7 @@ protected function getData() 'area' => Area::AREA_FRONTEND, 'themeModel' => $theme, ]); - $images = $config->getImages('Magento_Catalog'); + $images = $config->getMediaEntities('Magento_Catalog', ImageHelper::MEDIA_TYPE_CONFIG_NODE); foreach ($images as $imageId => $imageData) { $this->data[$theme->getCode() . $imageId] = array_merge(['id' => $imageId], $imageData); } diff --git a/app/code/Magento/Catalog/Model/Product/ProductList/Toolbar.php b/app/code/Magento/Catalog/Model/Product/ProductList/Toolbar.php index adf6d51492d38..1faf9da01388e 100644 --- a/app/code/Magento/Catalog/Model/Product/ProductList/Toolbar.php +++ b/app/code/Magento/Catalog/Model/Product/ProductList/Toolbar.php @@ -5,8 +5,6 @@ */ namespace Magento\Catalog\Model\Product\ProductList; -use Magento\Framework\Stdlib\CookieManagerInterface; - /** * Class Toolbar */ @@ -20,29 +18,22 @@ class Toolbar /** * Sort order cookie name */ - const ORDER_COOKIE_NAME = 'product_list_order'; + const ORDER_PARAM_NAME = 'product_list_order'; /** * Sort direction cookie name */ - const DIRECTION_COOKIE_NAME = 'product_list_dir'; + const DIRECTION_PARAM_NAME = 'product_list_dir'; /** * Sort mode cookie name */ - const MODE_COOKIE_NAME = 'product_list_mode'; + const MODE_PARAM_NAME = 'product_list_mode'; /** * Products per page limit order cookie name */ - const LIMIT_COOKIE_NAME = 'product_list_limit'; - - /** - * Cookie manager - * - * @var CookieManagerInterface - */ - protected $cookieManager; + const LIMIT_PARAM_NAME = 'product_list_limit'; /** * Request @@ -52,14 +43,11 @@ class Toolbar protected $request; /** - * @param CookieManagerInterface $cookieManager * @param \Magento\Framework\App\Request\Http $request */ public function __construct( - CookieManagerInterface $cookieManager, \Magento\Framework\App\Request\Http $request ) { - $this->cookieManager = $cookieManager; $this->request = $request; } @@ -70,7 +58,7 @@ public function __construct( */ public function getOrder() { - return $this->cookieManager->getCookie(self::ORDER_COOKIE_NAME); + return $this->request->getParam(self::ORDER_PARAM_NAME); } /** @@ -80,7 +68,7 @@ public function getOrder() */ public function getDirection() { - return $this->cookieManager->getCookie(self::DIRECTION_COOKIE_NAME); + return $this->request->getParam(self::DIRECTION_PARAM_NAME); } /** @@ -90,7 +78,7 @@ public function getDirection() */ public function getMode() { - return $this->cookieManager->getCookie(self::MODE_COOKIE_NAME); + return $this->request->getParam(self::MODE_PARAM_NAME); } /** @@ -100,7 +88,7 @@ public function getMode() */ public function getLimit() { - return $this->cookieManager->getCookie(self::LIMIT_COOKIE_NAME); + return $this->request->getParam(self::LIMIT_PARAM_NAME); } /** * Return current page from request diff --git a/app/code/Magento/Catalog/Model/ProductManagement.php b/app/code/Magento/Catalog/Model/ProductManagement.php new file mode 100644 index 0000000000000..2d98303a3115a --- /dev/null +++ b/app/code/Magento/Catalog/Model/ProductManagement.php @@ -0,0 +1,44 @@ +productsFactory = $productsFactory; + } + + /** + * {@inheritdoc} + */ + public function getCount($status = null) + { + $products = $this->productsFactory->create(); + /** @var \Magento\Catalog\Model\Resource\Product\Collection $products */ + switch ($status) { + case Status::STATUS_ENABLED: + $products->addAttributeToFilter('status', Status::STATUS_ENABLED); + break; + case Status::STATUS_DISABLED: + $products->addAttributeToFilter('status', Status::STATUS_DISABLED); + break; + } + return $products->getSize(); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php index 3ca45c47f27b8..5478152e8b99d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Helper/ImageTest.php @@ -149,8 +149,8 @@ protected function prepareAttributes($data, $imageId) ->disableOriginalConstructor() ->getMock(); $configViewMock->expects($this->once()) - ->method('getImageAttributes') - ->with('Magento_Catalog', $imageId) + ->method('getMediaAttributes') + ->with('Magento_Catalog', 'images', $imageId) ->willReturn($data); $this->viewConfig->expects($this->once()) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/App/Action/ContextPluginTest.php b/app/code/Magento/Catalog/Test/Unit/Model/App/Action/ContextPluginTest.php deleted file mode 100644 index 9f59ec919815c..0000000000000 --- a/app/code/Magento/Catalog/Test/Unit/Model/App/Action/ContextPluginTest.php +++ /dev/null @@ -1,136 +0,0 @@ -toolbarModelMock = $this->getMock( - 'Magento\Catalog\Model\Product\ProductList\Toolbar', - [ - 'getDirection', - 'getOrder', - 'getMode', - 'getLimit' - ], - [], - '', - false - ); - $this->closureMock = function () { - return 'ExpectedValue'; - }; - $this->subjectMock = $this->getMock('Magento\Framework\App\Action\Action', [], [], '', false); - $this->requestMock = $this->getMock('Magento\Framework\App\RequestInterface'); - $this->httpContextMock = $this->getMock('Magento\Framework\App\Http\Context', [], [], '', false); - $this->productListHelperMock = $this->getMock('Magento\Catalog\Helper\Product\ProductList', - [], [], '', false); - $this->plugin = new ContextPlugin( - $this->toolbarModelMock, - $this->httpContextMock, - $this->productListHelperMock - ); - } - - public function testAroundDispatchHasSortDirection() - { - $this->toolbarModelMock->expects($this->exactly(1)) - ->method('getDirection') - ->will($this->returnValue('asc')); - $this->toolbarModelMock->expects($this->once()) - ->method('getOrder') - ->will($this->returnValue('Name')); - $this->toolbarModelMock->expects($this->once()) - ->method('getMode') - ->will($this->returnValue('list')); - $this->toolbarModelMock->expects($this->once()) - ->method('getLimit') - ->will($this->returnValue([1 => 1, 2 => 2])); - $this->productListHelperMock->expects($this->once()) - ->method('getDefaultSortField') - ->will($this->returnValue('Field')); - $this->productListHelperMock->expects($this->exactly(2)) - ->method('getDefaultViewMode') - ->will($this->returnValue('grid')); - $this->productListHelperMock->expects($this->once()) - ->method('getDefaultLimitPerPageValue') - ->will($this->returnValue([10 => 10])); - $this->httpContextMock->expects($this->exactly(4)) - ->method('setValue') - ->will($this->returnValueMap([ - [ - \Magento\Catalog\Helper\Data::CONTEXT_CATALOG_SORT_DIRECTION, - 'asc', - \Magento\Catalog\Helper\Product\ProductList::DEFAULT_SORT_DIRECTION, - $this->httpContextMock, - ], [ - \Magento\Catalog\Helper\Data::CONTEXT_CATALOG_SORT_ORDER, - 'Name', - 'Field', - $this->httpContextMock - ], [ - \Magento\Catalog\Helper\Data::CONTEXT_CATALOG_DISPLAY_MODE, - 'list', - 'grid', - $this->httpContextMock - ], [ - \Magento\Catalog\Helper\Data::CONTEXT_CATALOG_LIMIT, - [1 => 1, 2 => 2], [10 => 10] - ], - ])); - $this->assertEquals( - 'ExpectedValue', - $this->plugin->aroundDispatch($this->subjectMock, $this->closureMock, $this->requestMock) - ); - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryManagementTest.php index 70e73e59e44e1..4dd3d46c20e21 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryManagementTest.php @@ -13,22 +13,35 @@ class CategoryManagementTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Api\CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $categoryRepositoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Category\Tree|\PHPUnit_Framework_MockObject_MockObject */ protected $categoryTreeMock; + /** + * @var \Magento\Catalog\Model\Resource\Category\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $categoriesFactoryMock; + protected function setUp() { - $this->categoryRepositoryMock = $this->getMock('\Magento\Catalog\Api\CategoryRepositoryInterface'); - $this->categoryTreeMock = $this->getMock('\Magento\Catalog\Model\Category\Tree', [], [], '', false); + $this->categoryRepositoryMock = $this->getMock('Magento\Catalog\Api\CategoryRepositoryInterface'); + $this->categoryTreeMock = $this->getMock('Magento\Catalog\Model\Category\Tree', [], [], '', false); + $this->categoriesFactoryMock = $this->getMock( + 'Magento\Catalog\Model\Resource\Category\CollectionFactory', + ['create'], + [], + '', + false + ); $this->model = new \Magento\Catalog\Model\CategoryManagement( $this->categoryRepositoryMock, - $this->categoryTreeMock + $this->categoryTreeMock, + $this->categoriesFactoryMock ); } @@ -171,4 +184,28 @@ public function testMoveWithCouldNotMoveException() ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('message'))); $this->model->move($categoryId, $parentId, $afterId); } + + public function testGetCount() + { + $categoriesMock = $this->getMock('\Magento\Catalog\Model\Resource\Category\Collection', [], [], '', false); + + $this->categoriesFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($categoriesMock); + $categoriesMock + ->expects($this->once()) + ->method('addAttributeToFilter') + ->with('parent_id', ['gt' => 0]) + ->willReturnSelf(); + $categoriesMock + ->expects($this->once()) + ->method('getSize') + ->willReturn('expected'); + + $this->assertEquals( + 'expected', + $this->model->getCount() + ); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php index 44a4e9ff27c1b..89bf16e78dde5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Image/CacheTest.php @@ -108,7 +108,7 @@ public function testGenerate() $data = $this->getTestData(); $this->config->expects($this->once()) - ->method('getImages') + ->method('getMediaEntities') ->with('Magento_Catalog') ->willReturn($data); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php index 4906cce6924ee..52edeec82e80e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/ProductList/ToolbarTest.php @@ -17,11 +17,6 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase */ protected $toolbarModel; - /** - * @var \Magento\Framework\Stdlib\CookieManagerInterface |\PHPUnit_Framework_MockObject_MockObject - */ - protected $cookieManagerMock; - /** * @var \Magento\Framework\App\Request\Http |\PHPUnit_Framework_MockObject_MockObject */ @@ -32,14 +27,12 @@ class ToolbarTest extends \PHPUnit_Framework_TestCase */ public function setUp() { - $this->cookieManagerMock = $this->getMock('Magento\Framework\Stdlib\CookieManagerInterface'); $this->requestMock = $this->getMockBuilder('Magento\Framework\App\Request\Http') ->disableOriginalConstructor() ->getMock(); $this->toolbarModel = (new ObjectManager($this))->getObject( 'Magento\Catalog\Model\Product\ProductList\Toolbar', [ - 'cookieManager' => $this->cookieManagerMock, 'request' => $this->requestMock, ] ); @@ -51,9 +44,9 @@ public function setUp() */ public function testGetOrder($param) { - $this->cookieManagerMock->expects($this->once()) - ->method('getCookie') - ->with(Toolbar::ORDER_COOKIE_NAME) + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with(Toolbar::ORDER_PARAM_NAME) ->will($this->returnValue($param)); $this->assertEquals($param, $this->toolbarModel->getOrder()); } @@ -64,9 +57,9 @@ public function testGetOrder($param) */ public function testGetDirection($param) { - $this->cookieManagerMock->expects($this->once()) - ->method('getCookie') - ->with(Toolbar::DIRECTION_COOKIE_NAME) + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with(Toolbar::DIRECTION_PARAM_NAME) ->will($this->returnValue($param)); $this->assertEquals($param, $this->toolbarModel->getDirection()); } @@ -77,9 +70,9 @@ public function testGetDirection($param) */ public function testGetMode($param) { - $this->cookieManagerMock->expects($this->once()) - ->method('getCookie') - ->with(Toolbar::MODE_COOKIE_NAME) + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with(Toolbar::MODE_PARAM_NAME) ->will($this->returnValue($param)); $this->assertEquals($param, $this->toolbarModel->getMode()); } @@ -90,9 +83,9 @@ public function testGetMode($param) */ public function testGetLimit($param) { - $this->cookieManagerMock->expects($this->once()) - ->method('getCookie') - ->with(Toolbar::LIMIT_COOKIE_NAME) + $this->requestMock->expects($this->once()) + ->method('getParam') + ->with(Toolbar::LIMIT_PARAM_NAME) ->will($this->returnValue($param)); $this->assertEquals($param, $this->toolbarModel->getLimit()); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductManagementTest.php new file mode 100644 index 0000000000000..af3caf60b77c2 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductManagementTest.php @@ -0,0 +1,83 @@ +productsFactoryMock = $this->getMock( + 'Magento\Catalog\Model\Resource\Product\CollectionFactory', + ['create'], + [], + '', + false + ); + $this->model = new \Magento\Catalog\Model\ProductManagement( + $this->productsFactoryMock + ); + } + + public function testGetEnabledCount() + { + $statusEnabled = 1; + $productsMock = $this->getMock('Magento\Catalog\Model\Resource\Product\Collection', [], [], '', false); + + $this->productsFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($productsMock); + $productsMock + ->expects($this->once()) + ->method('addAttributeToFilter') + ->with('status', $statusEnabled) + ->willReturnSelf(); + $productsMock + ->expects($this->once()) + ->method('getSize') + ->willReturn('expected'); + + $this->assertEquals( + 'expected', + $this->model->getCount($statusEnabled) + ); + } + + public function testGetDisabledCount() + { + $statusDisabled = 2; + $productsMock = $this->getMock('\Magento\Catalog\Model\Resource\Product\Collection', [], [], '', false); + + $this->productsFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($productsMock); + $productsMock + ->expects($this->once()) + ->method('addAttributeToFilter') + ->with('status', $statusDisabled) + ->willReturnSelf(); + $productsMock + ->expects($this->once()) + ->method('getSize') + ->willReturn('expected'); + + $this->assertEquals( + 'expected', + $this->model->getCount($statusDisabled) + ); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php index 821ff62d8d900..9cece1e8b642a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php @@ -1129,7 +1129,7 @@ public function testSetMediaGalleryEntries() $expectedResult = [ 'images' => [ [ - "value_id" => 1, + 'value_id' => 1, 'file' => 'file1.jpg', 'label' => 'label_text', 'position' => 4, @@ -1163,7 +1163,7 @@ public function testSetMediaGalleryEntries() ->getMockForAbstractClass(); $result = [ - "value_id" => 1, + 'value_id' => 1, 'file' => 'file1.jpg', 'label' => 'label_text', 'position' => 4, diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php index 1e8b7fb4a7fba..ec0547e6f1b9e 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php @@ -45,9 +45,9 @@ public function __construct( * Prepare Data Source * * @param array $dataSource - * @return void + * @return array */ - public function prepareDataSource(array & $dataSource) + public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { $store = $this->storeManager->getStore( @@ -64,5 +64,7 @@ public function prepareDataSource(array & $dataSource) } } } + + return $dataSource; } } diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/ProductActions.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/ProductActions.php index 0be379dabcb82..1dd1308c0ba8e 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/ProductActions.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/ProductActions.php @@ -42,9 +42,9 @@ public function __construct( * Prepare Data Source * * @param array $dataSource - * @return void + * @return array */ - public function prepareDataSource(array &$dataSource) + public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { $storeId = $this->context->getFilterParam('store_id'); @@ -60,5 +60,7 @@ public function prepareDataSource(array &$dataSource) ]; } } + + return $dataSource; } } diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php index 23b8f50484ab8..9b5cc999873f6 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Thumbnail.php @@ -39,9 +39,9 @@ public function __construct( * Prepare Data Source * * @param array $dataSource - * @return void + * @return array */ - public function prepareDataSource(array & $dataSource) + public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { $fieldName = $this->getData('name'); @@ -58,6 +58,8 @@ public function prepareDataSource(array & $dataSource) $item[$fieldName . '_orig_src'] = $origImageHelper->getUrl(); } } + + return $dataSource; } /** diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php index f2e6f5f00d2cc..ffeed2a2d25f1 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php @@ -44,7 +44,7 @@ public function __construct( /** * {@inheritdoc} */ - public function prepareDataSource(array & $dataSource) + public function prepareDataSource(array $dataSource) { $websiteNames = []; foreach ($this->getData('options') as $website) { @@ -60,6 +60,8 @@ public function prepareDataSource(array & $dataSource) $item[$fieldName] = implode(', ', $websites); } } + + return $dataSource; } /** diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index c8e2e9645cde1..a2bc7bcf6e1c6 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -42,6 +42,7 @@ + @@ -491,4 +492,26 @@ + + + + + + module + + + id + type + + + + + + + + + Magento\Catalog\Model\ImageExtractor + + + diff --git a/app/code/Magento/Catalog/etc/frontend/di.xml b/app/code/Magento/Catalog/etc/frontend/di.xml index 132f2a29b1526..328a35a83afa9 100644 --- a/app/code/Magento/Catalog/etc/frontend/di.xml +++ b/app/code/Magento/Catalog/etc/frontend/di.xml @@ -35,9 +35,6 @@ true - - - diff --git a/app/code/Magento/Catalog/etc/view.xml b/app/code/Magento/Catalog/etc/view.xml index df4b01c10ee6a..e487426151f62 100644 --- a/app/code/Magento/Catalog/etc/view.xml +++ b/app/code/Magento/Catalog/etc/view.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> - + 1 diff --git a/app/code/Magento/Catalog/etc/view.xsd b/app/code/Magento/Catalog/etc/view.xsd new file mode 100644 index 0000000000000..b05d57c48422a --- /dev/null +++ b/app/code/Magento/Catalog/etc/view.xsd @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Catalog/i18n/zh_CN.csv b/app/code/Magento/Catalog/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Catalog/i18n/zh_CN.csv rename to app/code/Magento/Catalog/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js index 163a537df655f..17b5f95205fdf 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/base-image-uploader.js @@ -8,7 +8,8 @@ define([ 'mage/template', 'jquery/ui', 'jquery/file-uploader', - 'mage/translate' + 'mage/translate', + 'mage/backend/notification' ], function ($, mageTemplate) { 'use strict'; @@ -17,6 +18,9 @@ define([ * Button creation * @protected */ + options: { + maxImageUploadCount : 10 + }, _create: function () { var $container = this.element, imageTmpl = mageTemplate(this.element.find('[data-template=image]').html()), @@ -130,6 +134,20 @@ define([ alert($.mage.__('We don\'t recognize or support this file extension type.')); } }, + change: function(e, data) { + if (data.files.length > this.options.maxImageUploadCount) { + $('body').notification('clear').notification('add', { + error: true, + message: $.mage.__('You can\'t upload more than ' + this.options.maxImageUploadCount + + ' images in one time'), + insertMethod: function(message) { + $('.page-main-actions').after(message); + } + }); + + return false; + } + }.bind(this), add: function (event, data) { $(this).fileupload('process', data).done(function () { data.submit(); diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js b/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js index 890dd8d6b456f..45ee5c2d5c909 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js @@ -46,6 +46,7 @@ define([ */ _bind: function () { var events = { + openDialog: '_onOpenDialog', addItem: '_addItem', removeItem: '_removeItem', setImageType: '_setImageType', @@ -138,7 +139,7 @@ define([ imageData = $.extend({ file_id: Math.random().toString(33).substr(2, 18), - disabled: 0, + disabled: imageData.disabled ? imageData.disabled : 0, position: count + 1 }, imageData); @@ -147,9 +148,6 @@ define([ }); element = $(element).data('imageData', imageData); - if(imageData.subclass) { - element.addClass(imageData.subclass); - } if (count === 0) { element.prependTo(this.element); } else { @@ -163,6 +161,7 @@ define([ ) { this.setBase(imageData); } + $.each(this.options.types, $.proxy(function (index, image) { if (imageData.file === image.value) { this.element.trigger('setImageType', { @@ -270,11 +269,7 @@ define([ */ _bind: function () { this._super(); - var events = { - 'change [data-role=visibility-trigger]': '_changeVisibility', - 'change [data-role=type-selector]': '_changeType' - }; - + var events = {}; events['click [data-role=close-panel]'] = $.proxy(function () { this.element.find('[data-role=dialog]').trigger('close'); }, this); @@ -283,39 +278,33 @@ define([ $(event.currentTarget).addClass('active'); var itemId = $(event.currentTarget).find('input')[0].name.match(/\[([^\]]*)\]/g)[2]; $('#item_id').val(itemId); - this._showDialog($(event.currentTarget).data('imageData')); + var imageData = $(event.currentTarget).data('imageData'); + var $imageContainer = this.findElement(imageData); + if ($imageContainer.is('.removed')) { + return; + } + this.element.trigger('openDialog', [imageData]); } }; this._on(events); this.element.on('sortstart', $.proxy(function () { this.element.find('[data-role=dialog]').trigger('close'); }, this)); - - this.element.on('change', '[data-role=type-selector]', function () { - var parent = $(this).closest('.item'), - selectedClass = 'selected'; - parent.toggleClass(selectedClass, $(this).prop('checked')); - }); }, /** - * Set Position of Image Pointer - * @param image - * @param panel + * + * Click by image handler + * + * @param e + * @param imageData * @private */ - _setImagePointerPosition: function (image, panel) { - var position = image.position(), - posX = position.left, - imageWidth = image.width(), - pointer = $('.image-pointer', panel), - pointerWidth = pointer.width(), - padding = -3, - pointerOffset = posX + padding + pointerWidth / 2 + imageWidth / 2; - - pointer.css({ - left: pointerOffset - }); + _onOpenDialog: function(e, imageData) { + if(imageData.media_type && imageData.media_type != 'image') { + return; + } + this._showDialog(imageData); }, /** @@ -325,69 +314,71 @@ define([ */ _showDialog: function (imageData) { var $imageContainer = this.findElement(imageData); - - if ($imageContainer.find('input[name*="media_type"]').val() == 'external-video') { - $('#new-video').modal('openModal'); + var dialogElement = $imageContainer.data('dialog'); + if(!this.dialogTmpl) { + alert('System problem!'); return; } - var dialogElement = $imageContainer.data('dialog'); + var $template = this.dialogTmpl({ data: imageData }); + dialogElement = $($template); + dialogElement.modal({ + 'type': 'slide', + title: $.mage.__('Image Detail'), + buttons: [], + opened: function() { + dialogElement.trigger('open'); + }, + closed: function(e) { + dialogElement.trigger('close'); + } + }); + dialogElement + .data('imageContainer', $imageContainer) + .on('open', $.proxy(function (event) { + $(event.target) + .find('[data-role=type-selector]') + .each($.proxy(function (index, checkbox) { + var $checkbox = $(checkbox), + parent = $checkbox.closest('.item'), + selectedClass = 'selected', + isChecked = this.options.types[$checkbox.val()].value == imageData.file; + $checkbox.prop( + 'checked', + isChecked + ); + parent.toggleClass(selectedClass, isChecked); + }, this)); + + }, this)) + .on('close', $.proxy(function (event) { + $imageContainer.removeClass('active'); + $imageContainer.data('dialog', null); + }, this)); + + $imageContainer.data('dialog', dialogElement); + + + var _changeDescription = function(e) { + var target = jQuery(e.target); + var targetName = target.attr('name'); + var desc = target.val(); + jQuery('input[type="hidden"][name="'+ targetName + '"]').val(desc); + imageData.label = desc; + imageData.label_default = desc; + }; - if ($imageContainer.is('.removed') || (dialogElement && dialogElement.is(':visible'))) { - return; - } - this.element.find('[data-role=dialog]').trigger('close'); - - if (!dialogElement && this.dialogTmpl) { - var $template = this.dialogTmpl({ - data: imageData - }), - imageCountInRow = 5; - - dialogElement = $($template); - - dialogElement - .data('imageContainer', $imageContainer) - .on('open', $.proxy(function (event) { - var imagesList = this.element.find(this.options.imageSelector + ':not(.removed), .image-placeholder'); - var index = imagesList.index($imageContainer); - var positionIndex = Math.floor(index / imageCountInRow + 1) * imageCountInRow - 1; - if (positionIndex > imagesList.length - 1) { - positionIndex = imagesList.length - 1; - } - var afterElement = imagesList.get(positionIndex); - - $(event.target) - .insertAfter(afterElement) - .slideDown(400); - - $(event.target) - .find('[data-role=type-selector]') - .each($.proxy(function (index, checkbox) { - var $checkbox = $(checkbox), - parent = $checkbox.closest('.item'), - selectedClass = 'selected', - isChecked = this.options.types[$checkbox.val()].value == imageData.file; - $checkbox.prop( - 'checked', - isChecked - ); - parent.toggleClass(selectedClass, isChecked); - }, this)); - this._setImagePointerPosition($imageContainer, dialogElement); - - }, this)) - .on('close', $.proxy(function (event) { - $imageContainer.removeClass('active'); - $(event.target) - .slideUp(400); - }, this)); - - $imageContainer.data('dialog', dialogElement); - } - if (dialogElement) { - dialogElement.trigger('open'); - } + dialogElement.on('change', '[data-role=type-selector]', function () { + var parent = $(this).closest('.item'), + selectedClass = 'selected'; + parent.toggleClass(selectedClass, $(this).prop('checked')); + }); + dialogElement.on('change', '[data-role=type-selector]', $.proxy(this._changeType, this)); + dialogElement.on('change', '[data-role=visibility-trigger]', $.proxy(function(e) { + this._changeVisibility(e, imageData); + }, this)); + dialogElement.on('change', '#image-description', _changeDescription); + dialogElement.modal('openModal'); }, /** @@ -396,11 +387,13 @@ define([ * @param event * @private */ - _changeVisibility: function (event) { + _changeVisibility: function (event, imageData) { var $checkbox = $(event.currentTarget); var $imageContainer = $checkbox.closest('[data-role=dialog]').data('imageContainer'); $imageContainer.toggleClass('hidden-for-front', $checkbox.is(':checked')); - $imageContainer.find('[name*="disabled"]').val($checkbox.is(':checked') ? 1 : 0); + var checked = $checkbox.is(':checked') ? 1 : 0; + $imageContainer.find('[name*="disabled"]').val(checked); + imageData.disabled = checked; }, /** diff --git a/app/code/Magento/Catalog/view/adminhtml/web/product/product.css b/app/code/Magento/Catalog/view/adminhtml/web/product/product.css index d425b8d20ac8f..395f4d87817f7 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/product/product.css +++ b/app/code/Magento/Catalog/view/adminhtml/web/product/product.css @@ -110,7 +110,7 @@ position: absolute; left: 6px; bottom: 6px; - z-index: 3; + z-index: 10; } .admin__scope-old .image .action-delete:before { @@ -153,15 +153,11 @@ /* Gallery image panel */ .admin__scope-old .image-panel { - display: none; position: relative; top: 5px; clear: both; background: #fff; - margin: 0 -2px 15px; padding: 20px 15px; - box-shadow: 0 1px 3px #aaa inset; - border-bottom: 1px solid #cfd0cb; } .admin__scope-old .image .file-row { diff --git a/app/code/Magento/Catalog/view/frontend/web/js/product/list/toolbar.js b/app/code/Magento/Catalog/view/frontend/web/js/product/list/toolbar.js index 0aaf2989a8757..688f836fb1035 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/product/list/toolbar.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/product/list/toolbar.js @@ -4,10 +4,9 @@ */ define([ "jquery", - "jquery/ui", - "mage/dataPost", - "jquery/jquery.cookie" -], function($){ + "jquery/ui" + +], function($) { /** * ProductListToolbarForm Widget - this widget is setting cookie and submitting form according to toolbar controls */ @@ -18,47 +17,68 @@ define([ directionControl: '[data-role="direction-switcher"]', orderControl: '[data-role="sorter"]', limitControl: '[data-role="limiter"]', - modeCookie: 'product_list_mode', - directionCookie: 'product_list_dir', - orderCookie: 'product_list_order', - limitCookie: 'product_list_limit', - postData: {} + mode: 'product_list_mode', + direction: 'product_list_dir', + order: 'product_list_order', + limit: 'product_list_limit', + modeDefault: 'grid', + directionDefault: 'asc', + orderDefault: 'position', + limitDefault: '9', + url: '' }, - _create: function() { - this._bind($(this.options.modeControl), this.options.modeCookie); - this._bind($(this.options.directionControl), this.options.directionCookie); - this._bind($(this.options.orderControl), this.options.orderCookie); - this._bind($(this.options.limitControl), this.options.limitCookie); + _create: function () { + this._bind($(this.options.modeControl), this.options.mode, this.options.modeDefault); + this._bind($(this.options.directionControl), this.options.direction, this.options.directionDefault); + this._bind($(this.options.orderControl), this.options.order, this.options.orderDefault); + this._bind($(this.options.limitControl), this.options.limit, this.options.limitDefault); }, - _bind: function(element, cookieValue) { + _bind: function (element, paramName, defaultValue) { if (element.is("select")) { - element.on('change', {cookieName: cookieValue}, $.proxy(this._processSelect, this)); + element.on('change', {paramName: paramName, default: defaultValue}, $.proxy(this._processSelect, this)); } else { - element.on('click', {cookieName: cookieValue}, $.proxy(this._processLink, this)); + element.on('click', {paramName: paramName, default: defaultValue}, $.proxy(this._processLink, this)); } }, - _processLink: function(event) { + _processLink: function (event) { event.preventDefault(); - this._setCookie(event.data.cookieName, $(event.currentTarget).data('value')); - $.mage.dataPost().postData(this.options.postData); + this.changeUrl( + event.data.paramName, + $(event.currentTarget).data('value'), + event.data.default + ); }, - _processSelect: function(event) { - this._setCookie( - event.data.cookieName, - event.currentTarget.options[event.currentTarget.selectedIndex].value + _processSelect: function (event) { + this.changeUrl( + event.data.paramName, + event.currentTarget.options[event.currentTarget.selectedIndex].value, + event.data.default ); - $.mage.dataPost().postData(this.options.postData); }, - _setCookie: function(cookieName, cookieValue) { - $.cookie(cookieName, cookieValue, {path: '/'}); + changeUrl: function (paramName, paramValue, defaultValue) { + var urlPaths = this.options.url.split('?'), + baseUrl = urlPaths[0], + urlParams = urlPaths[1] ? urlPaths[1].split('&') : [], + paramData = {}, + parameters; + for (var i = 0; i < urlParams.length; i++) { + parameters = urlParams[i].split('='); + paramData[parameters[0]] = parameters[1] !== undefined ? parameters[1] : ''; + } + paramData[paramName] = paramValue; + if (paramValue == defaultValue) { + delete paramData[paramName]; + } + paramData = $.param(paramData); + + location.href = baseUrl + (paramData.length ? '?' + paramData : ''); } }); - return $.mage.productListToolbarForm; }); \ No newline at end of file diff --git a/app/code/Magento/CatalogImportExport/i18n/zh_CN.csv b/app/code/Magento/CatalogImportExport/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/CatalogImportExport/i18n/zh_CN.csv rename to app/code/Magento/CatalogImportExport/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/CatalogInventory/i18n/zh_CN.csv b/app/code/Magento/CatalogInventory/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/CatalogInventory/i18n/zh_CN.csv rename to app/code/Magento/CatalogInventory/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/CatalogRule/i18n/zh_CN.csv b/app/code/Magento/CatalogRule/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/CatalogRule/i18n/zh_CN.csv rename to app/code/Magento/CatalogRule/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/CatalogRuleConfigurable/etc/crontab/di.xml b/app/code/Magento/CatalogRuleConfigurable/etc/crontab/di.xml new file mode 100644 index 0000000000000..051dd103f5d62 --- /dev/null +++ b/app/code/Magento/CatalogRuleConfigurable/etc/crontab/di.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/app/code/Magento/CatalogSearch/i18n/zh_CN.csv b/app/code/Magento/CatalogSearch/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/CatalogSearch/i18n/zh_CN.csv rename to app/code/Magento/CatalogSearch/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Checkout/etc/frontend/sections.xml b/app/code/Magento/Checkout/etc/frontend/sections.xml index 694fe535c74e7..9cf51d9dcc73e 100644 --- a/app/code/Magento/Checkout/etc/frontend/sections.xml +++ b/app/code/Magento/Checkout/etc/frontend/sections.xml @@ -31,6 +31,7 @@
+
@@ -38,9 +39,6 @@
- -
-
diff --git a/app/code/Magento/Checkout/i18n/zh_CN.csv b/app/code/Magento/Checkout/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Checkout/i18n/zh_CN.csv rename to app/code/Magento/Checkout/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/CheckoutAgreements/i18n/zh_CN.csv b/app/code/Magento/CheckoutAgreements/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/CheckoutAgreements/i18n/zh_CN.csv rename to app/code/Magento/CheckoutAgreements/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php index fdc87499f58ae..e50be29ce1130 100644 --- a/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php +++ b/app/code/Magento/Cms/Test/Unit/Ui/Component/Listing/Column/PageActionsTest.php @@ -81,7 +81,7 @@ public function testPrepareItemsByPageId() ); $model->setName($name); - $model->prepareDataSource($items); + $items = $model->prepareDataSource($items); // Run test $this->assertEquals($expectedItems, $items['data']['items']); } diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php index 617af42cb6122..68fbae8de5de0 100644 --- a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php @@ -55,9 +55,9 @@ public function __construct( * Prepare Data Source * * @param array $dataSource - * @return void + * @return array */ - public function prepareDataSource(array & $dataSource) + public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { @@ -98,5 +98,7 @@ public function prepareDataSource(array & $dataSource) } } } + + return $dataSource; } } diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php index 08379991a92b5..589884fc9bc56 100644 --- a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php @@ -59,9 +59,9 @@ public function __construct( * Prepare Data Source * * @param array $dataSource - * @return void + * @return array */ - public function prepareDataSource(array & $dataSource) + public function prepareDataSource(array $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { @@ -92,5 +92,7 @@ public function prepareDataSource(array & $dataSource) } } } + + return $dataSource; } } diff --git a/app/code/Magento/Cms/i18n/zh_CN.csv b/app/code/Magento/Cms/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Cms/i18n/zh_CN.csv rename to app/code/Magento/Cms/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/Config/i18n/zh_CN.csv b/app/code/Magento/Config/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/Config/i18n/zh_CN.csv rename to app/code/Magento/Config/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php b/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php index 66e05cf340d40..78409ad6cc9c9 100644 --- a/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php +++ b/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php @@ -20,4 +20,12 @@ interface ConfigurableProductManagementInterface * @return \Magento\Catalog\Api\Data\ProductInterface[] */ public function generateVariation(\Magento\Catalog\Api\Data\ProductInterface $product, $options); + + /** + * Provide the number of product count + * + * @param null|int $status + * @return int + */ + public function getCount($status = null); } diff --git a/app/code/Magento/ConfigurableProduct/Model/ConfigurableProductManagement.php b/app/code/Magento/ConfigurableProduct/Model/ConfigurableProductManagement.php index 62e4262591d8d..7406d4961acdf 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ConfigurableProductManagement.php +++ b/app/code/Magento/ConfigurableProduct/Model/ConfigurableProductManagement.php @@ -4,9 +4,13 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\ConfigurableProduct\Model; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; +use Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\CollectionFactory; + class ConfigurableProductManagement implements \Magento\ConfigurableProduct\Api\ConfigurableProductManagementInterface { /** @@ -19,28 +23,54 @@ class ConfigurableProductManagement implements \Magento\ConfigurableProduct\Api\ */ private $productVariationBuilder; + /** + * @var CollectionFactory + */ + protected $productsFactory; + /** * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository * @param ProductVariationsBuilder $productVariationBuilder + * @param CollectionFactory $productsFactory */ public function __construct( \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository, - ProductVariationsBuilder $productVariationBuilder + ProductVariationsBuilder $productVariationBuilder, + CollectionFactory $productsFactory ) { $this->attributeRepository = $attributeRepository; $this->productVariationBuilder = $productVariationBuilder; + $this->productsFactory = $productsFactory; } /** * {@inheritdoc} */ - public function generateVariation(\Magento\Catalog\Api\Data\ProductInterface $product, $options) + public function generateVariation(ProductInterface $product, $options) { $attributes = $this->getAttributesForMatrix($options); $products = $this->productVariationBuilder->create($product, $attributes); return $products; } + /** + * {@inheritdoc} + */ + public function getCount($status = null) + { + $products = $this->productsFactory->create(); + /** @var \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\Collection $products */ + switch ($status) { + case Status::STATUS_ENABLED: + $products->addAttributeToFilter('status', Status::STATUS_ENABLED); + break; + case Status::STATUS_DISABLED: + $products->addAttributeToFilter('status', Status::STATUS_DISABLED); + break; + } + return $products->getSize(); + } + /** * Prepare attribute info for variation matrix generation * diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableProductManagementTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableProductManagementTest.php index 0042ca9fc9b6b..380e5736d1d11 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableProductManagementTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/ConfigurableProductManagementTest.php @@ -6,6 +6,9 @@ namespace Magento\ConfigurableProduct\Test\Unit\Model; +use Magento\ConfigurableProduct\Model\ConfigurableProductManagement; +use Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\CollectionFactory; + class ConfigurableProductManagementTest extends \PHPUnit_Framework_TestCase { /** @@ -14,12 +17,12 @@ class ConfigurableProductManagementTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $attributeRepository; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\ConfigurableProduct\Model\ProductVariationsBuilder|\PHPUnit_Framework_MockObject_MockObject */ protected $productVariationBuilder; @@ -33,6 +36,11 @@ class ConfigurableProductManagementTest extends \PHPUnit_Framework_TestCase */ protected $option; + /** + * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productsFactoryMock; + protected function setUp() { $this->attributeRepository = $this->getMock('\Magento\Catalog\Api\ProductAttributeRepositoryInterface'); @@ -51,8 +59,19 @@ protected function setUp() '', false ); + $this->productsFactoryMock = $this->getMock( + '\Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\CollectionFactory', + ['create'], + [], + '', + false + ); - $this->model = new \Magento\ConfigurableProduct\Model\ConfigurableProductManagement($this->attributeRepository, $this->productVariationBuilder); + $this->model = new ConfigurableProductManagement( + $this->attributeRepository, + $this->productVariationBuilder, + $this->productsFactoryMock + ); } public function testGenerateVariation() @@ -86,4 +105,66 @@ public function testGenerateVariation() $expected = ['someObject']; $this->assertEquals($expected, $this->model->generateVariation($this->product, [$this->option])); } + + public function testGetEnabledCount() + { + $statusEnabled = 1; + $productsMock = $this->getMock( + 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\Collection', + [], + [], + '', + false + ); + + $this->productsFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($productsMock); + $productsMock + ->expects($this->once()) + ->method('addAttributeToFilter') + ->with('status', $statusEnabled) + ->willReturnSelf(); + $productsMock + ->expects($this->once()) + ->method('getSize') + ->willReturn('expected'); + + $this->assertEquals( + 'expected', + $this->model->getCount($statusEnabled) + ); + } + + public function testGetDisabledCount() + { + $statusDisabled = 2; + $productsMock = $this->getMock( + 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Product\Collection', + [], + [], + '', + false + ); + + $this->productsFactoryMock + ->expects($this->once()) + ->method('create') + ->willReturn($productsMock); + $productsMock + ->expects($this->once()) + ->method('addAttributeToFilter') + ->with('status', $statusDisabled) + ->willReturnSelf(); + $productsMock + ->expects($this->once()) + ->method('getSize') + ->willReturn('expected'); + + $this->assertEquals( + 'expected', + $this->model->getCount($statusDisabled) + ); + } } diff --git a/app/code/Magento/ConfigurableProduct/i18n/zh_CN.csv b/app/code/Magento/ConfigurableProduct/i18n/zh_Hans_CN.csv similarity index 100% rename from app/code/Magento/ConfigurableProduct/i18n/zh_CN.csv rename to app/code/Magento/ConfigurableProduct/i18n/zh_Hans_CN.csv diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml index f5951e3cd280d..b71eadea02864 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml @@ -18,7 +18,7 @@
- +
+
diff --git a/app/code/Magento/ProductVideo/view/adminhtml/templates/product/edit/base_image.phtml b/app/code/Magento/ProductVideo/view/adminhtml/templates/product/edit/base_image.phtml index 6fc06b824b269..54a09f5792da7 100644 --- a/app/code/Magento/ProductVideo/view/adminhtml/templates/product/edit/base_image.phtml +++ b/app/code/Magento/ProductVideo/view/adminhtml/templates/product/edit/base_image.phtml @@ -4,30 +4,30 @@ * See COPYING.txt for license details. */ ?> -
-
- - -

-
-
+
+
+
+
+
+ + +

+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/css/productvideo.css b/app/code/Magento/ProductVideo/view/adminhtml/web/css/productvideo.css index 7861103573d2d..e2aa3047a6892 100755 --- a/app/code/Magento/ProductVideo/view/adminhtml/web/css/productvideo.css +++ b/app/code/Magento/ProductVideo/view/adminhtml/web/css/productvideo.css @@ -1,4 +1,4 @@ -/** + /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ @@ -8,110 +8,254 @@ text-decoration: none; } -.image.video-placeholder { - background-color: #fff; - font-size: 4rem; - line-height: inherit; - color: #ccc; - overflow: hidden; - speak: none; - font-weight: normal; - -webkit-font-smoothing: antialiased; - display: inline-block; - vertical-align: middle; - text-align: center; - position: relative; -} .image.video-placeholder:before { - background: url(../images/gallery-sprite.png) no-repeat left bottom; - content: ''; - position: absolute; - height: 49px; - width: 49px; - left: 50%; - top: 18px; - margin-left: -24px; - opacity: 0.7; -} -#add_video_button { - background: rgba(0,0,0,0); - width: 100%; - height: 100%; - border: 0; - z-index: 5; - position: relative; + background: url(../images/gallery-sprite.png) no-repeat left bottom; + content: ''; + position: absolute; + height: 49px; + width: 49px; + left: 50%; + top: 18px; + margin-left: -24px; + opacity: 0.7; + z-index: 1; } + .video-placeholder .image-placeholder-text { - font-weight: 400; + font-weight: 400; } -.admin__field.field-video_base_image .admin__field-control, + +.admin__field.field-video_image .admin__field-control, .admin__field.field-video_small_image .admin__field-control, -.admin__field.field-video_thumb_image .admin__field-control, +.admin__field.field-video_thumbnail .admin__field-control, .admin__field.field-video_swatch_image .admin__field-control, .admin__field.field-new_video_disabled .admin__field-control { - width: 82px; - margin-left: calc( (100%) * .33333333 - 30px ); + width: 82px; + margin-left: calc((100%) * .33333333 - 30px); } -.admin__field.field-video_base_image .admin__field-control input, + +.admin__field.field-video_image .admin__field-control input, .admin__field.field-video_small_image .admin__field-control input, -.admin__field.field-video_thumb_image .admin__field-control input, +.admin__field.field-video_thumbnail .admin__field-control input, .admin__field.field-video_swatch_image .admin__field-control input, .admin__field.field-new_video_disabled .admin__field-control input { - float: right; + float: right; } -.admin__field.field-video_base_image .admin__field-label, + +.admin__field.field-video_image .admin__field-label, .admin__field.field-video_small_image .admin__field-label, -.admin__field.field-video_thumb_image .admin__field-label, +.admin__field.field-video_thumbnail .admin__field-label, .admin__field.field-video_swatch_image .admin__field-label, .admin__field.field-new_video_disabled .admin__field-label { - width: 200px; - position: absolute; - margin-left: calc( (100%) * .33333333 - 30px + 90px ); + width: 200px; + position: absolute; + margin-left: calc((100%) * .33333333 - 30px + 90px); + left: 0px; +} + +.admin__field.field-video_image .admin__field-label:before, +.admin__field.field-video_small_image .admin__field-label:before, +.admin__field.field-video_thumbnail .admin__field-label:before, +.admin__field.field-video_swatch_image .admin__field-label:before, +.admin__field.field-new_video_disabled .admin__field-label:before { + content: none; } -.admin__field.field-video_base_image .admin__field-label span, + +.admin__field.field-video_image .admin__field-label span, .admin__field.field-video_small_image .admin__field-label span, -.admin__field.field-video_thumb_image .admin__field-label span, +.admin__field.field-video_thumbnail .admin__field-label span, .admin__field.field-video_swatch_image .admin__field-label span, .admin__field.field-new_video_disabled .admin__field-label span { - float: left; + float: left; } -.admin__field.field-video_base_image, + +.admin__field.field-video_image, .admin__field.field-video_small_image, -.admin__field.field-video_thumb_image, +.admin__field.field-video_thumbnail, .admin__field.field-video_swatch_image { - margin-bottom: 20px !important; + margin-bottom: 20px !important; } + .admin__field.field-new_video_disabled { - margin-top: 32px !important; + margin-top: 32px !important; } -.admin__field.field-video_base_image .admin__field-control { - position: relative; + +.admin__field.field-video_image .admin__field-control { + position: relative; } -.admin__field.field-video_base_image .admin__field-control:after { - content: 'Role'; - position: absolute; - color: #000; - width: 34px; - height: 20px; - left: 1px; - top: -2px; - font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-size: 1.4rem; - font-weight: 600; + +.admin__field.field-video_image .admin__field-control:after { + content: 'Role'; + position: absolute; + color: #000; + width: 34px; + height: 20px; + left: 1px; + top: -2px; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 1.4rem; + font-weight: 600; } .preview_hidden_image_input_button { display: none; } + .video-item { - position: relative; + position: relative; } + .video-item:after { - content: ''; - position: absolute; - bottom: 0; - right: 9px; - background: url(../images/gallery-sprite.png) bottom left; - width: 49px; - height: 40px; -} \ No newline at end of file + content: ''; + position: absolute; + bottom: 0; + right: 0; + background: url(../images/gallery-sprite.png) bottom left; + width: 49px; + height: 40px; + z-index: 3; + left: 0; + top: 10px; + margin: auto; +} + +.mage-new-video-dialog #new_video_form { + width: 65%; + float: left; +} + +.mage-new-video-dialog #video-player-preview-location { + width: 34.99999%; + float: left; +} + +.video-player-container { + width: 100%; + height: 20vw; + margin-bottom: 30px; + border: 1px solid #e3e3e3; + position: relative; +} + +.video-player-container:after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + width: 93px; + height: 60px; + background: url(../images/camera.png) no-repeat center; + z-index: 1; +} + +.video-information { + margin-bottom: 7px; + display: none; +} + +.video-information:after { + content: " "; /* Older browser do not support empty content */ + visibility: hidden; + display: block; + height: 0; + clear: both; +} + +.video-information label { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 1.4rem; + font-weight: 600; + display: block; + width: 25%; + float: left; + text-align: right; +} + +.video-information span { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 1.4rem; + font-weight: 300; + display: block; + width: 74.9999%; + float: left; + padding-left: 20px; +} + +.product-video { + width: 100%; + z-index: 20; + height: 100%; + position: relative; +} + +.image.video-placeholder > button[data-role="add-video-button"], +.image.video-placeholder > button { + width: 100%; + height: 100%; + border: 0; + background: transparent; + z-index: 10; + position: relative; +} + +.add-video-button-container { + float: right; + margin-bottom: 10px; +} + +.admin__field.field.field-new_video_screenshot { + margin-bottom: 5px; +} + +.admin__field.field.field-new_video_screenshot_preview { + margin-bottom: 50px; +} + +.image .action-make-base:after { + -webkit-font-smoothing: antialiased; + font-size: 1.8rem; + line-height: inherit; + color: #9e9e9e; + content: '\e63b'; + font-family: 'Admin Icons'; + vertical-align: middle; + display: inline-block; + font-weight: normal; + overflow: hidden; + speak: none; + text-align: center; + position: absolute; + top: -7px; + left: -4px; +} + +.image .action-make-base:hover:after { + color: #7d7d7d; +} + +.admin__scope-old .gallery .image .action-make-base { + border: 0; + width: 0; + height: 0; + position: absolute; + margin: 0; + bottom: 9px; + right: 9px; + left: auto; + background: transparent; +} + +.image .action-make-base span { + display: none; +} + +.admin__scope-old .base-image .image-label { + display: block; +} + +.image.base-image:hover .image-label { + display: none; +} diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/images/camera.png b/app/code/Magento/ProductVideo/view/adminhtml/web/images/camera.png new file mode 100644 index 0000000000000..468f922ecb12d Binary files /dev/null and b/app/code/Magento/ProductVideo/view/adminhtml/web/images/camera.png differ diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js b/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js new file mode 100644 index 0000000000000..d692aaf4eccf6 --- /dev/null +++ b/app/code/Magento/ProductVideo/view/adminhtml/web/js/get-video-information.js @@ -0,0 +1,534 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +require([ + 'jquery', + 'Magento_Ui/js/modal/alert', + 'jquery/ui' + ], + function ($, alert) { + 'use strict'; + + var videoRegister = { + _register: {}, + + /** + * Checks, if api is already registered + * + * @param {String} api + * @returns {bool} + */ + isRegistered: function (api) { + return this._register[api] !== undefined; + }, + + /** + * Checks, if api is loaded + * + * @param {String} api + * @returns {bool} + */ + isLoaded: function (api) { + return this._register[api] !== undefined && this._register[api] === true; + }, + + /** + * Register new video api + * @param {String} api + * @param {bool} loaded + */ + register: function (api, loaded) { + loaded = loaded || false; + this._register[api] = loaded; + } + }; + + $.widget('mage.productVideoLoader', { + + /** + * @private + */ + _create: function () { + switch (this.element.data('type')) { + case 'youtube': + this.element.videoYoutube(); + this._player = this.element.data('mageVideoYoutube'); + break; + + case 'vimeo': + this.element.videoVimeo(); + this._player = this.element.data('mageVideoVimeo'); + break; + default: + throw { + name: 'Video Error', + message: 'Unknown video type', + + /** + * Return string + */ + toString: function () { + return this.name + ': ' + this.message; + } + }; + } + }, + + /** + * Initializes variables + * @private + */ + _initialize: function () { + this._params = this.element.data('params') || {}; + this._code = this.element.data('code'); + this._width = this.element.data('width'); + this._height = this.element.data('height'); + this._autoplay = !!this.element.data('autoplay'); + this._playing = this._autoplay || false; + + this._responsive = this.element.data('responsive') !== false; + + if (this._responsive === true) { + this.element.addClass('responsive'); + } + + this._calculateRatio(); + }, + + /** + * Abstract play command + */ + play: function () { + this._player.play(); + }, + + /** + * Abstract pause command + */ + pause: function () { + this._player.pause(); + }, + + /** + * Abstract stop command + */ + stop: function () { + this._player.stop(); + }, + + /** + * Abstract playing command + */ + playing: function () { + return this._player.playing(); + }, + + /** + * Abstract destroying command + */ + destroy: function () { + this._player.destroy(); + }, + + /** + * Calculates ratio for responsive videos + * @private + */ + _calculateRatio: function () { + if (!this._responsive) { + return; + } + this.element.css('paddingBottom', this._height / this._width * 100 + '%'); + } + }); + + $.widget('mage.videoYoutube', $.mage.productVideoLoader, { + + /** + * Initialization of the Youtube widget + * @private + */ + _create: function () { + var self = this; + + this._initialize(); + + this.element.append('
'); + + this._on(window, { + + /** + * Youtube state check + * @private + */ + 'youtubeapiready': function () { + if (self._player !== undefined) { + return; + } + + if (self._autoplay) { + self._params.autoplay = 1; + } + self._params.rel = 0; + + self._player = new window.YT.Player(self.element.children(':first')[0], { + height: self._height, + width: self._width, + videoId: self._code, + playerVars: self._params, + events: { + + /** + * @private + */ + 'onReady': function onPlayerReady() { + self._player.getDuration(); + }, + + /** + * State change flag init + */ + onStateChange: function (data) { + switch (window.parseInt(data.data, 10)) { + case 1: + self._playing = true; + break; + default: + self._playing = false; + break; + } + + self._trigger('statechange', {}, data); + } + } + + }); + } + }); + + this._loadApi(); + }, + + /** + * Loads Youtube API and triggers event, when loaded + * @private + */ + _loadApi: function () { + var element, + scriptTag; + + if (videoRegister.isRegistered('youtube')) { + if (videoRegister.isLoaded('youtube')) { + $(window).trigger('youtubeapiready'); + } + + return; + } + videoRegister.register('youtube'); + + element = document.createElement('script'); + scriptTag = document.getElementsByTagName('script')[0]; + + element.async = true; + element.src = 'https://www.youtube.com/iframe_api'; + scriptTag.parentNode.insertBefore(element, scriptTag); + + /** + * Trigger youtube api ready event + */ + window.onYouTubeIframeAPIReady = function () { + $(window).trigger('youtubeapiready'); + videoRegister.register('youtube', true); + }; + }, + + /** + * Play command for Youtube + */ + play: function () { + this._player.playVideo(); + this._playing = true; + }, + + /** + * Pause command for Youtube + */ + pause: function () { + this._player.pauseVideo(); + this._playing = false; + }, + + /** + * Stop command for Youtube + */ + stop: function () { + this._player.stopVideo(); + this._playing = false; + }, + + /** + * Playing command for Youtube + */ + playing: function () { + return this._playing; + }, + + /** + * stops and unloads player + * @private + */ + destroy: function () { + this.stop(); + this._player.destroy(); + } + }); + + $.widget('mage.videoVimeo', $.mage.productVideoLoader, { + + /** + * Initialize the Vimeo widget + * @private + */ + _create: function () { + var timestamp, + src, + additionalParams; + + this._initialize(); + timestamp = new Date().getTime(); + + if (this._autoplay) { + additionalParams += '&autoplay=1'; + } + + src = 'http://player.vimeo.com/video/' + + this._code + '?api=1&player_id=vimeo' + + this._code + + timestamp + + additionalParams; + this.element.append( + $('