├── .gitignore
├── Block
├── Categories.php
├── Cmspage.php
├── System
│ └── Config
│ │ └── Form
│ │ └── Field
│ │ └── Snippet.php
└── Widget
│ └── Categories.php
├── Controller
└── Adminhtml
│ └── Category
│ └── Thumbnail
│ └── Upload.php
├── Helper
└── Data.php
├── Model
├── Category
│ └── Attribute
│ │ └── Backend
│ │ └── Image.php
└── Config
│ ├── Category.php
│ ├── Layout.php
│ ├── SortAttribute.php
│ └── Source
│ ├── Col.php
│ ├── Responsive.php
│ ├── Row.php
│ ├── Status.php
│ └── Truefalse.php
├── README.md
├── Setup
└── InstallData.php
├── composer.json
├── etc
├── acl.xml
├── adminhtml
│ ├── di.xml
│ ├── routes.xml
│ └── system.xml
├── config.xml
├── module.xml
└── widget.xml
├── media
├── Mgento-2-category-4.jpg
├── frontend_category.png
├── frontend_home.png
├── magento-2-categories-10.jpg
├── magento-2-categories-11.jpg
├── magento-2-categories-3.jpg
├── magento-2-categories-5.png
├── magento-2-categories-6.jpg
├── magento-2-categories-7.jpg
├── magento-2-categories-8.jpg
└── magento-2-categories-9.jpg
├── registration.php
└── view
├── adminhtml
└── ui_component
│ └── category_form.xml
└── frontend
├── layout
├── catalog_category_view.xml
└── cms_index_index.xml
├── templates
├── categories.phtml
├── categories_widget.phtml
└── cmspage.phtml
└── web
└── css
└── source
└── _module.less
/.gitignore:
--------------------------------------------------------------------------------
1 | # General
2 | .DS_Store
3 | .AppleDouble
4 | .LSOverride
5 |
6 | # Icon must end with two \r
7 | Icon
8 |
9 | # Thumbnails
10 | ._*
11 |
12 | # Files that might appear in the root of a volume
13 | .DocumentRevisions-V100
14 | .fseventsd
15 | .Spotlight-V100
16 | .TemporaryItems
17 | .Trashes
18 | .VolumeIcon.icns
19 | .com.apple.timemachine.donotpresent
20 |
21 | # Directories potentially created on remote AFP share
22 | .AppleDB
23 | .AppleDesktop
24 | Network Trash Folder
25 | Temporary Items
26 | .apdisk
--------------------------------------------------------------------------------
/Block/Categories.php:
--------------------------------------------------------------------------------
1 | helper->getConfigModule(self::XML_PATH);
50 | //$dataConvert = array('infinite', 'vertical', 'autoplay', 'centerMode');
51 | if($data['slide']){
52 | $data['vertical-Swiping'] = $data['vertical'];
53 | $breakpoints = $this->getResponsiveBreakpoints();
54 | $responsive = '[';
55 | $num = count($breakpoints);
56 | foreach ($breakpoints as $size => $opt) {
57 | $item = (int) $data[$opt];
58 | $responsive .= '{"breakpoint": '.$size.', "settings": {"slidesToShow": '.$item.'}}';
59 | $num--;
60 | if($num) $responsive .= ', ';
61 | }
62 | $responsive .= ']';
63 | $data['slides-To-Show'] = $data['visible'];
64 | $data['autoplay-Speed'] = $data['autoplay_speed'];
65 | $data['swipe-To-Slide'] = 'true';
66 | $data['responsive'] = $responsive;
67 | }
68 |
69 | $this->addData($data);
70 |
71 | parent::_construct();
72 |
73 | }
74 |
75 | public function __construct(
76 | \Magento\Framework\View\Element\Template\Context $context,
77 | \Magento\Framework\Image\AdapterFactory $imageFactory,
78 | \Magento\Framework\Registry $coreRegistry,
79 | \Magento\Catalog\Model\CategoryFactory $categoryFactory,
80 | \Magento\Catalog\Helper\Image $helperImage,
81 | \Magento\Catalog\Helper\Output $catalogHelperOutput,
82 | \Magento\Store\Model\StoreManagerInterface $storeManager,
83 | \Magepow\Categories\Helper\Data $helper,
84 | array $data = []
85 | ) {
86 | $this->storeManager = $storeManager;
87 | $this->coreRegistry = $coreRegistry;
88 | $this->categoryFactory = $categoryFactory;
89 | $this->catalogHelperOutput = $catalogHelperOutput;
90 | $this->helperImage = $helperImage;
91 | $this->_imageFactory = $imageFactory;
92 | $this->_filesystem = $context->getFilesystem();
93 | $this->_directoryPub = $this->_filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::PUB);
94 | $this->helper = $helper;
95 |
96 | parent::__construct($context, $data);
97 |
98 | $this->attributesToSelect = [
99 | 'name',
100 | 'url_key',
101 | 'url_path',
102 | 'image',
103 | 'description'
104 | ];
105 | if($this->isShowThumbnail()) {
106 | $this->attributesToSelect[] = 'magepow_thumbnail';
107 | unset($this->attributesToSelect['image']);
108 | }
109 |
110 | }
111 |
112 | protected function getCacheLifetime()
113 | {
114 | return parent::getCacheLifetime() ?: 86400;
115 | }
116 |
117 | public function getCacheKeyInfo()
118 | {
119 | $keyInfo = parent::getCacheKeyInfo();
120 | $categoryId = $this->getCurrentCategory() ? $this->getCurrentCategory()->getId() : 0;
121 | $keyInfo[] = $categoryId;
122 | return $keyInfo;
123 | }
124 |
125 | /**
126 | * @return array
127 | */
128 | public function getIdentities()
129 | {
130 | $categoryId = $this->getCurrentCategory() ? $this->getCurrentCategory()->getId() : 0;
131 | return [self::DEFAULT_CACHE_TAG, self::DEFAULT_CACHE_TAG . '_' . $categoryId];
132 | }
133 |
134 | public function getLayout()
135 | {
136 | return $this->helper->getConfigModule(self::XML_PATH . '/layout');
137 | }
138 |
139 | public function getHeading()
140 | {
141 | return $this->helper->getConfigModule(self::XML_PATH . '/heading');
142 | }
143 |
144 | public function isShowDescription()
145 | {
146 | return $this->helper->getConfigModule(self::XML_PATH . '/description');
147 | }
148 |
149 | public function isShowThumbnail()
150 | {
151 | return $this->helper->getConfigModule(self::XML_PATH . '/thumbnail');
152 | }
153 |
154 | public function getItemAmount()
155 | {
156 | return $this->helper->getConfigModule(self::XML_PATH . '/item_amount');
157 | }
158 |
159 | public function getSortAttribute()
160 | {
161 | return $this->helper->getConfigModule(self::XML_PATH . '/sort_attribute');
162 | }
163 |
164 | public function getExcludeCategory()
165 | {
166 | return $this->helper->getConfigModule(self::XML_PATH . '/exclude_category');
167 | }
168 |
169 | public function getCurrentCategory()
170 | {
171 | return $this->coreRegistry->registry('current_category');
172 | }
173 |
174 | public function getCategories()
175 | {
176 | $category = $this->getCurrentCategory();
177 | if(!$category) return;
178 |
179 | $categoryId = $category->getId();
180 |
181 | if ($this->isExcluded($categoryId)) return;
182 |
183 | $sortAttribute = $this->getSortAttribute();
184 | $categories = $this->categoryFactory->create()->getCollection()
185 | ->addAttributeToSelect($this->attributesToSelect)
186 | ->addAttributeToFilter('parent_id', $categoryId)
187 | ->addIsActiveFilter();
188 |
189 | if($sortAttribute == "position") {
190 | $categories->addAttributeToSort('level');
191 | }
192 |
193 | $categories->addAttributeToSort($sortAttribute);
194 |
195 | return $categories;
196 | }
197 |
198 | public function getDescription($category)
199 | {
200 | $description = $category->getDescription();
201 | if ($description) {
202 | $categoryDescription = $this->catalogHelperOutput->categoryAttribute($category, $description, 'description');
203 | } else {
204 | $categoryDescription = '';
205 | }
206 | return trim($categoryDescription);
207 | }
208 |
209 | public function getImage($category)
210 | {
211 | if($this->isShowThumbnail()){
212 | $image = ($category->getData('magepow_thumbnail')) ? $category->getData('magepow_thumbnail') : '';
213 | return $this->getImageUrl($image);
214 | }
215 |
216 | return $this->getImageUrl($category);
217 | }
218 |
219 | public function getImageInfo($image)
220 | {
221 | if(is_object($image)){
222 | $img = $this->isShowThumbnail() ? $image->getData('magepow_thumbnail'): $image->getImage();
223 | if(!$img) return $image;
224 | } else {
225 | $img = $image;
226 | }
227 | $_image = $this->_imageFactory->create();
228 | $mediaPath = $this->_directoryPub->getAbsolutePath();
229 | $mediaPath = explode(DIRECTORY_SEPARATOR, $mediaPath);
230 | $img = explode(DIRECTORY_SEPARATOR, $img);
231 | $imagePath = array_unique(array_merge($mediaPath, $img));
232 | $imagePath = implode(DIRECTORY_SEPARATOR, $imagePath);
233 | if(file_exists($imagePath) ){
234 | $_image->open($imagePath);
235 | return $_image;
236 | }
237 | return $image;
238 | }
239 |
240 | public function getImageUrl($image)
241 | {
242 | if(is_object($image)){
243 | $image = $image->getImage();
244 | }
245 | if(strpos($image ?? '', "media/"))$image = strstr($image,'/media');
246 | elseif($image!=NULL){
247 | $image = 'catalog/category/'.$image;
248 | }
249 | $image = str_replace('media/', '', $image ?? '');
250 |
251 | if($image) {
252 | $url = $this->storeManager->getStore()->getBaseUrl( \Magento\Framework\UrlInterface::URL_TYPE_MEDIA ) . $image;
253 | } else {
254 | $url = $this->helperImage->getDefaultPlaceholderUrl('small_image');
255 | }
256 |
257 | return $url;
258 | }
259 |
260 | public function isExcluded($id)
261 | {
262 | $excluded = explode(',', $this->getExcludeCategory() ?? '');
263 | if (!$excluded) return;
264 | return in_array($id, $excluded);
265 | }
266 |
267 | public function getResponsiveBreakpoints()
268 | {
269 | return Responsive::getBreakpoints();
270 | }
271 |
272 | public function getSlideOptions()
273 | {
274 | return array('autoplay', 'arrows', 'autoplay-Speed', 'dots', 'infinite', 'padding', 'vertical', 'vertical-Swiping', 'responsive', 'rows', 'slides-To-Show');
275 | }
276 |
277 | public function getFrontendCfg()
278 | {
279 | if($this->getSlide()) return $this->getSlideOptions();
280 |
281 | $this->addData(array('responsive' =>json_encode($this->getGridOptions())));
282 | return array('padding', 'responsive');
283 |
284 | }
285 |
286 | public function getGridOptions()
287 | {
288 | $options = array();
289 | $breakpoints = $this->getResponsiveBreakpoints(); ksort($breakpoints);
290 | foreach ($breakpoints as $size => $screen) {
291 | $options[]= array($size-1 => $this->getData($screen));
292 | }
293 | return $options;
294 | }
295 |
296 | }
297 |
--------------------------------------------------------------------------------
/Block/Cmspage.php:
--------------------------------------------------------------------------------
1 | helper->getConfigModule(self::XML_PATH . '/layout');
24 | }
25 |
26 | public function getHeading()
27 | {
28 | return $this->helper->getConfigModule(self::XML_PATH . '/heading');
29 | }
30 |
31 | public function isShowDescription()
32 | {
33 | return $this->helper->getConfigModule(self::XML_PATH . '/description');
34 | }
35 |
36 | public function isShowThumbnail()
37 | {
38 | return $this->helper->getConfigModule(self::XML_PATH . '/thumbnail');
39 | }
40 |
41 | public function getItemAmount()
42 | {
43 | return $this->helper->getConfigModule(self::XML_PATH . '/item_amount');
44 | }
45 |
46 | public function getSortAttribute()
47 | {
48 | return $this->helper->getConfigModule(self::XML_PATH . '/sort_attribute');
49 | }
50 |
51 | public function getCategorySelect()
52 | {
53 | return $this->helper->getConfigModule(self::XML_PATH . '/category_select');
54 | }
55 |
56 | public function getCategories()
57 | {
58 | $categoryIds = $this->getCategorySelect();
59 | if(!$categoryIds) return;
60 |
61 | $sortAttribute = $this->getSortAttribute();
62 | $categories = $this->categoryFactory->create()->getCollection()
63 | ->addAttributeToSelect($this->attributesToSelect)
64 | ->addIdFilter($categoryIds)
65 | ->addIsActiveFilter();
66 |
67 | switch ($sortAttribute) {
68 | case 'position':
69 | $categories->addAttributeToSort('level');
70 | $categories->addAttributeToSort($sortAttribute);
71 | break;
72 | case 'custom':
73 | // will sort as per order of Id's set in config value: magepow_categories/home_page/category_select
74 | $categories->getSelect()->order(new \Zend_Db_Expr('FIELD(e.entity_id,' . $categoryIds . ')'));
75 | break;
76 | default:
77 | $categories->addAttributeToSort($sortAttribute);
78 | break;
79 | }
80 |
81 | return $categories;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Block/System/Config/Form/Field/Snippet.php:
--------------------------------------------------------------------------------
1 | _getElementHtml($element);
24 | }
25 |
26 | protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
27 | {
28 | // $html = $element->getElementHtml();
29 | $html = '';
30 | $value = $element->getData('value');
31 | $shortcodeWidget = '{{block class="Magepow\Categories\Block\Widget\Categories" title="Magepow Categories Widget" subtitle="Magepow Categories Widget" template="categories_widget.phtml" sort_attribute="name" description="1" thumbnail="1" item_amount="1" categories="25,11,22,33" slide="1" vertical="false" infinite="true" autoplay="true" arrows="true" dots="false" speed="300" autoplaySpeed="3000" padding="15" rows="1" mobile="1" portrait="1" landscape="2" tablet="3" notebook="3" laptop="4" desktop="4" widescreen="4" visible="5"}}';
32 |
33 | $html = '
- ';
34 | $html .= '
' . __('Add Widget name "Magiccart Magicslider widget" and set categorie for it.') . '
';
35 | $html .= '' . __('Example: categories="1,5,10,12"') . '
';
36 | $html .= ' - ';
37 | $html .= '' . __('Copy Short code add to CMS Page/Static Block.') . '';
38 | $html .= '
' . $shortcodeWidget . '
';
39 | $html .= '
';
40 |
41 | return $html;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Block/Widget/Categories.php:
--------------------------------------------------------------------------------
1 | getResponsiveBreakpoints();
19 | $total = count($breakpoints);
20 | $responsive = '[';
21 | foreach ($breakpoints as $size => $screen) {
22 | if ($this->getData($screen)){
23 | $responsive .= '{"breakpoint": '.$size.', "settings": {"slidesToShow": '.$this->getData($screen).'}}';
24 | }
25 | if($total-- > 1) $responsive .= ', ';
26 | }
27 | $responsive .= ']';
28 | $data['responsive'] = $responsive;
29 | $data['autoplay-Speed'] = $this->getData('autoplaySpeed');
30 | $data['slides-To-Show'] = $this->getData('visible');
31 | // $data['swipe-To-Slide'] = 'true';
32 | $data['vertical-Swiping'] = $this->getData('vertical');
33 | $data['slide'] = 1;
34 | //$data['lazy-Load'] = 'progressive';
35 | $this->addData($data);
36 | parent::_construct();
37 | }
38 |
39 | public function getCacheKeyInfo()
40 | {
41 | $keyInfo = parent::getCacheKeyInfo();
42 | $uniqueId = $this->getUniqueId();
43 | $keyInfo[] = $uniqueId;
44 | return $keyInfo;
45 | }
46 |
47 | public function getUniqueId()
48 | {
49 | $categories = $this->getData('categories');
50 | $categories = str_replace(" ", "", $categories);
51 | $categories = str_replace(",", "_", $categories);
52 | return $categories;
53 | }
54 |
55 | public function isShowThumbnail(){
56 | return $this->getData('thumbnail');
57 | }
58 |
59 | public function getLayout()
60 | {
61 | return 'grid';
62 | }
63 |
64 | public function getHeading()
65 | {
66 | return $this->getData('title');
67 | }
68 |
69 | public function isShowDescription()
70 | {
71 | return $this->getData('description');
72 | }
73 |
74 | public function getItemAmount(){
75 | return $this->getData('item_amount');
76 | }
77 |
78 | public function getSortAttribute()
79 | {
80 | return $this->getData('sort_attribute');
81 | }
82 |
83 | public function getCategories()
84 | {
85 |
86 | $categoryIds = $this->getData('categories');
87 | if(!$categoryIds) return;
88 | $sortAttribute = $this->getSortAttribute();
89 |
90 | $attributesSelect = ['name', 'url_key', 'url_path', 'image','description'];
91 | if($this->isShowThumbnail()) $attributesSelect[] = 'magepow_thumbnail';
92 | $categories = $this->categoryFactory->create();
93 | $categories = $categories->getCollection()
94 | ->addAttributeToSelect($attributesSelect)
95 | ->addIdFilter($categoryIds);
96 |
97 | if($sortAttribute == "position") {
98 | $categories->addAttributeToSort('level');
99 | }elseif($sortAttribute=='custom'){
100 | $custom_sort= $this->getData('custom_sort');
101 | if(preg_match('/^(\d+,)+\d+$/', (string) $custom_sort)){
102 | $custom_sort_arr = [];
103 | $categoryIds = explode(',', (string) $categoryIds);
104 | $custom_sort_arr = explode(',',(string) $custom_sort);
105 | $custom_sort_arr2 = array_merge(array_diff($custom_sort_arr, $categoryIds), array_diff($categoryIds,$custom_sort_arr));
106 | $custom_sort_arr = array_merge($custom_sort_arr,$custom_sort_arr2);
107 | $categories->getSelect()->order(new \Zend_Db_Expr('FIELD(entity_id,' . implode(',', $custom_sort_arr).')'));
108 | }else{
109 | $categories->addAttributeToSort('level');
110 | }
111 | }else{
112 | $categories->addAttributeToSort($sortAttribute);
113 | }
114 |
115 | return $categories;
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Category/Thumbnail/Upload.php:
--------------------------------------------------------------------------------
1 | imageUploader = $imageUploader;
18 | parent::__construct($context);
19 |
20 | }
21 | public function execute() {
22 | try {
23 | $result = $this->imageUploader->saveFileToTmpDir('magepow_thumbnail');
24 | $result['cookie'] = [
25 | 'name' => $this->_getSession()->getName(),
26 | 'value' => $this->_getSession()->getSessionId(),
27 | 'lifetime' => $this->_getSession()->getCookieLifetime(),
28 | 'path' => $this->_getSession()->getCookiePath(),
29 | 'domain' => $this->_getSession()->getCookieDomain(),
30 | ];
31 | } catch (\Exception $e) {
32 | $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
33 | }
34 | return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
35 | }
36 | }
--------------------------------------------------------------------------------
/Helper/Data.php:
--------------------------------------------------------------------------------
1 | configModule = $this->getConfig(strtolower($this->_getModuleName()));
28 | }
29 |
30 | public function getConfig($cfg='')
31 | {
32 | if($cfg) return $this->scopeConfig->getValue( $cfg, \Magento\Store\Model\ScopeInterface::SCOPE_STORE );
33 | return $this->scopeConfig;
34 | }
35 |
36 | public function getConfigModule($cfg='', $value=null)
37 | {
38 | $values = $this->configModule;
39 | if( !$cfg ) return $values;
40 | $config = explode('/', (string) $cfg);
41 | $end = count($config) - 1;
42 | foreach ($config as $key => $vl) {
43 | if( isset($values[$vl]) ){
44 | if( $key == $end ) {
45 | $value = $values[$vl];
46 | }else {
47 | $values = $values[$vl];
48 | }
49 | }
50 |
51 | }
52 | return $value;
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/Model/Category/Attribute/Backend/Image.php:
--------------------------------------------------------------------------------
1 | _filesystem = $filesystem;
81 | $this->_fileUploaderFactory = $fileUploaderFactory;
82 | $this->_logger = $logger;
83 | $this->storeManager = $storeManager ??
84 | ObjectManager::getInstance()->get(StoreManagerInterface::class);
85 | $this->imageUploader = $imageUploader ??
86 | ObjectManager::getInstance()->get(ImageUploader::class);
87 | }
88 |
89 | /**
90 | * Gets image name from $value array.
91 | *
92 | * Will return empty string in a case when $value is not an array.
93 | *
94 | * @param array $value Attribute value
95 | * @return string
96 | */
97 | private function getUploadedImageName($value)
98 | {
99 | if (is_array($value) && isset($value[0]['name'])) {
100 | // var_dump($value[0]['name']);
101 | // die('zxcvzx');
102 | return $value[0]['name'];
103 | }
104 |
105 | return '';
106 | }
107 |
108 | /**
109 | * Check that image name exists in catalog/category directory and return new image name if it already exists.
110 | *
111 | * @param string $imageName
112 | * @return string
113 | */
114 | private function checkUniqueImageName(string $imageName): string
115 | {
116 | $mediaDirectory = $this->_filesystem->getDirectoryWrite(DirectoryList::MEDIA);
117 | $imageAbsolutePath = $mediaDirectory->getAbsolutePath(
118 | $this->imageUploader->getBasePath() . DIRECTORY_SEPARATOR . $imageName
119 | );
120 |
121 | // phpcs:ignore Magento2.Functions.DiscouragedFunction
122 | $imageName = call_user_func([Uploader::class, 'getNewFilename'], $imageAbsolutePath);
123 |
124 | return $imageName;
125 | }
126 |
127 | /**
128 | * Avoiding saving potential upload data to DB.
129 | *
130 | * Will set empty image attribute value if image was not uploaded.
131 | *
132 | * @param \Magento\Framework\DataObject $object
133 | * @return $this
134 | * @since 101.0.8
135 | */
136 | public function beforeSave($object)
137 | {
138 | $attributeName = $this->getAttribute()->getName();
139 |
140 | $value = $object->getData($attributeName);
141 |
142 | if ($this->isTmpFileAvailable($value) && $imageName = $this->getUploadedImageName($value)) {
143 | try {
144 | /** @var StoreInterface $store */
145 | $store = $this->storeManager->getStore();
146 | $baseMediaDir = $store->getBaseMediaDir();
147 | $newImgRelativePath = $this->imageUploader->moveFileFromTmp($imageName, true);
148 | $value[0]['url'] = '/' . $baseMediaDir . '/' . $newImgRelativePath;
149 | $value[0]['name'] = $value[0]['url'];
150 | } catch (\Exception $e) {
151 | $this->_logger->critical($e);
152 | }
153 | } elseif ($this->fileResidesOutsideCategoryDir($value)) {
154 | // use relative path for image attribute so we know it's outside of category dir when we fetch it
155 | // phpcs:ignore Magento2.Functions.DiscouragedFunction
156 | $value[0]['url'] = parse_url($value[0]['url'], PHP_URL_PATH);
157 | // $value[0]['name'] = $value[0]['url'];
158 | }
159 |
160 | if ($imageName = $this->getUploadedImageName($value)) {
161 | if (!$this->fileResidesOutsideCategoryDir($value)) {
162 | $imageName = $this->checkUniqueImageName($imageName);
163 | }
164 | $object->setData($this->additionalData . $attributeName, $value);
165 |
166 | $object->setData($attributeName, $imageName);
167 |
168 | } elseif (!is_string($value)) {
169 | $object->setData($attributeName, null);
170 | }
171 | return parent::beforeSave($object);
172 | }
173 |
174 | /**
175 | * Check if temporary file is available for new image upload.
176 | *
177 | * @param array $value
178 | * @return bool
179 | */
180 | private function isTmpFileAvailable($value)
181 | {
182 | return is_array($value) && isset($value[0]['tmp_name']);
183 | }
184 |
185 | /**
186 | * Check for file path resides outside of category media dir. The URL will be a path including pub/media if true
187 | *
188 | * @param array|null $value
189 | * @return bool
190 | */
191 | private function fileResidesOutsideCategoryDir($value)
192 | {
193 | if (!is_array($value) || !isset($value[0]['url'])) {
194 | return false;
195 | }
196 |
197 | $fileUrl = ltrim($value[0]['url'], '/');
198 | $baseMediaDir = $this->_filesystem->getUri(DirectoryList::MEDIA);
199 |
200 | if (!$baseMediaDir) {
201 | return false;
202 | }
203 |
204 | return strpos($fileUrl, $baseMediaDir) !== false;
205 | }
206 |
207 | /**
208 | * Save uploaded file and set its name to category
209 | *
210 | * @param \Magento\Framework\DataObject $object
211 | * @return \Magento\Catalog\Model\Category\Attribute\Backend\Image
212 | * @SuppressWarnings(PHPMD.UnusedFormalParameter)
213 | */
214 | public function afterSave($object)
215 | {
216 | return $this;
217 | }
218 | }
219 |
--------------------------------------------------------------------------------
/Model/Config/Category.php:
--------------------------------------------------------------------------------
1 | request = $request;
45 | $this->storeManager = $storeManager;
46 | $this->categoryTree = $categoryTree;
47 | }
48 |
49 | public function toOptionArray()
50 | {
51 | if(!$this->options){
52 | $store = $this->request->getParam('store');
53 | $categories = $this->categoryTree->getTree();
54 | $options = [['label' => __('All'), 'value' => '0']];
55 | foreach ($categories as $category) {
56 | $this->options = [];
57 | if(isset($category['cls']) && str_contains($category['cls'] , 'no-active')) continue;
58 | if($category['id']) {
59 | $this->options[] = ['label' => __('All in "%1"', $category['text']), 'value' => $category['id']];
60 | $_categories = isset($category['children']) ? $category['children'] : '' ;
61 | if($_categories){
62 | // $rootOption = ['label' => $category['label']];
63 | foreach ($_categories as $cat) {
64 | $this->options[] = [
65 | 'label' => self::PREFIX_ROOT .$cat['text'],
66 | 'value' => $cat['id']
67 | ];
68 | if(isset($cat['cls']) && str_contains($cat['cls'] , 'no-active')) continue;
69 | if (isset($cat['children'])) $this->_getChildOptions($cat['children']);
70 | }
71 | // $rootOption['value'] = $this->options;
72 | // $options[] = $rootOption;
73 | if($this->options){
74 | $options[] = [
75 | 'label' => $category['text'],
76 | 'value' => $this->options
77 | ];
78 | }
79 | }
80 | }
81 | }
82 | $this->options = $options;
83 | }
84 | return $this->options;
85 | }
86 |
87 | protected function _getChildOptions($categories)
88 | {
89 | foreach ($categories as $category) {
90 | $prefix = str_repeat(self::REPEATER, count(explode("/", $category['path'])) * 1) . self::PREFIX_END;
91 | $this->options[] = [
92 | 'label' => $prefix . $category['text'],
93 | 'value' => $category['id']
94 | ];
95 | if(isset($category['cls']) && str_contains($category['cls'] , 'no-active')) continue;
96 | if (isset($category['children'])) $this->_getChildOptions($category['children']);
97 | }
98 | }
99 |
100 | }
--------------------------------------------------------------------------------
/Model/Config/Layout.php:
--------------------------------------------------------------------------------
1 | 'grid', 'label' => __('Grid')],
27 | ['value' => 'list', 'label' => __('List')]
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Model/Config/SortAttribute.php:
--------------------------------------------------------------------------------
1 | 'name', 'label' => __('Name')],
27 | ['value' => 'meta_title', 'label' => __('Page Title')],
28 | ['value' => 'position', 'label' => __('Position')],
29 | ['value' => 'created_at', 'label' => __('Created Date')],
30 | ['value' => 'custom', 'label' => __('Custom Sort')]
31 | ];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Model/Config/Source/Col.php:
--------------------------------------------------------------------------------
1 | 1, 'label'=>__('1 item(s) /row')),
24 | array('value' => 2, 'label'=>__('2 item(s) /row')),
25 | array('value' => 3, 'label'=>__('3 item(s) /row')),
26 | array('value' => 4, 'label'=>__('4 item(s) /row')),
27 | array('value' => 5, 'label'=>__('5 item(s) /row')),
28 | array('value' => 6, 'label'=>__('6 item(s) /row')),
29 | array('value' => 7, 'label'=>__('7 item(s) /row')),
30 | array('value' => 8, 'label'=>__('8 item(s) /row')),
31 | array('value' => 9, 'label'=>__('9 item(s) /row')),
32 | array('value' => 10, 'label'=>__('10 item(s) /row')),
33 | array('value' => 11, 'label'=>__('11 item(s) /row')),
34 | array('value' => 12, 'label'=>__('12 item(s) /row')),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Model/Config/Source/Responsive.php:
--------------------------------------------------------------------------------
1 | 'visible',
18 | 1920 =>'widescreen',
19 | 1480 =>'desktop',
20 | 1200 =>'laptop',
21 | 992 =>'notebook',
22 | 768 =>'tablet',
23 | 576 =>'landscape',
24 | 481 =>'portrait',
25 | 361 =>'mobile',
26 | 1 =>'mobile'
27 | );
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/Model/Config/Source/Row.php:
--------------------------------------------------------------------------------
1 | __('1 row(s) /slider'),
18 | '2'=> __('2 row(s) /slider'),
19 | '3'=> __('3 row(s) /slider'),
20 | '4'=> __('4 row(s) /slider'),
21 | '5'=> __('5 row(s) /slider'),
22 | '6'=> __('6 row(s) /slider'),
23 | ];
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Model/Config/Source/Status.php:
--------------------------------------------------------------------------------
1 | __('Enabled')
26 | , self::STATUS_DISABLED => __('Disabled'),
27 | ];
28 | }
29 |
30 | public static function getOptionArray()
31 | {
32 | return self::getAvailableStatuses();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Model/Config/Source/Truefalse.php:
--------------------------------------------------------------------------------
1 | 'true', 'label' => __('True')], ['value' => 'false', 'label' => __('False')]];
22 | }
23 |
24 | /**
25 | * Get options in "key-value" format
26 | *
27 | * @return array
28 | */
29 | public function toArray()
30 | {
31 | return ['false' => __('No'), 'true' => __('Yes')];
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [
](https://shopify.pxf.io/VyL446)
2 |
3 | ## Magento 2 Categories Extension Free
4 | **Magento 2 Categories Extension Free** allows you to take the shortest way to lead customers to their target pages. With this extension, you can show subcategories on category pages and choose the layout to display them as the grid or list. Aside from that, you also can show the hot categories or simply the chosen categories on the Homepage or any CMS page.
5 |
6 | **Categories extension free by Magepow** is very easy to configure and manage, with no coding needed and responsive ready. With this extension, you can suggest to customers more content/products you have on your store and make an eye-catching look.
7 |
8 | For example, your online store is selling a wide range of subcategories such as Tops, bottoms, pants, bags, jackets... might dozens of categories but you want when your customers come to your store, you want them to buy or know most of some products types that you concentrate more than normal products.
9 |
10 | 
11 |
12 | So this extension can help you show on the top of the page the hot categories are chosen from categories collection or show them on the top of the category pages to recommend to customers.
13 |
14 | [](https://packagist.org/packages/magepow/categories)
15 | [](https://packagist.org/packages/magepow/categories)
16 | [](https://packagist.org/packages/magepow/categories)
17 |
18 | ### 1. Highlight Features
19 | | Features | Free Version | Pro Version |
20 | | :------------ |:---------------:| :-----:|
21 | |Display optional subcategories on **Home page**|:white_check_mark:|:white_check_mark:|
22 | |Display the subcategories as slider layout on the Home page|X|:white_check_mark:|
23 | |Display optional subcategories on **Category page**|:white_check_mark:|:white_check_mark:|
24 | |Display the subcategories as slider layout on the Categories page|X|:white_check_mark:|
25 | |Display optional subcategories on **Product page**|X|:white_check_mark:|
26 | |Display optional subcategories on **Shopping Cart page**|X|:white_check_mark:|
27 | |Add or remove categories for the home pape and category pages as desired|:white_check_mark:|:white_check_mark:|
28 | |Add or remove categories on each page as desired|X|:white_check_mark:|
29 | |Multiple positions show categories|X|:white_check_mark:|
30 | |Subcategory characteristics on homepage and category page vary with 2
independent installers|:white_check_mark:|:white_check_mark:|
31 | |Subcategory block characteristics on each page can be individually
customized using 'Category Pro Rule'|X|:white_check_mark:|
32 | |**Grid layout**|:white_check_mark:|:white_check_mark:|
33 | |**List layout**|:white_check_mark:|:white_check_mark:|
34 | |**Slider layout**|X|:white_check_mark:|
35 | |Sort the subcategories by **Name**|:white_check_mark:|:white_check_mark:|
36 | |Sort the subcategories by **Page Title**|:white_check_mark:|:white_check_mark:|
37 | |Sort the subcategories by **Location**|:white_check_mark:|:white_check_mark:|
38 | |Sort the subcategories by **Creation Date**|:white_check_mark:|:white_check_mark:|
39 | |Sort the subcategories by **Admin tree**|X|:white_check_mark:|
40 | |Display subcategory with **Block Title**|:white_check_mark:|:white_check_mark:|
41 | |Display subcategory with **Description**|:white_check_mark:|:white_check_mark:|
42 | |Display subcategory with **Thumbnail**|:white_check_mark:|:white_check_mark:|
43 | |Display subcategory with **Item Amount**|:white_check_mark:|:white_check_mark:|
44 | |Full responsive design|:white_check_mark:|:white_check_mark:|
45 | |Customize Responsive Information|X|:white_check_mark:|
46 | |Display different categories with customer groups
(Not logged in, General, Wholesale, Retailer)|X|:white_check_mark:|
47 | |Free Support|X|:white_check_mark:|
48 |
49 | 
50 |
51 | Display optional subcategories on Home page
52 |
53 | 
54 |
55 | Display optional subcategories on Category page
56 |
57 | 
58 |
59 | Display optional subcategories on Product page
60 |
61 | 
62 |
63 | Display optional subcategories on Shopping Cart page
64 |
65 | See more: [Demo free version](https://demo.magepow.com/categories/) - [Demo Pro version](https://demo.magepow.com/categoriespro/)
66 |
67 | [](https://magepow.com/magento-2-categories-extension.html) [](https://magepow.com/magento-2-categories-extension.html)
68 |
69 | ### 2. How to install Magento 2 Categories extension Free
70 | #### ✓ Install Magepow Categories via composer (recommend)
71 | Run the following command in Magento 2 root folder:
72 |
73 | ```
74 | composer require magepow/categories
75 | php bin/magento setup:upgrade
76 | php bin/magento setup:static-content:deploy -f
77 | ```
78 |
79 | ### 3. Magepow Categories user guide
80 | **SubCategories extension free for Magento** allows customers access the categories quickly and conveniently, stimulating users to click on the categories because of the beautiful interface.
81 |
82 | #### Enable Magepow Categories
83 | Go to `Admin Panel > Stores > Settings > Configuration > Magepow > Categories`
84 |
85 | Select `Yes` to enable module.
86 | #### Setting Magepow SubCategories
87 | Go to `Admin Panel > Stores > Settings > Configuration > Magepow > Categories`
88 |
89 | * Two layouts available (Grid or List).
90 | * Ability to sort subcategories by "Name", "Page Title", "Position", and "Created Date".
91 | * Ability to show subcategories heading or not and to type in the heading text.
92 | * Ability to show or not category description.
93 | * Select categories that do not display subcategories.
94 |
95 | 
96 |
97 | The home page also has the same settings as the category page, except that:
98 |
99 | * The home page can choose the display categories instead of excluding the display category.
100 | * The home page can order the categories by 'custom sort', which will display in the order ids appear in the config value.
101 | You can curate this by manually setting the ids in the env.php file to override admin based config.
102 | ```
103 | ./bin/magento config:set -e magepow_categories/home_page/category_select "64,72,73,1052,68,69,70,1046,65,88,311"
104 | ```
105 | * Select the categories displayed on the home page.
106 |
107 | 
108 |
109 | ### This Is Result In Frontend
110 | #### In homepage
111 |
112 | 
113 |
114 | #### In categories page
115 |
116 | 
117 |
118 | ### [How does Magento 2 Categories work?](https://www.youtube.com/watch?v=k3A7PBh-NbQ&lc=UgzCFSLUqlD6cl__PH54AaABAg)
119 | ## Donation
120 |
121 | If this project help you reduce time to develop, you can give me a cup of coffee :)
122 |
123 | [](https://www.paypal.com/paypalme/alopay)
124 |
125 |
126 | **[Our Magento 2 Extensions](https://magepow.com/magento-2-extensions.html)**
127 |
128 | * [Magento 2 Recent Sales Notification](https://magepow.com/magento-2-recent-order-notification.html)
129 |
130 | * [Magento 2 Categories Extension](https://magepow.com/magento-categories-extension.html)
131 |
132 | * [Magento 2 Sticky Cart](https://magepow.com/magento-sticky-cart.html)
133 |
134 | * [Magento 2 Ajax Contact](https://magepow.com/magento-ajax-contact-form.html)
135 |
136 | * [Magento 2 Lazy Load](https://magepow.com/magento-lazy-load.html)
137 |
138 | * [Magento 2 Mutil Translate](https://magepow.com/magento-multi-translate.html)
139 |
140 | * [Magento 2 Instagram Integration](https://magepow.com/magento-2-instagram.html)
141 |
142 | * [Magento 2 Lookbook Pin Products](https://magepow.com/lookbook-pin-products.html)
143 |
144 | * [Magento 2 Product Slider](https://magepow.com/magento-product-slider.html)
145 |
146 | * [Magento 2 Product Banner](https://magepow.com/magento-2-banner-slider.html)
147 |
148 | **[Our Magento 2 services](https://magepow.com/magento-services.html)**
149 |
150 | * [PSD to Magento 2 Theme Conversion](https://alothemes.com/psd-to-magento-theme-conversion.html)
151 |
152 | * [Magento 2 Speed Optimization Service](https://magepow.com/magento-speed-optimization-service.html)
153 |
154 | * [Magento 2 Security Patch Installation](https://magepow.com/magento-security-patch-installation.html)
155 |
156 | * [Magento 2 Website Maintenance Service](https://magepow.com/website-maintenance-service.html)
157 |
158 | * [Magento 2 Professional Installation Service](https://magepow.com/professional-installation-service.html)
159 |
160 | * [Magento 2 Upgrade Service](https://magepow.com/magento-upgrade-service.html)
161 |
162 | * [Magento 2 Customization Service](https://magepow.com/customization-service.html)
163 |
164 | * [Hire Magento 2 Developer](https://magepow.com/hire-magento-developer.html)
165 |
166 | **[Our Magento 2 Themes](https://alothemes.com/)**
167 |
168 | * [Expert Multipurpose Responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/expert-premium-responsive-magento-2-and-1-support-rtl-magento-2-/21667789)
169 |
170 | * [Gecko Premium Responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/gecko-responsive-magento-2-theme-rtl-supported/24677410)
171 |
172 | * [Milano Fashion Responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/milano-fashion-responsive-magento-1-2-theme/12141971)
173 |
174 | * [Electro 2 Responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/electro2-premium-responsive-magento-2-rtl-supported/26875864)
175 |
176 | * [Electro Responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/electro-responsive-magento-1-2-theme/17042067)
177 |
178 | * [Pizzaro Food responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/pizzaro-food-responsive-magento-1-2-theme/19438157)
179 |
180 | * [Biolife organic responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/biolife-organic-food-magento-2-theme-rtl-supported/25712510)
181 |
182 | * [Market responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/market-responsive-magento-2-theme/22997928)
183 |
184 | * [Kuteshop responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/kuteshop-multipurpose-responsive-magento-1-2-theme/12985435)
185 |
186 | * [Bencher - Responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/bencher-responsive-magento-1-2-theme/15787772)
187 |
188 | * [Supermarket Responsive Magento 2 Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/supermarket-responsive-magento-1-2-theme/18447995)
189 |
190 | **[Our Shopify Themes](https://themeforest.net/user/alotheme)**
191 |
192 | * [Dukamarket - Multipurpose Shopify Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/dukamarket-multipurpose-shopify-theme/36158349)
193 |
194 | * [Ohey - Multipurpose Shopify Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/ohey-multipurpose-shopify-theme/34624195)
195 |
196 | * [Flexon - Multipurpose Shopify Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/flexon-multipurpose-shopify-theme/33461048)
197 |
198 | **[Our Shopify App](https://apps.shopify.com/partners/maggicart)**
199 |
200 | * [Magepow Infinite Scroll](https://apps.shopify.com/magepow-infinite-scroll)
201 |
202 | * [Magepow Promotionbar](https://apps.shopify.com/magepow-promotionbar)
203 |
204 | * [Magepow Size Chart](https://apps.shopify.com/magepow-size-chart)
205 |
206 | **[Our WordPress Theme](https://themeforest.net/user/alotheme/portfolio)**
207 |
208 | * [SadesMarket - Multipurpose WordPress Theme](https://1.envato.market/c/1314680/275988/4415?u=https://themeforest.net/item/sadesmarket-multipurpose-wordpress-theme/35369933)
209 |
--------------------------------------------------------------------------------
/Setup/InstallData.php:
--------------------------------------------------------------------------------
1 | categorySetupFactory = $categorySetupFactory;
21 | }
22 |
23 | public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
24 | {
25 | $installer = $setup;
26 | $installer->startSetup();
27 |
28 | $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);
29 | $entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Category::ENTITY);
30 | $attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
31 | $categorySetup->removeAttribute(
32 | \Magento\Catalog\Model\Category::ENTITY, 'magepow_thumbnail' );
33 | $categorySetup->addAttribute(
34 | \Magento\Catalog\Model\Category::ENTITY, 'magepow_thumbnail', [
35 | 'type' => 'varchar',
36 | 'label' => 'Thumbnail',
37 | 'input' => 'image',
38 | 'backend' => 'Magento\Catalog\Model\Category\Attribute\Backend\Image',
39 | 'required' => false,
40 | 'sort_order' => 5,
41 | 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
42 | 'group' => 'General Information',
43 | ]
44 | );
45 | $installer->endSetup();
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "magepow/categories",
3 | "description": "Shows categories in the form of a grid or list, on category pages, home page or any other page.",
4 | "require": {
5 | "magepow/core": "^1.0.0"
6 | },
7 | "type": "magento2-module",
8 | "license": [
9 | "OSL-3.0",
10 | "AFL-3.0"
11 | ],
12 | "authors": [
13 | {
14 | "name": "Magepow",
15 | "email": "support@magepow.com",
16 | "homepage": "https://magepow.com",
17 | "role": "Technical Support"
18 | }
19 | ],
20 | "autoload": {
21 | "files": [
22 | "registration.php"
23 | ],
24 | "psr-4": {
25 | "Magepow\\Categories\\": ""
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/etc/adminhtml/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Magento\Catalog\CategoryImageUpload
6 |
7 |
8 |
9 |
10 |
11 | - jpg
12 | - jpeg
13 | - gif
14 | - png
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/etc/adminhtml/routes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/etc/adminhtml/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | magepow
10 | Magepow_Categories::config
11 |
12 |
13 |
14 |
15 | Enables or disables extension.
16 | Magento\Config\Model\Config\Source\Yesno
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | The way categories are presented. Can be either "Grid" or "List".
25 | Magepow\Categories\Model\Config\Layout
26 |
27 |
28 |
29 | The way categories are sorted.
30 | Magepow\Categories\Model\Config\SortAttribute
31 |
32 |
33 |
34 | Categories heading text.
35 | validate-no-html-tags
36 |
37 |
38 |
39 | Enables or disables description.
40 | Magento\Config\Model\Config\Source\Yesno
41 |
42 |
43 |
44 | Enables to use Thumbnail set in Categories or disables to use Category Image.
45 | Magento\Config\Model\Config\Source\Yesno
46 |
47 |
48 |
49 | Enables to show number of items in each category.
50 | Magento\Config\Model\Config\Source\Yesno
51 |
52 |
53 |
54 | Use Ctrl+Click for check several values or uncheck value. Select categories that do not display subcategories.
55 | Magepow\Categories\Model\Config\Category
56 | 1
57 |
58 |
59 |
60 | Magento\Config\Block\System\Config\Form\Field\Heading
61 |
62 |
63 |
64 | Enabled Slide
65 | Magento\Config\Model\Config\Source\Yesno
66 |
67 |
68 |
69 | Mode Vertical
70 | Magepow\Categories\Model\Config\Source\Truefalse
71 | 1,3
72 |
73 |
74 |
75 | Infinite
76 | Magepow\Categories\Model\Config\Source\Truefalse
77 | 1
78 |
79 |
80 |
81 | Auto Play
82 | Magepow\Categories\Model\Config\Source\Truefalse
83 | 1
84 |
85 |
86 |
87 | Next/Back
88 | Magepow\Categories\Model\Config\Source\Truefalse
89 | 1
90 |
91 |
92 |
93 | Pager
94 | Magepow\Categories\Model\Config\Source\Truefalse
95 | 1
96 |
97 |
98 |
99 | Row Item
100 | Magepow\Categories\Model\Config\Source\Row
101 | 1
102 |
103 |
104 |
105 | Speed
106 | validate-zero-or-greater
107 | 1
108 |
109 |
110 |
111 | autoplay Speed
112 | validate-zero-or-greater
113 | 1
114 |
115 |
116 |
117 | Padding item Brand
118 | validate-zero-or-greater
119 |
120 |
121 |
122 | Magento\Config\Block\System\Config\Form\Field\Heading
123 |
124 |
125 |
126 |
127 | Magepow\Categories\Model\Config\Source\Col
128 | required-entry validate-greater-than-zero
129 |
130 |
131 |
132 |
133 | Magepow\Categories\Model\Config\Source\Col
134 | required-entry validate-greater-than-zero
135 |
136 |
137 |
138 |
139 | Magepow\Categories\Model\Config\Source\Col
140 | required-entry validate-greater-than-zero
141 |
142 |
143 |
144 |
145 | Magepow\Categories\Model\Config\Source\Col
146 | required-entry validate-greater-than-zero
147 |
148 |
149 |
150 |
151 | Magepow\Categories\Model\Config\Source\Col
152 | required-entry validate-greater-than-zero
153 |
154 |
155 |
156 |
157 | Magepow\Categories\Model\Config\Source\Col
158 | required-entry validate-greater-than-zero
159 |
160 |
161 |
162 |
163 | Magepow\Categories\Model\Config\Source\Col
164 |
165 |
166 |
167 |
168 | Magepow\Categories\Model\Config\Source\Col
169 |
170 |
171 |
172 | = 1920 ) ]]>
173 | Magepow\Categories\Model\Config\Source\Col
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 | The way categories are presented. Can be either "Grid" or "List".
183 | Magepow\Categories\Model\Config\Layout
184 |
185 |
186 |
187 | The way categories are sorted.
188 | Magepow\Categories\Model\Config\SortAttribute
189 |
190 |
191 |
192 | Categories heading text.
193 | validate-no-html-tags
194 |
195 |
196 |
197 | Enables or disables description.
198 | Magento\Config\Model\Config\Source\Yesno
199 |
200 |
201 |
202 | Enables to use Thumbnail set in Categories or disables to use Category Image.
203 | Magento\Config\Model\Config\Source\Yesno
204 |
205 |
206 |
207 | Enables to show number of items in each category.
208 | Magento\Config\Model\Config\Source\Yesno
209 |
210 |
211 |
212 | Use Ctrl+Click for check several values or uncheck value. Select the categories displayed on the home page.
213 | Magepow\Categories\Model\Config\Category
214 | 1
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 | Copy to code to page or block you want display categories
223 | Magepow\Categories\Block\System\Config\Form\Field\Snippet
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/etc/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1
7 |
8 |
9 | grid
10 | position
11 |
12 | 0
13 | 1
14 |
15 | 1
16 | false
17 | true
18 | true
19 | true
20 | false
21 | 0
22 | 300
23 | 3000
24 | 15
25 | 1
26 | 2
27 | 3
28 | 4
29 | 5
30 | 5
31 | 5
32 | 6
33 | 6
34 |
35 |
36 | grid
37 | position
38 | Categories
39 | 0
40 | 1
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/etc/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 | Magepow Categories Widget
17 |
18 |
19 |
20 | Magepow Categories Widget
21 |
22 |
23 |
24 | Magepow Categories Widget
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
44 |
47 |
48 |
49 |
50 |
51 |
52 |
55 |
58 |
59 |
60 |
61 |
62 |
63 |
66 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Sort by typing down the category id and separating by comma.
77 | Mentioned ids will be sorted from the top, unmentioned ids will queue at the back.
78 | Wrong syntax won't sort.
79 | Right syntax example: 1,2,3,4
]]>
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
90 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
104 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
118 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
132 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
146 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
160 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | 300
171 |
172 |
173 |
174 |
175 |
176 |
177 | 3000
178 |
179 |
180 |
181 | 15
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
192 |
195 |
198 |
201 |
204 |
205 |
206 |
207 |
208 |
209 |
212 |
215 |
218 |
221 |
224 |
227 |
230 |
233 |
234 |
235 |
236 |
237 |
238 |
241 |
244 |
247 |
250 |
253 |
256 |
259 |
262 |
263 |
264 |
265 |
266 |
267 |
270 |
273 |
276 |
279 |
282 |
285 |
288 |
291 |
292 |
293 |
294 |
295 |
296 |
299 |
302 |
305 |
308 |
311 |
314 |
317 |
320 |
321 |
322 |
323 |
324 |
325 |
328 |
331 |
334 |
337 |
340 |
343 |
346 |
349 |
350 |
351 |
352 |
353 |
354 |
357 |
360 |
363 |
366 |
369 |
372 |
375 |
378 |
379 |
380 |
381 |
382 |
383 |
386 |
389 |
392 |
395 |
398 |
401 |
404 |
407 |
408 |
409 |
410 |
411 |
412 |
415 |
418 |
421 |
424 |
427 |
430 |
433 |
436 |
437 |
438 |
439 |
440 |
441 |
444 |
447 |
450 |
453 |
456 |
459 |
462 |
465 |
466 |
467 |
468 |
469 |
470 |
--------------------------------------------------------------------------------
/media/Mgento-2-category-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/Mgento-2-category-4.jpg
--------------------------------------------------------------------------------
/media/frontend_category.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/frontend_category.png
--------------------------------------------------------------------------------
/media/frontend_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/frontend_home.png
--------------------------------------------------------------------------------
/media/magento-2-categories-10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-10.jpg
--------------------------------------------------------------------------------
/media/magento-2-categories-11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-11.jpg
--------------------------------------------------------------------------------
/media/magento-2-categories-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-3.jpg
--------------------------------------------------------------------------------
/media/magento-2-categories-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-5.png
--------------------------------------------------------------------------------
/media/magento-2-categories-6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-6.jpg
--------------------------------------------------------------------------------
/media/magento-2-categories-7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-7.jpg
--------------------------------------------------------------------------------
/media/magento-2-categories-8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-8.jpg
--------------------------------------------------------------------------------
/media/magento-2-categories-9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/magepow/magento-2-categories/1096b3388c0353da33213dce64f6e858a50813a7/media/magento-2-categories-9.jpg
--------------------------------------------------------------------------------
/registration.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/view/frontend/layout/catalog_category_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/view/frontend/layout/cms_index_index.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/view/frontend/templates/categories.phtml:
--------------------------------------------------------------------------------
1 |
12 | getCategories();
20 | $layout = $block->getLayout();
21 | $heading = $block->getHeading();
22 | $description = $block->isShowDescription();
23 | $itemAmount = $block->getItemAmount();
24 | $selector = 'alo-content-' . uniqid();
25 | ?>
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
getFrontendCfg() as $opt) : ?> data-='getData($opt) ?>' getResponsiveBreakpoints() as $opt) : ?> data-='getData($opt) ?>' >
34 |
35 | -
36 |
37 |
47 |
48 |
49 | = $this->getDescription($cat) ?>
50 |
51 |
52 |
53 |
54 | getProductCollection()->count();
55 | if($cat->getProductCollection()->count()>0)echo " items)";
56 | else echo " item)";
57 | ?>
58 |
59 |
60 | /**
61 |
64 | */ ?>
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/view/frontend/templates/categories_widget.phtml:
--------------------------------------------------------------------------------
1 |
12 | getCategories();
20 | $heading = $block->getHeading();
21 | $description = $block->isShowDescription();
22 | $itemAmount = $block->getItemAmount();
23 | if (empty($categories)) return;
24 | $selector = 'alo-content-' . uniqid();
25 | ?>
26 | getData('visible'); ?>
27 |
30 |
31 |
32 | = __($this->getData('subtitle')); ?>
33 |
34 |
35 |
getFrontendCfg() as $opt) : ?> data-='getData($opt) ?>' getResponsiveBreakpoints() as $opt) : ?> data-='getData($opt) ?>' >
36 |
37 | getImageInfo($cat); ?>
38 | -
39 |
40 |
45 |
46 |
51 |
52 |
53 |
54 | getDescription($cat) ?>
55 |
56 |
57 |
58 |
59 | getProductCollection()->count();
60 | if ($cat->getProductCollection()->count() > 0) echo " items)";
61 | else echo " item)";
62 | ?>
63 |
64 |
65 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/view/frontend/templates/cmspage.phtml:
--------------------------------------------------------------------------------
1 |
12 | getCategories();
20 | $layout = $block->getLayout();
21 | $heading = $block->getHeading();
22 | $description = $block->isShowDescription();
23 | $itemAmount = $block->getItemAmount();
24 | ?>
25 |
26 |
27 |
28 |
29 |
30 |
31 | -
32 |
33 |
43 |
44 |
45 |
46 | getDescription($cat) ?>
47 |
48 |
49 |
50 |
51 | getProductCollection()->count();
52 | if($cat->getProductCollection()->count()>0)echo " items)";
53 | else echo " item)";
54 | ?>
55 |
56 |
57 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/view/frontend/web/css/source/_module.less:
--------------------------------------------------------------------------------
1 | & when (@media-common = true) {
2 | .magepow-categories-grid, .magepow-categories-list {
3 | clear: both;
4 | display: block;
5 | margin: 0;
6 | padding: 0;
7 | border: none;
8 | box-sizing: content-box;
9 | width: 100%;
10 | list-style-type: none;
11 | text-align: left;
12 | }
13 |
14 | .magepow-categories-grid {
15 | display: flex;
16 | flex-wrap: wrap;
17 | }
18 |
19 | .magepow-categories-heading {
20 | margin: 16px 0;
21 | }
22 |
23 |
24 | /* Grid layout */
25 |
26 | .magepow-categories-grid li {
27 | display: inline-block;
28 | text-align: left;
29 | margin: 0;
30 | padding: 0;
31 | border: none;
32 | box-sizing: content-box;
33 | width: 25%;
34 | vertical-align: top;
35 | }
36 |
37 | .magepow-categories-grid .category-item {
38 | display: block;
39 | margin: 16px;
40 | }
41 |
42 | .magepow-categories-grid .category-item-image img {
43 | margin: 0;
44 | padding: 0;
45 | border: none;
46 | width: 100%;
47 | }
48 |
49 | .magepow-categories-grid .category-item-name {
50 | text-align: center;
51 | }
52 |
53 | /* List layout */
54 |
55 | .magepow-categories-list li {
56 | margin: 0;
57 | padding: 0;
58 | border: none;
59 | box-sizing: content-box;
60 | overflow: auto;
61 | }
62 |
63 | .magepow-categories-list .category-item {
64 | display: block;
65 | overflow: auto;
66 | margin: 16px;
67 | }
68 |
69 | .magepow-categories-list .category-item-image {
70 | float: left;
71 | width: 20%; /* These percentages must match 1/3 */
72 | }
73 |
74 | .magepow-categories-list .category-item-image img {
75 | margin: 0;
76 | padding: 0;
77 | border: none;
78 | width: 100%;
79 | }
80 |
81 | .magepow-categories-list .category-item-name,
82 | .magepow-categories-list .category-item-description {
83 | margin: 0 0 16px 20%;
84 | padding: 0 0 0 32px;
85 | }
86 |
87 | .magepow-categories .category-item{
88 | display: inline-block;
89 | float: left;
90 | }
91 |
92 | /* Media Queries */
93 |
94 | @media only screen and (min-width: 320px) {
95 |
96 | .magepow-categories-grid li {
97 | width: 100%;
98 | }
99 |
100 | }
101 |
102 | @media only screen and (min-width: 360px) {
103 |
104 | .magepow-categories-grid li {
105 | width: 100%;
106 | }
107 |
108 | }
109 |
110 | @media only screen and (min-width: 400px) {
111 |
112 | .magepow-categories-grid li {
113 | width: 100%;
114 | }
115 |
116 | }
117 |
118 | @media only screen and (min-width: 480px) {
119 |
120 | .magepow-categories-grid li {
121 | width: 50%;
122 | }
123 |
124 | }
125 |
126 | @media only screen and (min-width: 540px) {
127 |
128 | .magepow-categories-grid li {
129 | width: 50%;
130 | }
131 |
132 | }
133 |
134 | @media only screen and (min-width: 600px) {
135 |
136 | .magepow-categories-grid li {
137 | width: 50%;
138 | }
139 |
140 | }
141 |
142 | @media only screen and (min-width: 640px) {
143 |
144 | .magepow-categories-grid li {
145 | width: 50%;
146 | }
147 |
148 | }
149 |
150 | @media only screen and (min-width: 720px) {
151 |
152 | .magepow-categories-grid li {
153 | width: 33.3%;
154 | }
155 |
156 | }
157 |
158 | @media only screen and (min-width: 768px) {
159 |
160 | .magepow-categories-grid li {
161 | width: 33.3%;
162 | }
163 |
164 | }
165 |
166 | @media only screen and (min-width: 800px) {
167 |
168 | .magepow-categories-grid li {
169 | width: 33.3%;
170 | }
171 |
172 | }
173 |
174 | @media only screen and (min-width: 960px) {
175 |
176 | .magepow-categories-grid li {
177 | width: 33.3%;
178 | }
179 |
180 | }
181 |
182 | @media only screen and (min-width: 1024px) {
183 |
184 | .magepow-categories-grid li {
185 | width: 25%;
186 | }
187 |
188 | }
189 |
190 | @media only screen and (min-width: 1280px) {
191 |
192 | .magepow-categories-grid li {
193 | width: 25%;
194 | }
195 |
196 | }
197 | }
--------------------------------------------------------------------------------