diff --git a/Astrio/Task529/Block/CustomBlock.php b/Astrio/Task529/Block/CustomBlock.php new file mode 100644 index 0000000000000000000000000000000000000000..f8d67c90cdd077596a15d4cae1eb5792c051ba7b --- /dev/null +++ b/Astrio/Task529/Block/CustomBlock.php @@ -0,0 +1,103 @@ +<?php +namespace Astrio\Task529\Block; + + +/** + * Class Test + * @package Astrio\KnockoutJs\Block + */ +class CustomBlock extends \Magento\Framework\View\Element\Template +{ + /** @var array|\Magento\Checkout\Block\Checkout\LayoutProcessorInterface[] */ + protected $layoutProcessors; + + + /** @var \Magento\Framework\Serialize\Serializer\Json */ + protected $serializer; + + + /** @var array|mixed */ + protected $jsLayout; + + /** + * @var \Magento\Catalog\Model\ResourceModel\Category\Collection + */ + protected $categoryCollection; + + /** + * @var \Magento\Catalog\Model\Category + */ + protected $categoryObject; + + /** + * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory + */ + protected $productCollectionFactory; + + /** + * @param \Magento\Framework\View\Element\Template\Context $context + * @param \Magento\Framework\Serialize\Serializer\Json $serializer + * @param array $layoutProcessors + * @param array $data + * @param \Magento\Catalog\Model\Category $categoryObject + * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory + */ + public function __construct( + \Magento\Framework\View\Element\Template\Context $context, + \Magento\Framework\Serialize\Serializer\Json $serializer, + array $layoutProcessors = [], + array $data = [], + \Magento\Catalog\Model\ResourceModel\Category\Collection $categoryCollection, + \Magento\Catalog\Model\Category $categoryObject, + \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory + ) { + parent::__construct($context, $data); + $this->jsLayout = isset($data['jsLayout']) && is_array($data['jsLayout']) ? + + $data['jsLayout'] : []; + $this->layoutProcessors = $layoutProcessors; + $this->serializer = $serializer; + $this->categoryCollection = $categoryCollection; + $this->categoryObject = $categoryObject; + $this->productCollectionFactory = $productCollectionFactory; + } + + + /** @return string */ + public function getJsLayout() + { + foreach ($this->layoutProcessors as $processor) { + $this->jsLayout = $processor->process($this->jsLayout); + } + return $this->serializer->serialize($this->jsLayout); + } + + /** + * @return array + */ + public function getCategories() + { + $productsCollection = $this->productCollectionFactory->create() + ->addAttributeToFilter('is_collection', '1') + ->load(); + + $categories = []; + foreach ($productsCollection as $product) { + if ($product->getCategoryIds()) { + $categories = array_merge($categories, $product->getCategoryIds()); + } + } + + $categories = array_unique($categories); + $resultCategoriesArray = []; + + $this->categoryCollection->addAttributeToSelect(['entity_id', 'name']) + ->addAttributeToFilter('entity_id', ['in' => $categories]); + $this->categoryCollection->load(); + + foreach ($this->categoryCollection as $category) { + $resultCategoriesArray[] = array('value' => $category->getId(), 'name' => $category->getName()); + } + return $resultCategoriesArray; + } +} diff --git a/Astrio/Task529/Controller/Ajax/Products.php b/Astrio/Task529/Controller/Ajax/Products.php new file mode 100644 index 0000000000000000000000000000000000000000..1b49f01ee5610d01b9797badce811b1b54521cb6 --- /dev/null +++ b/Astrio/Task529/Controller/Ajax/Products.php @@ -0,0 +1,97 @@ +<?php +namespace Astrio\Task529\Controller\Ajax; + + +/** + * Class Product + * @package Astrio\KnockoutJs\Controller\Module9 + */ +class Products extends \Magento\Framework\App\Action\Action +{ + /** + * @var \Magento\Customer\Model\Session + */ + protected $customerSession; + + /** + * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory + */ + protected $productCollectionFactory; + + /** + * @var \Magento\Catalog\Helper\Image + */ + protected $helperImport; + + /** + * @param \Magento\Framework\App\Action\Context $context + * @param \Magento\Customer\Model\Session $customerSession + * @param \Magento\Framework\Controller\ResultFactory $resultFactory + * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory + * @param \Magento\Catalog\Helper\Image $helperImport + */ + public function __construct( + \Magento\Framework\App\Action\Context $context, + \Magento\Customer\Model\Session $customerSession, + \Magento\Framework\Controller\ResultFactory $resultFactory, + \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory, + \Magento\Catalog\Helper\Image $helperImport + ) { + parent::__construct($context); + $this->customerSession = $customerSession; + $this->resultFactory = $resultFactory; + $this->productCollectionFactory = $productCollectionFactory; + $this->helperImport = $helperImport; + } + + /** + * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface + */ + public function execute() + { + $params = $this->getRequest()->getParams(); + + $productsCollection = $this->productCollectionFactory->create() + ->addAttributeToSelect(['name', 'description', 'price', 'small_image', 'is_collection']) + ->addAttributeToFilter('is_collection', '1') + ->addCategoriesFilter(['in' => $params['categoryid']]); + + if (isset($params['sortby'])) { + switch ($params['sortby']) { + case 'asc_price': + $productsCollection->addAttributeToSort('price', 'ASC'); + break; + case 'desc_price': + $productsCollection->addAttributeToSort('price', 'DESC'); + break; + case 'asc_name': + $productsCollection->addAttributeToSort('name', 'ASC'); + break; + case 'desc_name': + $productsCollection->addAttributeToSort('name', 'DESC'); + break; + } + } + + + $productsCollection->load(); + + $productsArray = []; + foreach ($productsCollection as $product) { + $productsArray[] = [ + 'name' => $product->getName(), + 'description' => $product->getDescription(), + 'price' => $product->getPrice(), + 'image' => $this->helperImport->init($product, 'product_page_image_small') + ->setImageFile($product->getSmallImage()) + ->resize(380) + ->getUrl() + ]; + } + + $resultJson = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_JSON); + $resultJson->setData($productsArray); + return $resultJson; + + } +} diff --git a/Astrio/Task529/Controller/Index/Index.php b/Astrio/Task529/Controller/Index/Index.php new file mode 100644 index 0000000000000000000000000000000000000000..a2543ab61711bb359aaeb6d3521b83bbf563f9b4 --- /dev/null +++ b/Astrio/Task529/Controller/Index/Index.php @@ -0,0 +1,17 @@ +<?php +namespace Astrio\Task529\Controller\Index; + +/** + * + */ +class Index extends \Magento\Framework\App\Action\Action +{ + /** @return \Magento\Framework\View\Result\Page */ + public function execute() + { + /** @var \Magento\Framework\View\Result\Page $resultPage */ + $resultPage = $this->resultFactory + ->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE); + return $resultPage; + } +} diff --git a/Astrio/Task529/Setup/Patch/Data/AddIsCollectionAttribute.php b/Astrio/Task529/Setup/Patch/Data/AddIsCollectionAttribute.php new file mode 100644 index 0000000000000000000000000000000000000000..ca39aabf169880e27c69b4a335e983954fec01fc --- /dev/null +++ b/Astrio/Task529/Setup/Patch/Data/AddIsCollectionAttribute.php @@ -0,0 +1,75 @@ +<?php + +namespace Astrio\Task529\Setup\Patch\Data; + +use Magento\Eav\Setup\EavSetup; +use Magento\Eav\Setup\EavSetupFactory; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\Setup\Patch\DataPatchInterface; + +class AddIsCollectionAttribute implements DataPatchInterface { + /** @var ModuleDataSetupInterface */ + private $moduleDataSetup; + + /** @var EavSetupFactory */ + private $eavSetupFactory; + + /** + * @param ModuleDataSetupInterface $moduleDataSetup + * @param EavSetupFactory $eavSetupFactory + */ + public function __construct( + ModuleDataSetupInterface $moduleDataSetup, + EavSetupFactory $eavSetupFactory + ) { + $this->moduleDataSetup = $moduleDataSetup; + $this->eavSetupFactory = $eavSetupFactory; + } + + /** + * {@inheritdoc} + */ + public function apply() + { + /** @var EavSetup $eavSetup */ + $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]); + + $eavSetup->addAttribute(\Magento\Catalog\Model\Product::ENTITY, 'is_collection', [ + 'group' => 'General', + 'type' => 'int', + 'backend' => '', + 'frontend' => '', + 'input' => 'select', + 'label' => 'Is Collection', + 'source' => \Magento\Catalog\Model\Product\Attribute\Source\Boolean::class, + 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL, + 'visible' => true, + 'required' => false, + 'default' => '0', + 'searchable' => false, + 'filterable' => false, + 'comparable' => false, + 'visible_on_front' => true, + 'used_in_product_listing' => true, + 'unique' => false, + ]); + + } + + /** + * {@inheritdoc} + */ + public static function getDependencies() + { + return []; + } + + /** + * {@inheritdoc} + */ + public function getAliases() + { + return []; + } + +} diff --git a/Astrio/Task529/etc/frontend/routes.xml b/Astrio/Task529/etc/frontend/routes.xml new file mode 100644 index 0000000000000000000000000000000000000000..f95811816375dea55aa0e8bfb6726fc923f449d0 --- /dev/null +++ b/Astrio/Task529/etc/frontend/routes.xml @@ -0,0 +1,7 @@ +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"> + <router id="standard"> + <route id="collection" frontName="collection"> + <module name="Astrio_Task529"/> + </route> + </router> +</config> diff --git a/Astrio/Task529/etc/module.xml b/Astrio/Task529/etc/module.xml new file mode 100644 index 0000000000000000000000000000000000000000..d9bcd142e1ac98ad17767a040918528853085644 --- /dev/null +++ b/Astrio/Task529/etc/module.xml @@ -0,0 +1,3 @@ +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:fraVendor_Modulemework:Module/etc/module.xsd"> + <module name="Astrio_Task529" setup_version = "1.0.0"/> +</config> diff --git a/Astrio/Task529/registration.php b/Astrio/Task529/registration.php new file mode 100644 index 0000000000000000000000000000000000000000..a50cd91e2b0e0c2826710bca4301971c3c92f85a --- /dev/null +++ b/Astrio/Task529/registration.php @@ -0,0 +1,6 @@ +<?php +\Magento\Framework\Component\ComponentRegistrar::register( + \Magento\Framework\Component\ComponentRegistrar::MODULE, + 'Astrio_Task529', + __DIR__ +); diff --git a/Astrio/Task529/view/frontend/layout/collection_index_index.xml b/Astrio/Task529/view/frontend/layout/collection_index_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..6248467c01844714a2c73fe33f6db25c488938bf --- /dev/null +++ b/Astrio/Task529/view/frontend/layout/collection_index_index.xml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> + <head> + <title>Product list</title> + </head> + <body> + <referenceBlock name="content"> + <block class="Astrio\Task529\Block\CustomBlock" name="astrio_product-collection" template="view.phtml"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="product-list" xsi:type="array"> + <item name="component" xsi:type="string">Astrio_Task529/js/view/kocomponent</item> + <item name="displayArea" xsi:type="string">product-list</item> + </item> + </item> + </argument> + </arguments> + </block> + </referenceBlock> + </body> +</page> diff --git a/Astrio/Task529/view/frontend/templates/view.phtml b/Astrio/Task529/view/frontend/templates/view.phtml new file mode 100644 index 0000000000000000000000000000000000000000..7c03ebf1415554c914d5ba7552795c25f11c4c7f --- /dev/null +++ b/Astrio/Task529/view/frontend/templates/view.phtml @@ -0,0 +1,26 @@ +<?php /** @var \Astrio\Task529\Block\CustomBlock $block */ ?> + +<div id="test-div" data-bind="scope:'product-list'"> + + <?php + $categories = $block->getCategories(); + ?> + <span>Select a category</span> + <select id="selectCategory" + data-bind="event: { change: getProducts(document.getElementById('selectCategory').value) }" + name="categories"> + <option value="">--Please choose an option--</option> + <?php foreach ($categories as $category) { ?> + <option value="<?php echo $category['value'] ?>"><?php echo $category['name'] ?></option> + <?php } ?> + </select> + + <!-- ko template: getTemplate() --><!-- /ko --> + <script type="text/x-magento-init"> + { + "#test-div": { + "Magento_Ui/js/core/app": <?= /* @escapeNotVerified */ $block->getJsLayout(); ?> + } + } + </script> +</div> diff --git a/Astrio/Task529/view/frontend/web/js/view/kocomponent.js b/Astrio/Task529/view/frontend/web/js/view/kocomponent.js new file mode 100644 index 0000000000000000000000000000000000000000..3d1ef1783a7bc6756734214a3b932ce8b8df7ba5 --- /dev/null +++ b/Astrio/Task529/view/frontend/web/js/view/kocomponent.js @@ -0,0 +1,38 @@ +define([ + 'ko', + 'uiComponent', + 'mage/url', + 'mage/storage', +], function (ko, Component, urlBuilder, storage) { + 'use strict'; + var id = 1; + return Component.extend({ + defaults: { + template: 'Astrio_Task529/view', + }, + products: ko.observableArray([]), + getProducts: function (categoryId = '', sortBy = '') { + var url = 'collection/ajax/products'; + if (categoryId == '') + return; + else + url += '/categoryid/' + categoryId; + var self = this; + if (sortBy != '') + url += '/sortby/' + sortBy; + var serviceUrl = urlBuilder.build(url); + id++; + return storage.post( + serviceUrl, '' + ).done(function (response) { + self.products.removeAll(); + response.forEach(function(element) { + self.products.push(element); + console.log(element); + }); + }).fail(function (response) { + console.log(response); + }); + }, + }); +}); diff --git a/Astrio/Task529/view/frontend/web/template/view.html b/Astrio/Task529/view/frontend/web/template/view.html new file mode 100644 index 0000000000000000000000000000000000000000..e02376fafad65eef0a2ea998829c551213ae3682 --- /dev/null +++ b/Astrio/Task529/view/frontend/web/template/view.html @@ -0,0 +1,29 @@ +<span>Sort by</span> +<select id="sortBy" data-bind="event: { change: getProducts(document.getElementById('selectCategory').value, + document.getElementById('sortBy').value) + }" name="sortBy"> + <option value="">--Please choose an option--</option> + <option value="asc_price">By price in ascending order</option> + <option value="desc_price">By price in descending order</option> + <option value="asc_name">By name in ascending order</option> + <option value="desc_name">By name in descending order</option> +</select> + +<table> + <thead> + <tr> + <th>Image</th> + <th>Name</th> + <th>Description</th> + <th>Price</th> + </tr> + </thead> + <tbody data-bind="foreach: products"> + <tr> + <td><img data-bind="attr: {src: image}"></td> + <td data-bind="text: name"></td> + <td data-bind="html: description"></td> + <td data-bind="text: price"></td> + </tr> + </tbody> +</table>