├── .gitignore
├── Block
├── Adminhtml
│ └── Form
│ │ └── Field
│ │ ├── OptionalFieldConfig.php
│ │ └── SpecificFieldConfig.php
└── Onepage
│ └── PlaceholderProcessor.php
├── CODE_OF_CONDUCT.md
├── LICENSE
├── Model
├── FieldFilter.php
├── PlaceholderInterface.php
└── System
│ ├── Config.php
│ └── ConfigInterface.php
├── README.md
├── ViewModel
└── ConfigViewModel.php
├── composer.json
├── etc
├── acl.xml
├── adminhtml
│ └── system.xml
├── config.xml
├── frontend
│ └── di.xml
└── module.xml
├── i18n
└── de_DE.csv
├── registration.php
└── view
└── frontend
├── layout
└── checkout_index_index.xml
├── requirejs-config.js
├── templates
├── css.phtml
└── custom-required-mark.phtml
└── web
└── template
└── form
└── element
├── email-amasty-checkout.html
├── email-amazon-pay.html
├── email-amazon-payment.html
└── email.html
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Field/OptionalFieldConfig.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | declare(strict_types=1);
9 |
10 | namespace Checkout\Placeholder\Block\Adminhtml\Form\Field;
11 |
12 | use Checkout\Placeholder\Model\System\ConfigInterface;
13 | use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
14 |
15 | class OptionalFieldConfig extends AbstractFieldArray implements ConfigInterface
16 | {
17 | protected function _prepareToRender()
18 | {
19 | $this->addColumn(
20 | self::COLUMN_KEY_FIELD_ID,
21 | ['label' => __('Field ID')]
22 | );
23 | $this->addColumn(
24 | self::COLUMN_KEY_FIELDSET_ID,
25 | ['label' => __('Fieldset ID')]
26 | );
27 | $this->_addAfter = false;
28 | $this->_addButtonLabel = __('Add');
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Field/SpecificFieldConfig.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | declare(strict_types=1);
9 |
10 | namespace Checkout\Placeholder\Block\Adminhtml\Form\Field;
11 |
12 | use Checkout\Placeholder\Model\System\ConfigInterface;
13 | use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
14 |
15 | class SpecificFieldConfig extends AbstractFieldArray implements ConfigInterface
16 | {
17 | protected function _prepareToRender()
18 | {
19 | $this->addColumn(
20 | self::COLUMN_KEY_FIELD_ID,
21 | ['label' => __('Field ID')]
22 | );
23 | $this->addColumn(
24 | self::COLUMN_KEY_PLACEHOLDER,
25 | ['label' => 'Placeholder']
26 | );
27 | $this->addColumn(
28 | self::COLUMN_KEY_FIELDSET_ID,
29 | ['label' => __('Fieldset ID')]
30 | );
31 | $this->_addAfter = false;
32 | $this->_addButtonLabel = __('Add');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Block/Onepage/PlaceholderProcessor.php:
--------------------------------------------------------------------------------
1 | arrayManager = $arrayManager;
29 | $this->fieldFilter = $fieldFilter;
30 | $this->config = $config;
31 | }
32 |
33 | /**
34 | * Search and convert all field lists.
35 | */
36 | private function processFields(array $jsLayout): array
37 | {
38 | $nodes = $this->fieldFilter->getLabeledFields($jsLayout);
39 | foreach ($nodes as $node) {
40 | $this->addPlaceholder($node);
41 | $jsLayout = $this->arrayManager->merge($node[self::KEY_PATH], $jsLayout, $node);
42 | }
43 | return $jsLayout;
44 | }
45 |
46 | private function addPlaceholder(array &$node): void
47 | {
48 | $config = $this->config->getFieldConfig($node[self::KEY_ID], $node[self::KEY_PATH]);
49 | $override = $config[Config::COLUMN_KEY_PLACEHOLDER] ?? '';
50 | $label = $override ?: $node[self::KEY_LABEL] ?? false;
51 | if ($label) {
52 | $label = ($label instanceof Phrase) ? (string)__($label) : $label;
53 | $customMark = $this->getRequiredEntryMark($node) ?: $this->getOptionalEntryMark($config);
54 | $placeholder = $label . ' ' . $customMark;
55 | $node['config'][Config::COLUMN_KEY_PLACEHOLDER] = trim($placeholder);
56 | }
57 | }
58 |
59 | private function getRequiredEntryMark(array &$field): string
60 | {
61 | $requiredChar = $this->config->getCustomRequiredMark() ?: '*';
62 | $isRequiredEntry = isset($field['validation']['required-entry'])
63 | && $field['validation']['required-entry']
64 | && $this->config->getEnableRequiredMark();
65 | return $isRequiredEntry ? $requiredChar : '';
66 | }
67 |
68 | private function getOptionalEntryMark($config): string
69 | {
70 | return $config[Config::SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK] ?? '';
71 | }
72 |
73 | /**
74 | * Processor init.
75 | *
76 | * @param array $jsLayout
77 | * @return array
78 | */
79 | public function process($jsLayout)
80 | {
81 | return $this->config->getEnable() ? $this->processFields($jsLayout) : $jsLayout;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | info@mediarox.de.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 mediarox
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Model/FieldFilter.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | declare(strict_types=1);
9 |
10 | namespace Checkout\Placeholder\Model;
11 |
12 | use Magento\Framework\Stdlib\ArrayManager;
13 |
14 | class FieldFilter implements PlaceholderInterface
15 | {
16 | protected ArrayManager $arrayManager;
17 |
18 | public function __construct(
19 | ArrayManager $arrayManager
20 | ) {
21 | $this->arrayManager = $arrayManager;
22 | }
23 |
24 | private function getFieldId(string $path)
25 | {
26 | $elements = explode(ArrayManager::DEFAULT_PATH_DELIMITER, $path);
27 | return array_pop($elements);
28 | }
29 |
30 | public function getLabeledFields(array $jsLayout): array
31 | {
32 | $checkoutRoot = $this->arrayManager->get(self::START_PATH_CHECKOUT_COMPONENTS_CHILDREN, $jsLayout);
33 | $componentPaths = $this->arrayManager->findPaths(
34 | self::KEY_LABEL,
35 | $checkoutRoot
36 | );
37 |
38 | $nodes = [];
39 | foreach ($componentPaths as $componentPath) {
40 | $componentPath = str_replace('/label', '', $componentPath);
41 | $node = $this->arrayManager->get($componentPath, $checkoutRoot);
42 | if ($node) {
43 | $node[self::KEY_ID] = $this->getFieldId($componentPath);
44 | $node[self::KEY_PATH] = self::START_PATH_CHECKOUT_COMPONENTS_CHILDREN .
45 | ArrayManager::DEFAULT_PATH_DELIMITER .
46 | $componentPath;
47 | $nodes[] = $node;
48 | }
49 | }
50 | return $nodes;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Model/PlaceholderInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Checkout\Placeholder\Model;
9 |
10 | interface PlaceholderInterface
11 | {
12 | const START_PATH_CHECKOUT_COMPONENTS_CHILDREN = 'components/checkout/children';
13 |
14 | const KEY_ID = 'id';
15 | const KEY_PATH = 'path';
16 | const KEY_LABEL = 'label';
17 | }
18 |
--------------------------------------------------------------------------------
/Model/System/Config.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | declare(strict_types=1);
9 |
10 | namespace Checkout\Placeholder\Model\System;
11 |
12 | use Magento\Framework\App\Config\ScopeConfigInterface;
13 | use Magento\Framework\Serialize\Serializer\Json;
14 | use Magento\Store\Model\ScopeInterface;
15 | use Magento\Store\Model\StoreManagerInterface;
16 |
17 | class Config implements ConfigInterface
18 | {
19 | protected StoreManagerInterface $storeManager;
20 | protected ScopeConfigInterface $scopeConfig;
21 | protected Json $json;
22 |
23 | public function __construct(StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig, Json $json)
24 | {
25 | $this->storeManager = $storeManager;
26 | $this->scopeConfig = $scopeConfig;
27 | $this->json = $json;
28 | }
29 |
30 | public function getConfigValue(string $key, string $basePath = self::SYSTEM_CONFIG_BASE_PATH_GENERAL)
31 | {
32 | return $this->scopeConfig->getValue(
33 | $basePath . $key,
34 | ScopeInterface::SCOPE_STORE,
35 | $this->storeManager->getStore()
36 | );
37 | }
38 |
39 | public function getEnable(): int
40 | {
41 | return (int)$this->getConfigValue(self::SYSTEM_CONFIG_KEY_ENABLE);
42 | }
43 |
44 | public function getCustomRequiredMark(): string
45 | {
46 | return $this->getConfigValue(self::SYSTEM_CONFIG_KEY_CUSTOM_REQUIRED_MARK) ?:
47 | self::DEFAULT_REQUIRED_MARK;
48 | }
49 |
50 | public function getEnableRequiredMark(): int
51 | {
52 | return (int)$this->getConfigValue(self::SYSTEM_CONFIG_KEY_ENABLE_REQUIRED_MARK);
53 | }
54 |
55 | public function getEnableOptionalMark()
56 | {
57 | return (int)$this->getConfigValue(
58 | self::SYSTEM_CONFIG_KEY_ENABLE,
59 | self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS
60 | );
61 | }
62 |
63 | public function getOptionalMark(): string
64 | {
65 | $optionalMark = $this->getConfigValue(
66 | self::SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK,
67 | self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS
68 | ) ?: self::DEFAULT_OPTIONAL_MARK;
69 |
70 | return $this->getEnableOptionalMark() ? $optionalMark : '';
71 | }
72 |
73 | public function getFieldConfig(string $fieldId, string $path): array
74 | {
75 | if (count(str_split($fieldId)) == 1) {
76 | $fieldId = self::COLUMN_KEY_STREET_PREFIX . $fieldId;
77 | }
78 |
79 | $configPaths = [
80 | self::SYSTEM_CONFIG_BASE_PATH_GENERAL => self::SYSTEM_CONFIG_KEY_SPECIFIC_FIELDS,
81 | self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS => self::SYSTEM_CONFIG_KEY_OPTIONAL_FIELDS,
82 | ];
83 |
84 | $config = [];
85 | foreach ($configPaths as $basePath => $configKey) {
86 | $systemValues = $this->getConfigValue($configKey, $basePath) ?
87 | $this->json->unserialize($this->getConfigValue($configKey, $basePath)) : [];
88 |
89 | foreach ($systemValues as $value) {
90 | if (array_shift($value) === $fieldId) {
91 | $isUnique = isset($value[self::COLUMN_KEY_FIELDSET_ID]) && !empty($value[self::COLUMN_KEY_FIELDSET_ID]);
92 | $correctPath = $isUnique ? strstr($path, $value[self::COLUMN_KEY_FIELDSET_ID]) : false;
93 | if ($isUnique && $correctPath) {
94 | $config = array_merge($config, $value);
95 | } elseif ($isUnique && !$correctPath) {
96 | continue;
97 | } else {
98 | $config = array_merge($config, $value);
99 | }
100 | if ($basePath == self::SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS) {
101 | $config[self::SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK] = $this->getOptionalMark();
102 | }
103 | }
104 | }
105 | }
106 | return $config;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Model/System/ConfigInterface.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | namespace Checkout\Placeholder\Model\System;
9 |
10 | interface ConfigInterface
11 | {
12 | const SYSTEM_CONFIG_BASE_PATH_GENERAL = 'checkout_placeholder/general/';
13 | const SYSTEM_CONFIG_KEY_ENABLE = 'enable';
14 | const SYSTEM_CONFIG_KEY_ENABLE_REQUIRED_MARK = 'enable_required_mark';
15 | const SYSTEM_CONFIG_KEY_CUSTOM_REQUIRED_MARK = 'custom_required_mark';
16 | const DEFAULT_REQUIRED_MARK = '*';
17 | const SYSTEM_CONFIG_KEY_SPECIFIC_FIELDS = 'specific_fields';
18 |
19 | const SYSTEM_CONFIG_BASE_PATH_OPTIONAL_MARKS = 'checkout_placeholder/optional_marks/';
20 | const SYSTEM_CONFIG_KEY_OPTIONAL_FIELDS = 'optional_fields';
21 | const SYSTEM_CONFIG_KEY_CUSTOM_OPTIONAL_MARK = 'custom_optional_mark';
22 | const DEFAULT_OPTIONAL_MARK = '(optional)';
23 |
24 | const COLUMN_KEY_STREET_PREFIX = 'street_';
25 | const COLUMN_KEY_FIELD_ID = 'field_id';
26 | const COLUMN_KEY_PLACEHOLDER = 'placeholder';
27 | const COLUMN_KEY_FIELDSET_ID = 'fieldset_id';
28 | const COLUMN_KEY_SEARCH_KEY = 'searchKey';
29 | }
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Checkout placeholder
2 |
3 | ## Description
4 | This module is designed to visually change all field pairs (label + field) so that the label is placed inside the field (As HTML Placeholder incl. "required-entry" mark "*"). Additionally, you can decide if you want to hide labels, define a custom required mark, hide required marks, customize placeholder text and mark fields as
5 | optional.
6 |
7 | ## Good to know
8 |
9 | Most of the fields in the checkout are collected via PHP and rendered dynamically via templates. For example, all input fields via the template `vendor/magento/module-ui/view/frontend/web/templates/form/element/input.html`.
10 | For all these dynamic fields we have created a [LayoutProcessor](https://devdocs.magento.com/guides/v2.4/howdoi/checkout/checkout_custom_checkbox.html) that provides the features described below.
11 |
12 | However, there are also fields that cannot be influenced via a LayoutProcessor.
13 | In a standard checkout these would be the fields:
14 | * email
15 | * password
16 | * password confirmation (if available)
17 |
18 | These fields are created together in the knockout template `Magento_Checkout/template/form/element/email` and are also not prepared for HTML placeholders by default.
19 | For these fields we provide at the moment only knockout templates overrides, which ensure that always (after installation) the label is used as a placeholder. Including the static required mark "*".
20 |
21 | As soon as time or a customer order allows, we would provide these fields with full features as well.
22 |
23 | ## Features
24 |
25 | * display field label as placeholder
26 | * customize placeholder text
27 | * hide labels
28 | * define a custom required mark
29 | * hide required mark
30 | * mark fields as optional
31 |
32 | ## Installation
33 | ```bash
34 | composer require mediarox/module-checkout-placeholder
35 | bin/magento setup:upgrade
36 | ```
37 |
38 | ## Configuration
39 |
40 | STORES > Configuration > MEDIAROX > Checkout Placeholder
41 |
42 | ### General
43 |
44 | #### Enable
45 | Enables the module. After activation, the field placeholders are filled with the label by default.
46 | * path: checkout_placeholder/general/enable
47 | * default: 0
48 |
49 | #### Hide Labels
50 | Enable this setting to hide labels.
51 | * path: checkout_placeholder/general/hide_labels
52 | * default: 0
53 |
54 | #### Show Required Mark
55 | Enable to display required marks.
56 | * path: checkout_placeholder/general/enable_required_mark
57 | * default: 1
58 |
59 | #### Custom Required Mark
60 | If you want to display a custom required mark enter it here.
61 | * path: checkout_placeholder/general/custom_required_mark
62 | * default: '*'
63 | * depends on: checkout_placeholder/general/enable_required_mark = 1
64 |
65 | #### Specific Fields
66 | To override placeholder content (label text) for specific fields enter the field_id and placeholder you want to display. If you need to customize a field that is used in multiple fieldsets (e.g. firstname is available in billing & shipping address) enter an additional, unique fieldset id (e.g. billing-address: 'form-fields', shipping-address: 'shipping-address-fieldset'). For street fields use the field_ids `street_0`, `street_1` and `street_2`.
67 | * path: checkout_placeholder/general/specific_fields
68 | * default: ''
69 |
70 | ### Optional Fields
71 |
72 | #### Enable:
73 | If enabled a custom optional mark will be applied to fields configured in *Optional Fields*.
74 | * path: checkout_placeholder/optional_marks/enable
75 | * default: 0
76 |
77 | #### Optional Mark:
78 | Enter your optional text/mark that you want to display here.
79 | * path: checkout_placeholder/optional_marks/custom_optional_mark
80 | * default: ''
81 |
82 | #### Mark Fields As Optional:
83 | Specify the fields you want to display an optional mark for here. If you need to customize a field that is used in multiple fieldsets (e.g. firstname is available in billing & shipping address) enter an additional, unique fieldset id (e.g. billing-address: 'form-fields', shipping-address: 'shipping-address-fieldset'). For street fields use the field_ids `street_0`, `street_1` and `street_2`.
84 | * path: checkout_placeholder/optional_marks/optional_fields
85 | * default: ''
86 |
87 | ## Compatible with
88 |
89 | * amzn/amazon-pay-module (deprecated core dependency), tested: 4.2.2
90 | * [amzn/amazon-pay-magento-2-module](https://marketplace.magento.com/amzn-amazon-pay-magento-2-module.html) (up-to-date amazon pay module), tested: 5.7.1, 5.9.1
91 | * [amasty/module-single-step-checkout](https://amasty.com/one-step-checkout-for-magento-2.html), tested: 3.1.2, 3.1.3, 4.0.0
92 |
93 | #### Wiki
94 |
95 | * [How do I add a custom checkout field ?](https://github.com/mediarox/module-checkout-placeholder/wiki/How-do-I-add-a-custom-checkout-field-%3F)
96 | * [What does the checkout look like with the Amasty Checkout module ?](https://github.com/mediarox/module-checkout-placeholder/wiki/What-does-the-checkout-look-like-with-the-Amasty-Checkout-module-%3F)
97 | * [What about Hyvä or the Hyvä Checkout ?](https://github.com/mediarox/module-checkout-placeholder/wiki/What-about-Hyv%C3%A4-or-the-Hyv%C3%A4-Checkout-%3F)
98 |
99 | #### Before
100 |
101 | 
102 |
103 | #### After
104 |
105 | 
106 |
--------------------------------------------------------------------------------
/ViewModel/ConfigViewModel.php:
--------------------------------------------------------------------------------
1 |
6 | */
7 |
8 | declare(strict_types=1);
9 |
10 | namespace Checkout\Placeholder\ViewModel;
11 |
12 | use Checkout\Placeholder\Model\System\Config;
13 | use Magento\Framework\View\Element\Block\ArgumentInterface;
14 |
15 | class ConfigViewModel implements ArgumentInterface
16 | {
17 | protected Config $config;
18 |
19 | public function __construct(Config $config)
20 | {
21 | $this->config = $config;
22 | }
23 |
24 | public function getConfig(): Config
25 | {
26 | return $this->config;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mediarox/module-checkout-placeholder",
3 | "description": "Show placeholders instead of labels at common checkout field's (incl. required entry mark).",
4 | "type": "magento2-module",
5 | "version": "0.4.3",
6 | "license": [
7 | "MIT"
8 | ],
9 | "require": {
10 | "php": "~7.4|~8.0|~8.1",
11 | "magento/framework": "103.0.*",
12 | "magento/module-checkout": "100.4.*"
13 | },
14 | "autoload": {
15 | "files": [
16 | "registration.php"
17 | ],
18 | "psr-4": {
19 | "Checkout\\Placeholder\\": ""
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |