Skip to content

Commit 44e3919

Browse files
author
Willem Wigman
committed
initial commit
0 parents  commit 44e3919

File tree

10 files changed

+689
-0
lines changed

10 files changed

+689
-0
lines changed

CONTRIBUTING.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Contributing to IntegerNet_GlobalCustomLayout
2+
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
3+
4+
- Reporting a bug
5+
- Discussing the current state of the code
6+
- Submitting a fix
7+
- Proposing new features
8+
- Becoming a maintainer
9+
10+
## We Develop with Github
11+
We use github to host code, to track issues and feature requests, as well as accept pull requests.
12+
13+
## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests
14+
Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
15+
16+
1. Fork the repo and create your branch from `master`.
17+
2. If you've added code that should be tested, add tests.
18+
3. If you've changed APIs, update the documentation.
19+
4. Ensure the test suite passes.
20+
5. Make sure your code lints.
21+
6. Issue that pull request!
22+
23+
## Any contributions you make will be under the MIT Software License
24+
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
25+
26+
## Report bugs using Github's [issues](https://github.com/integer-net/magento2-global-custom-layout/issues)
27+
We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/integer-net/magento2-global-custom-layout/issues/new); it's that easy!
28+
29+
## Write bug reports with detail, background, and sample code
30+
[This is an example](http://stackoverflow.com/q/12488905/180626) of a bug report I wrote, and I think it's not a bad model. Here's [another example from Craig Hockenberry](http://www.openradar.me/11905408), an app developer whom I greatly respect.
31+
32+
**Great Bug Reports** tend to have:
33+
34+
- A quick summary and/or background
35+
- Steps to reproduce
36+
- Be specific!
37+
- Give sample code if you can. [My stackoverflow question](http://stackoverflow.com/q/12488905/180626) includes sample code that *anyone* with a base R setup can run to reproduce what I was seeing
38+
- What you expected would happen
39+
- What actually happens
40+
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
41+
42+
People *love* thorough bug reports. I'm not even kidding.
43+
44+
## Pull Requests
45+
46+
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - Check the code style with ``$ composer check-style`` and fix it with ``$ composer fix-style``.
47+
48+
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
49+
50+
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
51+
52+
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
53+
54+
- **Create feature branches** - Don't ask us to pull from your master branch.
55+
56+
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
57+
58+
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
59+
60+
## License
61+
By contributing, you agree that your contributions will be licensed under its MIT License.
62+
63+
## References
64+
This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md) with additions from [ThePhpLeague Template](https://github.com/thephpleague/skeleton)

LICENSE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Copyright 2020 integer_net GmbH
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Integer_Net GlobalCustomLayout
2+
3+
[![Software License][ico-license]](LICENSE.md)
4+
5+
Allows you to add global layout update files to be selected from admin, by using `0` instead of a `category_id` / `sku` / `url_path`.
6+
7+
Compatible with Magento 2.3.4 and higher, since **cms-page/product/category specific layouts** where introduced in this version.
8+
9+
## Purpose
10+
11+
In Magento 2.3.4, [xml layout updates were removed from the Magento Admin](https://devdocs.magento.com/guides/v2.3/release-notes/release-notes-2-3-4-open-source.html#highlights), for security reasons.
12+
Previously this textfield allowed you to add XML Layout updates to any given Category, Product or CMS Page.
13+
After the update, this textfield is no longer available, but you can select custom layout updates which are defined in xml layout files in the filesystem.
14+
15+
After uploading/deploying _selectable layout files_ onto your project's filesystem, these layouts can be selected from the admin under the **Design** section.
16+
The field is called **Custom Layout Update**.
17+
18+
## Usage:
19+
20+
Replace identifiers in selectable layouts with a 0 (zero).
21+
Add layout file to themes/modules using:
22+
- catalog_category_view_selectable_0_<Layout Update Name>.xml for Categories
23+
- catalog_product_view_selectable_0_<Layout Update Name>.xml for Products
24+
- cms_page_view_selectable_0_<Layout Update Name>.xml for Cms pages
25+
26+
These files can go anywhere where you'd normally put layout files. For example:
27+
`app/design/frontend/[Theme_Vendor]/[Theme_Name]/Magento_Theme/layout/catalog_category_view_0_customchanges.xml`
28+
29+
You can now select the layout update at _any_ given Category/Product/Page, under **Custom layout update** field of **Design**.
30+
31+
More info on default behaviour of selectable layouts:
32+
[Magento DevDocs: Create cms-page/product/category-specific layouts](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/xml-manage.html#create-cms-pageproductcategory-specific-layouts)
33+
34+
## Installation
35+
36+
1. Install via composer
37+
```
38+
composer require integer-net/magento2-global-custom-layout
39+
```
40+
2. Enable module
41+
```
42+
bin/magento setup:upgrade
43+
```
44+
## Configuration
45+
46+
Zero configuration needed.
47+
48+
## Contributing
49+
50+
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
51+
52+
## Known issues
53+
54+
1. Does not work with the homepage (cms_index_index). But hey, it doesn't in the default Magento implementation either.
55+
56+
## Security
57+
58+
If you discover any security related issues, please email ww@integer-net.de instead of using the issue tracker.
59+
60+
## Credits
61+
62+
- [Willem Wigman][link-author]
63+
- [All Contributors][link-contributors]
64+
65+
## License
66+
67+
The MIT License (MIT). Please see [License File](LICENSE.txt) for more information.
68+
69+
[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
70+
71+
[link-packagist]: https://packagist.org/packages/integer-net/magento2-global-custom-layout
72+
[link-author]: https://github.com/wigman
73+
[link-contributors]: ../../contributors

composer.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "integer-net/magento2-global-custom-layout",
3+
"description": "Module for Magento 2 that allows you to add global layout update files to be selected from admin, by using '0' instead of an entity_id",
4+
"authors": [
5+
{
6+
"name": "Willem Wigman",
7+
"email": "ww@integer-net.de"
8+
}
9+
],
10+
"require": {
11+
"magento/framework": ">=102.0.4",
12+
"magento/module-catalog": ">=103.0.4",
13+
"magento/module-cms": ">=103.0.4",
14+
"php": ">=7.1.0"
15+
},
16+
"type": "magento2-module",
17+
"license": [
18+
"MIT"
19+
],
20+
"autoload": {
21+
"files": [
22+
"src/registration.php"
23+
],
24+
"psr-4": {
25+
"IntegerNet\\GlobalCustomLayout\\": "src/"
26+
}
27+
},
28+
"repositories": [
29+
{
30+
"type": "composer",
31+
"url": "https://repo.magento.com/"
32+
}
33+
],
34+
"require-dev": {
35+
"magento/magento-coding-standard": "@dev"
36+
}
37+
}
38+

src/Plugin/CategoryLayoutPlugin.php

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace IntegerNet\GlobalCustomLayout\Plugin;
5+
6+
use Magento\Catalog\Api\Data\CategoryInterface;
7+
use Magento\Catalog\Model\Category;
8+
use Magento\Catalog\Model\Category\Attribute\LayoutUpdateManager;
9+
use Magento\Framework\App\Area;
10+
use Magento\Framework\DataObject;
11+
use Magento\Framework\View\Design\Theme\FlyweightFactory;
12+
use Magento\Framework\View\DesignInterface;
13+
use Magento\Framework\View\Model\Layout\Merge as LayoutProcessor;
14+
use Magento\Framework\View\Model\Layout\MergeFactory as LayoutProcessorFactory;
15+
16+
class CategoryLayoutPlugin
17+
{
18+
19+
/**
20+
* @var FlyweightFactory
21+
*/
22+
private $themeFactory;
23+
24+
/**
25+
* @var DesignInterface
26+
*/
27+
private $design;
28+
29+
/**
30+
* @var LayoutProcessorFactory
31+
*/
32+
private $layoutProcessorFactory;
33+
34+
/**
35+
* @var LayoutProcessor|null
36+
*/
37+
private $layoutProcessor;
38+
39+
/**
40+
* @param FlyweightFactory $themeFactory
41+
* @param DesignInterface $design
42+
* @param LayoutProcessorFactory $layoutProcessorFactory
43+
*/
44+
public function __construct(
45+
FlyweightFactory $themeFactory,
46+
DesignInterface $design,
47+
LayoutProcessorFactory $layoutProcessorFactory
48+
)
49+
{
50+
$this->themeFactory = $themeFactory;
51+
$this->design = $design;
52+
$this->layoutProcessorFactory = $layoutProcessorFactory;
53+
}
54+
55+
/**
56+
* Get the processor instance.
57+
*
58+
* @return LayoutProcessor
59+
*
60+
* Unchanged private method copied over from @var LayoutUpdateManager
61+
*/
62+
private function getLayoutProcessor(): LayoutProcessor
63+
{
64+
if (!$this->layoutProcessor) {
65+
$this->layoutProcessor = $this->layoutProcessorFactory->create(
66+
[
67+
'theme' => $this->themeFactory->create(
68+
$this->design->getConfigurationDesignTheme(Area::AREA_FRONTEND)
69+
)
70+
]
71+
);
72+
$this->themeFactory = null;
73+
$this->design = null;
74+
}
75+
76+
return $this->layoutProcessor;
77+
}
78+
79+
/**
80+
* Fetch list of available global files/handles for the category.
81+
*
82+
* @param LayoutUpdateManager $subject
83+
* @param array $result
84+
* @param CategoryInterface $category
85+
* @return array
86+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
87+
*/
88+
public function afterFetchAvailableFiles(
89+
LayoutUpdateManager $subject,
90+
array $result,
91+
CategoryInterface $category
92+
): array
93+
{
94+
if (!$category->getId()) {
95+
return $result;
96+
}
97+
98+
$handles = $this->getLayoutProcessor()->getAvailableHandles();
99+
100+
return array_merge($result, array_filter(
101+
array_map(
102+
function (string $handle) use ($category) : ?string {
103+
preg_match(
104+
'/^catalog\_category\_view\_selectable\_0\_([a-z0-9]+)/i',
105+
$handle,
106+
$selectable
107+
);
108+
if (!empty($selectable[1])) {
109+
return $selectable[1];
110+
}
111+
112+
return null;
113+
},
114+
$handles
115+
)
116+
));
117+
}
118+
119+
/**
120+
* Extract selected global custom layout settings.
121+
*
122+
* If no update is selected none will apply.
123+
*
124+
* @param LayoutUpdateManager $subject
125+
* @param $result
126+
* @param CategoryInterface $category
127+
* @param DataObject $intoSettings
128+
* @return void
129+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
130+
*/
131+
public function afterExtractCustomSettings(
132+
LayoutUpdateManager $subject,
133+
$result,
134+
CategoryInterface $category,
135+
DataObject $intoSettings
136+
): void
137+
{
138+
if ($category->getId() && $value = $this->extractAttributeValue($category)) {
139+
$handles = $intoSettings->getPageLayoutHandles() ?? [];
140+
$handles = array_merge_recursive(
141+
$handles,
142+
['selectable_0' => $value]
143+
);
144+
$intoSettings->setPageLayoutHandles($handles);
145+
}
146+
}
147+
148+
/**
149+
* Extract custom layout attribute value.
150+
*
151+
* @param CategoryInterface $category
152+
* @return mixed
153+
*
154+
* Unchanged private method copied over from @var LayoutUpdateManager
155+
*/
156+
private function extractAttributeValue(CategoryInterface $category)
157+
{
158+
if ($category instanceof Category && !$category->hasData(CategoryInterface::CUSTOM_ATTRIBUTES)) {
159+
return $category->getData('custom_layout_update_file');
160+
}
161+
if ($attr = $category->getCustomAttribute('custom_layout_update_file')) {
162+
return $attr->getValue();
163+
}
164+
165+
return null;
166+
}
167+
}

0 commit comments

Comments
 (0)