├── .gitignore
├── view
├── frontend
│ ├── templates
│ │ ├── form
│ │ │ ├── additional_info.phtml
│ │ │ ├── blocks_container.phtml
│ │ │ ├── success.phtml
│ │ │ ├── action.phtml
│ │ │ └── tab.phtml
│ │ └── widget_form.phtml
│ ├── web
│ │ ├── css
│ │ │ └── source
│ │ │ │ └── _module.less
│ │ └── js
│ │ │ └── widget-form.js
│ └── layout
│ │ └── alekseon_widgetforms_form_success.xml
└── adminhtml
│ └── layout
│ └── alekseon_customformsbuilder_form_edit.xml
├── registration.php
├── Block
├── Form
│ ├── BlocksContainer.php
│ ├── Action.php
│ ├── AdditionalInfo.php
│ ├── Tab.php
│ └── Success.php
├── Adminhtml
│ └── Form
│ │ └── Edit
│ │ └── Tab
│ │ ├── NewsletterSettings.php
│ │ └── WidgetSettings.php
└── WidgetForm.php
├── Model
├── Attribute
│ └── Source
│ │ └── TextFormAttributes.php
└── Config
│ └── Source
│ └── AvailableForms.php
├── etc
├── frontend
│ ├── routes.xml
│ └── events.xml
├── module.xml
├── di.xml
├── adminhtml
│ ├── events.xml
│ └── di.xml
└── widget.xml
├── composer.json
├── .github
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
└── workflows
│ ├── coding-standard.yml
│ └── integration.yml
├── Observer
├── FormRecordAttributeSaveAfter.php
├── AddFrontendInputBlockOptions.php
└── SubscribeToNewsletter.php
├── Plugin
├── RemoveWidgetGroupAttributesFromGeneralTabPlugin.php
├── RemoveAttributesFromGeneralTabPlugin.php
├── AddFormFieldsetWarningPlugin.php
├── FromAttributeGroupCodesPlugin.php
└── NewsletterEmailValidatorPlugin.php
├── LICENCE
├── README.md
├── Controller
└── Form
│ ├── Success.php
│ └── Submit.php
├── CHANGELOG.md
└── Setup
└── Patch
└── Data
└── CreateWidgetFormsAttributesPatch.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .DS_Store
3 | Thumbs.db
--------------------------------------------------------------------------------
/view/frontend/templates/form/additional_info.phtml:
--------------------------------------------------------------------------------
1 |
9 | = $block->getChildHtml() ?>
10 |
--------------------------------------------------------------------------------
/view/frontend/templates/form/blocks_container.phtml:
--------------------------------------------------------------------------------
1 |
11 | = $block->getChildHtml() ?>
12 |
--------------------------------------------------------------------------------
/registration.php:
--------------------------------------------------------------------------------
1 | getForm();
13 | ?>
14 |
15 | = $block->getSuccessMessage(); ?>
16 |
17 |
--------------------------------------------------------------------------------
/Block/Form/Action.php:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/etc/frontend/events.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/view/frontend/templates/form/action.phtml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "alekseon/widget-forms",
3 | "description": "N/A",
4 | "require": {
5 | "alekseon/custom-forms-frontend": "^100.1.0",
6 | "alekseon/widget-forms-re-captcha": "100.2.*"
7 | },
8 | "type": "magento2-module",
9 | "version": "102.5.6",
10 | "license": [
11 | "OSL-3.0",
12 | "AFL-3.0"
13 | ],
14 | "autoload": {
15 | "files": [
16 | "registration.php"
17 | ],
18 | "psr-4": {
19 | "Alekseon\\WidgetForms\\": ""
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Block/Form/AdditionalInfo.php:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/etc/adminhtml/events.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Magento Version:**
27 | Example: Magento ver. 2.4.3-p3
28 |
29 | **Extension versions**
30 | Example: alekseon/widget-forms 102.2.0
31 |
32 | **Additional context**
33 | Add any other context about the problem here.
34 |
--------------------------------------------------------------------------------
/.github/workflows/coding-standard.yml:
--------------------------------------------------------------------------------
1 | name: M2 Coding Standard
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | phpcs:
6 | name: M2 Code Analysis
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v4
10 | - uses: extdn/github-actions-m2/magento-coding-standard/8.1@master
11 | with:
12 | phpcs_severity: 10
13 | phpcs_report: full
14 |
15 | phpmd:
16 | name: M2 Mess Detection
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v4
20 | - uses: extdn/github-actions-m2/magento-mess-detector@master
21 |
22 | phpstan:
23 | name: M2 PHPStan
24 | runs-on: ubuntu-latest
25 | steps:
26 | - uses: actions/checkout@v4
27 | - uses: extdn/github-actions-m2/magento-phpstan/8.3@master
28 | with:
29 | composer_name: alekseon/widget-forms
30 |
--------------------------------------------------------------------------------
/Observer/FormRecordAttributeSaveAfter.php:
--------------------------------------------------------------------------------
1 | getEvent()->getAttribute();
25 | if ($frontendInputBlock = $attribute->getFrontendInputBlock()) {
26 | $attribute->setAttributeExtraParam('frontend_input_block', $frontendInputBlock);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Plugin/RemoveWidgetGroupAttributesFromGeneralTabPlugin.php:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Alekseon Ltd.
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 | © 2020 GitHub, Inc.
--------------------------------------------------------------------------------
/view/adminhtml/layout/alekseon_customformsbuilder_form_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 | form_widget_settings_tab
14 | form_widget_settings_tab
15 |
16 |
17 |
18 | newsletter_settings_tab
19 | newsletter_settings_tab
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/view/frontend/templates/form/tab.phtml:
--------------------------------------------------------------------------------
1 |
12 |
25 | getTab()->getIsFirstTab()): ?>style="display: none">
28 | = $block->getSubmitButtonHtml() ?>
29 |
30 |
--------------------------------------------------------------------------------
/.github/workflows/integration.yml:
--------------------------------------------------------------------------------
1 | name: M2 Integration Tests
2 | on:
3 | push:
4 | branches:
5 | - master
6 | pull_request:
7 |
8 | jobs:
9 | integration-tests:
10 | name: Magento 2 Integration Tests
11 | runs-on: ubuntu-latest
12 | services:
13 | mysql:
14 | image: mysql:5.7
15 | env:
16 | MYSQL_ROOT_PASSWORD: root
17 | ports:
18 | - 3306:3306
19 | options: --tmpfs /tmp:rw --tmpfs /var/lib/mysql:rw --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
20 | es:
21 | image: docker.io/wardenenv/elasticsearch:7.8
22 | ports:
23 | - 9200:9200
24 | env:
25 | 'discovery.type': single-node
26 | 'xpack.security.enabled': false
27 | ES_JAVA_OPTS: "-Xms64m -Xmx512m"
28 | options: --health-cmd="curl localhost:9200/_cluster/health?wait_for_status=yellow&timeout=60s" --health-interval=10s --health-timeout=5s --health-retries=3
29 | steps:
30 | - uses: actions/checkout@v4
31 | - name: M2 Integration Tests with Magento 2 (Php 8.3)
32 | uses: extdn/github-actions-m2/magento-integration-tests/8.3@master
33 | with:
34 | module_name: Alekseon_WidgetForms
35 | composer_name: alekseon/widget-forms
36 | ce_version: '2.4.0'
37 |
--------------------------------------------------------------------------------
/Plugin/AddFormFieldsetWarningPlugin.php:
--------------------------------------------------------------------------------
1 | getDataObject();
27 |
28 | if ($form->getCanUseForWidget()) {
29 | $frontendInputTypeConfig = $attribute->getFrontendInputTypeConfig();
30 | if ($frontendInputTypeConfig) {
31 | $frontendBlocks = $frontendInputTypeConfig->getFrontendBlocks();
32 |
33 | if (!isset($frontendBlocks['default'])) {
34 | $formFieldSettings['warnings'][] = __(
35 | 'Frontend input %1 is not supported by form widgets.',
36 | $frontendInputTypeConfig->getLabel()
37 | );
38 | }
39 | }
40 | }
41 |
42 | return $formFieldSettings;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Plugin/FromAttributeGroupCodesPlugin.php:
--------------------------------------------------------------------------------
1 | formRepository = $formRepository;
30 | }
31 |
32 | /**
33 | * @param $attribute
34 | * @param $result
35 | * @return bool
36 | * @throws \Magento\Framework\Exception\NoSuchEntityException
37 | */
38 | public function afterGetCanUseGroup($attribute, $result)
39 | {
40 | $form = $this->formRepository->getById($attribute->getFormId());
41 | return $form->getCanUseForWidget() || $result;
42 | }
43 |
44 | /**
45 | * @param $attribute
46 | * @param $result
47 | * @return bool
48 | * @throws \Magento\Framework\Exception\NoSuchEntityException
49 | */
50 | public function afterGetIsGroupEditable($attribute, $result)
51 | {
52 | $form = $this->formRepository->getById($attribute->getFormId());
53 | if ($form->getCanUseForWidget()) {
54 | return false;
55 | }
56 | return $result;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/view/frontend/templates/widget_form.phtml:
--------------------------------------------------------------------------------
1 |
12 | getForm()): ?>
13 |
14 |
23 | = $block->getBlocksContainer('after_form')->toHtml() ?>
24 |
25 |
38 |
39 |
--------------------------------------------------------------------------------
/Block/Form/Tab.php:
--------------------------------------------------------------------------------
1 | getLayout()->createBlock(
31 | \Alekseon\WidgetForms\Block\Form\Action::class,
32 | 'form_' . $this->getForm()->getId() . '_action_' . $this->getTab()->getId(),
33 | [
34 | 'data' => [
35 | 'submit_button_label' => $this->getSubmitButtonLabel()
36 | ],
37 | ]
38 | )->toHtml();
39 | }
40 |
41 | /**
42 | * @return \Magento\Framework\Phrase
43 | */
44 | private function getSubmitButtonLabel()
45 | {
46 | if (!$this->getTab()->getIsLastTab()) {
47 | return __('Next');
48 | }
49 |
50 | $form = $this->getForm();
51 | if ($form && $form->getSubmitButtonLabel()) {
52 | return $form->getSubmitButtonLabel();
53 | }
54 |
55 | return __('Submit');
56 | }
57 |
58 | /**
59 | * @return \Alekseon\WidgetForms\Block\WidgetForm
60 | */
61 | public function getWidgetFormBlock()
62 | {
63 | return $this->getParentBlock()->getParentBlock();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Plugin/NewsletterEmailValidatorPlugin.php:
--------------------------------------------------------------------------------
1 | formRepository = $formRepository;
40 | $this->emailValidatorFactory = $emailValidatorFactory;
41 | }
42 |
43 | /**
44 | * @param Attribute $attribute
45 | * @param $validator
46 | */
47 | public function afterGetInputValidators(Attribute $attribute, $validators)
48 | {
49 | $formId = $attribute->getFormId();
50 | $form = $this->formRepository->getById($formId);
51 |
52 | if ($form->getSubscribeToNewsletter() && $form->getNewsletterEmail() == $attribute->getAttributeCode()) {
53 | $emailValidator = $this->emailValidatorFactory->create();
54 | if (!isset($validators[$emailValidator->getCode()])) {
55 | $validators[] = $emailValidator;
56 | }
57 | }
58 |
59 | return $validators;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Block/Form/Success.php:
--------------------------------------------------------------------------------
1 | formRepository = $formRepository;
47 | parent::__construct($context, $data);
48 | }
49 |
50 | /**
51 | * @return \Alekseon\CustomFormsBuilder\Model\Form|false
52 | */
53 | public function getForm()
54 | {
55 | if ($this->form === null) {
56 | $formId = (int)$this->getData('form_id');
57 | $form = false;
58 | if ($formId) {
59 | try {
60 | $form = $this->formRepository->getById($formId, null, true);
61 | } catch (\Exception $e) {
62 | }
63 | }
64 |
65 | $this->form = $form;
66 | }
67 |
68 | return $this->form;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Observer/AddFrontendInputBlockOptions.php:
--------------------------------------------------------------------------------
1 | getEvent()->getFormFieldId();
25 | $fieldset = $observer->getEvent()->getFieldset();
26 | $fieldSettings = $observer->getEvent()->getFieldSettings();
27 |
28 | if (!isset($fieldSettings['attribute'])) {
29 | return;
30 | }
31 |
32 | $attribute = $fieldSettings['attribute'];
33 | $attribute->setFrontendInputBlock($attribute->getAttributeExtraParam('frontend_input_block'));
34 |
35 | $frontendInputTypeConfig = $attribute->getFrontendInputTypeConfig();
36 | if ($frontendInputTypeConfig) {
37 | $frontendBlocks = $frontendInputTypeConfig->getFrontendBlocks();
38 | } else {
39 | $frontendBlocks = [];
40 | }
41 |
42 | if (is_array($frontendBlocks) && count($frontendBlocks) > 1 ) {
43 |
44 | $options = [];
45 | foreach ($frontendBlocks as $code => $data) {
46 | $options[] = [
47 | 'value' => $code,
48 | 'label' => __($data['label']),
49 | ];
50 | }
51 |
52 | $fieldset->addField('form_field_' . $formFieldId . '_frontend_input_block', 'select',
53 | [
54 | 'label' => __('Input Block Type'),
55 | 'name' => 'form_fields[' . $formFieldId . '][frontend_input_block]',
56 | 'values' => $options,
57 | ]
58 | )->addCustomAttribute("data-fieldcode", "frontend_input_block");
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/etc/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
11 |
12 | Widget Form
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Model/Config/Source/AvailableForms.php:
--------------------------------------------------------------------------------
1 | formCollectionFactory = $formCollectionFactory;
34 | }
35 |
36 | /**
37 | * @return array
38 | * @throws \Magento\Framework\Exception\LocalizedException
39 | */
40 | public function toOptionArray()
41 | {
42 | $optionArray = [
43 | '' => __('-- Not Selected --'),
44 | ];
45 | $options = $this->toArray();
46 | foreach ($options as $optionId => $optionLabel)
47 | {
48 | $optionArray[$optionId] = $optionLabel;
49 | }
50 | return $optionArray;
51 | }
52 |
53 | /**
54 | * @return array|null
55 | * @throws \Magento\Framework\Exception\LocalizedException
56 | */
57 | public function toArray()
58 | {
59 | if ($this->options === null) {
60 | $this->options = [];
61 | $formCollection = $this->formCollectionFactory->create();
62 | $formCollection->addAttributeToSelect('title');
63 | $formCollection->addAttributeToFilter('can_use_for_widget', true);
64 |
65 | foreach ($formCollection as $form) {
66 | $this->options[$form->getId()] = $form->getTitle();
67 | }
68 | }
69 | return $this->options;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Edit/Tab/NewsletterSettings.php:
--------------------------------------------------------------------------------
1 | getDataObject()->getCanUseForWidget();
43 | }
44 |
45 | /**
46 | * {@inheritdoc}
47 | */
48 | public function isHidden()
49 | {
50 | return false;
51 | }
52 |
53 | /**
54 | * @return mixed
55 | */
56 | public function getDataObject()
57 | {
58 | return $this->_coreRegistry->registry('current_form');
59 | }
60 |
61 | /**
62 | * @return $this
63 | * @throws \Magento\Framework\Exception\LocalizedException
64 | */
65 | protected function _prepareForm()
66 | {
67 | $dataObject = $this->getDataObject();
68 |
69 | /** @var \Magento\Framework\Data\Form $form */
70 | $form = $this->_formFactory->create();
71 | $newsletterFieldset = $form->addFieldset('newsletter_settings_fieldset',
72 | [
73 | 'legend' => __('Newsletter Settings')
74 | ]
75 | );
76 | $this->addAllAttributeFields($newsletterFieldset, $dataObject,['included' => ['newsletter']]);
77 | $this->setForm($form);
78 |
79 | return parent::_prepareForm();
80 | }
81 |
82 |
83 | /**
84 | * Initialize form fileds values
85 | *
86 | * @return $this
87 | */
88 | protected function _initFormValues()
89 | {
90 | $this->getForm()->addValues($this->getDataObject()->getData());
91 | return parent::_initFormValues();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Edit/Tab/WidgetSettings.php:
--------------------------------------------------------------------------------
1 | getDataObject()->getCanUseForWidget();
43 | }
44 |
45 | /**
46 | * {@inheritdoc}
47 | */
48 | public function isHidden()
49 | {
50 | return false;
51 | }
52 |
53 | /**
54 | * @return mixed
55 | */
56 | public function getDataObject()
57 | {
58 | return $this->_coreRegistry->registry('current_form');
59 | }
60 |
61 | /**
62 | * @return $this
63 | * @throws \Magento\Framework\Exception\LocalizedException
64 | */
65 | protected function _prepareForm()
66 | {
67 | $dataObject = $this->getDataObject();
68 |
69 | /** @var \Magento\Framework\Data\Form $form */
70 | $form = $this->_formFactory->create();
71 | $widgetFieldset = $form->addFieldset('widget_settings_fieldset', ['legend' => __('Widget Settings')]);
72 | $this->addAllAttributeFields($widgetFieldset, $dataObject, ['included' => ['widget_form_attribute']]);
73 | $this->setForm($form);
74 |
75 | return parent::_prepareForm();
76 | }
77 |
78 |
79 | /**
80 | * Initialize form fileds values
81 | *
82 | * @return $this
83 | */
84 | protected function _initFormValues()
85 | {
86 | $this->getForm()->addValues($this->getDataObject()->getData());
87 | return parent::_initFormValues();
88 | }
89 |
90 |
91 | /**
92 | * @inheritDoc
93 | */
94 | protected function _addAdditionalFormElementData(AbstractElement $element)
95 | {
96 | if (in_array($element->getId(), ['form_submit_success_message', 'form_submit_success_title'])) {
97 | $element->setNote(
98 | ''
99 | . __('Template Variables')
100 | . ' '
101 | . __( ' are allowed.'));
102 | }
103 |
104 | return parent::_addAdditionalFormElementData($element);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/view/frontend/web/js/widget-form.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright © Alekseon sp. z o.o.
3 | * http://www.alekseon.com/
4 | */
5 | define([
6 | 'jquery',
7 | 'Magento_Ui/js/modal/alert'
8 | ], function ($, alert) {
9 | 'use strict';
10 |
11 | $.widget('mage.alekseonWidgetForm', {
12 |
13 | options: {
14 | currentTab: 1,
15 | tabs: [],
16 | form: null,
17 | formSubmitUrl: 'formSubmitUrl',
18 | formId: '',
19 | success_mode: '',
20 | formSuccessUrl: ''
21 | },
22 |
23 | _create: function () {
24 | let self = this;
25 | this.options.form = $('#' + this.options.formId)[0];
26 | $(this.options.form).submit(function (event) {
27 | self.submitFormAction();
28 | event.preventDefault(event);
29 | });
30 | },
31 |
32 | openTab: function (form, tabIndex) {
33 | $(this.options.form).find('#form-tab-fieldset-' + this.options.currentTab).slideUp();
34 | $(this.options.form).find('#form-tab-actions-' + this.options.currentTab).hide();
35 |
36 | setTimeout(() => {
37 | this.options.currentTab = tabIndex;
38 |
39 | $(this.options.form).find('#form-tab-fieldset-' + this.options.currentTab).slideDown();
40 | $(this.options.form).find('#form-tab-actions-' + this.options.currentTab).show();
41 | }, "100");
42 | },
43 |
44 | submitFormAction: function () {
45 | if ($(this.options.form).validation && !$(this.options.form).validation('isValid')) {
46 | return false;
47 | }
48 |
49 | if (this.options.tabs[this.options.currentTab + 1] !== undefined) {
50 | this.openTab(this.options, this.options.currentTab + 1);
51 | return;
52 | }
53 |
54 | let self = this;
55 | const formData = new FormData(this.options.form);
56 |
57 | $.ajax({
58 | url: this.options.formSubmitUrl,
59 | type: 'POST',
60 | data: formData,
61 | processData: false,
62 | contentType: false,
63 | dataType: 'json',
64 | showLoader: true
65 | }).done(function (response) {
66 | if (response.errors) {
67 | self.onError(response);
68 | } else {
69 | self.onSuccess(response);
70 | }
71 | }).fail(function (error) {
72 | self.onError(error.responseJSON);
73 | }).always(function() {
74 | self.onComplete();
75 | });
76 | },
77 |
78 | onComplete: function() {
79 | },
80 |
81 | onError: function(response) {
82 | alert({
83 | title: $.mage.__('Error'),
84 | content: response.message
85 | });
86 | },
87 |
88 | onSuccess: function(response) {
89 | if (this.options.success_mode === 'form') {
90 | this.options.form.parentElement.innerHTML = response.message;
91 | } else if (this.success_mode === 'success_page') {
92 | window.location.href = this.formSuccessUrl;
93 | return;
94 | } else {
95 | alert({
96 | title: response.title,
97 | content: response.message
98 | });
99 | }
100 | this.options.form.reset();
101 | if (this.options.currentTab !== 1) {
102 | this.openTab(this.options.form, 1);
103 | }
104 | }
105 | });
106 |
107 | return $.mage.alekseonWidgetForm;
108 | });
109 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Alekseon_WidgetForms
7 |
8 |
9 |
10 | Place forms as widgets to CMS page in Magento 2
11 |
12 | Let you add forms to CMS pages
13 |
14 | ## Demo
15 |
16 | https://widget-forms.alekseon.com/
17 |
18 | ## Examples of usage
19 |
20 | - Ask About Product
21 | - Multi-step Survey (soon)
22 |
23 | ## Videos
24 |
25 |
34 |
35 | ## Installation
36 |
37 | In your Magento2 root directory, you may install this package via composer:
38 |
39 | ```
40 | composer require alekseon/widget-forms
41 | bin/magento setup:upgrade
42 | ```
43 |
44 |
45 | ## Support
46 |
47 | CJM Ver. | Magento 2.0 | Magento 2.1 | Magento 2.2 | Magento 2.3 | Magento 2.4
48 | --- | :---: | :---: | :---: | :---: | :---:
49 | 1.x | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark:
50 |
51 |
52 | ## Features
53 |
54 | ### Add Forms to CMS Pages
55 |
56 | You can place any Form you will create by [Alekseon_CustomFormsBuilder](https://github.com/Alekseon/magento2-custom-forms-builder) extension to CMS page.
57 |
58 | Visit our [alekseon.com](https://alekseon.com/en/blog/post/module-widget-forms/) website for more information about the Widget.
59 |
60 |
61 |
62 | ## Hyvä Theme compatibility
63 |
64 | [
](https://hyva.io/)
65 |
66 | Alekseon_WidgetForms is also available as a [Compatibility module](https://gitlab.hyva.io/hyva-public/module-tracker/-/issues/236) for [Hyvä Themes](https://hyva.io/)
67 |
68 | ## Issue Tracking / Upcoming Features
69 |
70 | For issues, please use the [issue tracker](https://github.com/Alekseon/widget-forms/issues).
71 |
72 | Issues keep this project alive and strong, so let us know if you find anything!
73 |
76 | ### Development / Contribution
77 |
78 | If you want to contribute please follow the below instructions:
79 |
80 | 1. Create an issue and describe your idea
81 | 2. [Fork this repository](https://github.com/Alekseon/widget-forms/fork)
82 | 3. Create your feature branch (`git checkout -b my-new-feature`)
83 | 4. Commit your changes
84 | 5. Publish the branch (`git push origin my-new-feature`)
85 | 6. Submit a new Pull Request for review
86 |
87 | ## Wiki
88 |
89 | https://github.com/Alekseon/magento2-widget-forms/wiki
90 |
91 | ## Maintainers
92 |
93 | Current maintainers:
94 |
95 | * [Linek](https://github.com/Linek)
96 | * [marcinfr](https://github.com/marcinfr)
97 |
98 | See also our [contributors](https://github.com/Alekseon/widget-forms/graphs/contributors)
99 |
100 |
101 | ## License
102 |
103 | [The Open Software License 3.0 (OSL-3.0)](https://opensource.org/licenses/OSL-3.0)
104 |
--------------------------------------------------------------------------------
/Observer/SubscribeToNewsletter.php:
--------------------------------------------------------------------------------
1 | subscriptionManager = $subscriptionManager;
62 | $this->storeManager = $storeManager;
63 | $this->customerSession = $customerSession;
64 | $this->customerAccountManagement = $customerAccountManagement;
65 | $this->eventManager = $eventManager;
66 | }
67 |
68 | /**
69 | * Execute
70 | *
71 | * @param Observer $observer
72 | */
73 | public function execute(Observer $observer)
74 | {
75 | $formRecord = $observer->getEvent()->getFormRecord();
76 | $form = $formRecord->getForm();
77 |
78 | if ($form->getSubscribeToNewsletter()) {
79 | $emailField = $form->getNewsletterEmail();
80 | $email = $formRecord->getData($emailField);
81 | $storeId = (int) $this->storeManager->getStore()->getId();
82 | if ($email) {
83 | $this->validateEmailAvailable($email);
84 | $customerId = $this->getCurrentCustomerId();
85 | if ($customerId) {
86 | $subscriber = $this->subscriptionManager->subscribeCustomer($customerId, $storeId);
87 | } else {
88 | $subscriber = $this->subscriptionManager->subscribe($email, $storeId);
89 | }
90 | $this->eventManager->dispatch(
91 | 'alekseon_widget_form_after_subscribe',
92 | [
93 | 'form_record' => $formRecord,
94 | 'subscriber' => $subscriber,
95 | ]
96 | );
97 | }
98 | }
99 | }
100 |
101 | /**
102 | * @return false | int
103 | */
104 | private function getCurrentCustomerId()
105 | {
106 | if ($this->customerSession->isLoggedIn()) {
107 | return $this->customerSession->getCustomerDataObject()->getId();
108 | }
109 |
110 | return false;
111 | }
112 |
113 | /**
114 | * @param $email
115 | */
116 | private function validateEmailAvailable($email)
117 | {
118 | $websiteId = $this->storeManager->getStore()->getWebsiteId();
119 | if ($this->customerSession->isLoggedIn()
120 | && ($this->customerSession->getCustomerDataObject()->getEmail() !== $email
121 | && !$this->customerAccountManagement->isEmailAvailable($email, $websiteId))
122 | ) {
123 | throw new LocalizedException(
124 | __('This email address is already assigned to another user.')
125 | );
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/Controller/Form/Success.php:
--------------------------------------------------------------------------------
1 | request = $context->getRequest();
61 | $this->resultPageFactory = $resultPageFactory;
62 | $this->formRepository = $formRepository;
63 | $this->templateFilter = $templateFilter;
64 | $this->customerSession = $customerSession;
65 | $this->resultForwardFactory = $resultForwardFactory;
66 | }
67 |
68 | /**
69 | * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
70 | */
71 | public function execute()
72 | {
73 | $customerFormId = $this->customerSession->getWidgetFormsSubmitFormId();
74 | $form = $this->getForm();
75 | if (!$form || !$customerFormId) {
76 | return $this->resultForwardFactory->create()->forward('noroute');
77 | }
78 |
79 | if ($form->getId() != $customerFormId) {
80 | return $this->resultForwardFactory->create()->forward('noroute');
81 | }
82 | $this->customerSession->setWidgetFormsSubmitFormId(null);
83 |
84 | $resultPage = $this->resultPageFactory->create();
85 | $resultPage->initLayout();
86 | $successBlock = $resultPage->getLayout()->getBlock(
87 | 'widgetforms_success'
88 | );
89 |
90 | if ($successBlock) {
91 | $successBlock->setData('form_id', $form->getId());
92 | $successBlock->setData('success_message', $this->getSuccessMessage($form));
93 | }
94 | $resultPage->getConfig()->getTitle()->append($form->getTitle());
95 | $resultPage->getConfig()->getTitle()->set($this->getSuccessTitle($form));
96 | return $resultPage;
97 | }
98 |
99 | /**
100 | * @param $form
101 | * @return string
102 | */
103 | public function getSuccessMessage($form)
104 | {
105 | $successMessage = $form->getFormSubmitSuccessMessage();
106 | if ($successMessage) {
107 | $successMessage = $this->templateFilter->filter($successMessage);
108 | } else {
109 | $successMessage = __('Thank You!');
110 | }
111 | return (string) $successMessage;
112 | }
113 |
114 | /**
115 | * @param $form
116 | * @return string
117 | */
118 | public function getSuccessTitle($form)
119 | {
120 | $successTitle = $form->getFormSubmitSuccessTitle();
121 | if (!$successTitle) {
122 | $successTitle = __('Success');
123 | }
124 | return (string) $successTitle;
125 | }
126 |
127 | /**
128 | * @return \Alekseon\CustomFormsBuilder\Model\Form|false
129 | * @throws NoSuchEntityException
130 | */
131 | public function getForm()
132 | {
133 | $formId = $this->getRequest()->getParam('form_id');
134 | $form = false;
135 | if ($formId) {
136 | try {
137 | $form = $this->formRepository->getByIdentifier($formId, null, true);
138 | } catch (\Exception $e) {}
139 | } else {
140 | try {
141 | $form = $this->formRepository->getById($formId, null, true);
142 | } catch (\Exception $e) {}
143 | }
144 |
145 | if ($form && $form->getCanUseForWidget()) {
146 | return $form;
147 | } else {
148 | return false;
149 | }
150 | }
151 |
152 | /**
153 | * @return \Magento\Framework\App\RequestInterface
154 | */
155 | public function getRequest()
156 | {
157 | return $this->request;
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6 |
7 | ## [Unreleased]
8 | ### Changed
9 | ### Fixed
10 | ### Added
11 | ### Removed
12 |
13 | ## [102.5.6] - 2025-06-17
14 | ### Fixed
15 | - set form_id as required in widget
16 | ### Added
17 | - "Not Selected" option in available forms options
18 |
19 | ## [102.5.5] - 2025-01-22
20 | ### Fixed
21 | - widget option - Success display mode - some CS fixes
22 |
23 | ## [102.5.4] - 2025-01-17
24 | ### Added
25 | - widget option - Success display mode - redirect to Success Page
26 |
27 | ## [102.5.3] - 2024-11-28
28 | ### changed
29 | - revert last changes (use prepareLayout) - when widget has been added by admin/content/widgets, widget data was not set yet
30 |
31 | ## [102.5.2] - 2024-11-17
32 | ### changed
33 | - use prepareLayout method instead of toHtml
34 |
35 | ## [102.5.1] - 2024-11-14
36 | ### Fixed
37 | - fix for missing form title and description
38 |
39 | ## [102.5.0] - 2024-11-07
40 | ### Changed
41 | - group tabs in tabs_container
42 | ### Added
43 | - after_form blocks caontainer
44 | - form object in alekseon_widget_form_after_submit event
45 |
46 | ## [102.4.4] - 2024-09-25
47 | ### Changed
48 | - removed success cms block from widget configuration and allow cms block in Form Submit Success Message
49 | ### Added
50 | - alekseon_widget_form_after_subscribe event
51 |
52 | ## [102.4.3] - 2024-06-24
53 | ### Added
54 | - added success display mode option
55 |
56 | ## [102.4.2] - 2024-06-24
57 | ### Changed
58 | - Translate labels (https://github.com/Alekseon/AlekseonEav/issues/45)
59 |
60 | ## [102.4.1] - 2024-02-26
61 | ### Fixed
62 | - fix ajax error: "complete is not a function"
63 |
64 | ## [102.4.0] - 2023-12-03
65 | ### Changed
66 | - refactoring - removed UI component on frontend
67 |
68 | ## [102.3.0] - 2023-06-21
69 | ### Changed
70 | - frontend inputs moved from Alekseon_WidgetForms to Alekseon_CustonFormsFrontend
71 | ### Added
72 | - form wrapper class
73 |
74 | ## [102.2.7] - 2023-05-02
75 | ### Changed
76 | - changes for tests in github actions
77 |
78 | ## [102.2.6] - 2023-05-01
79 | ### Added
80 | - added email validation for newsletter email input in admin
81 | ### Fixed
82 | - code quality fixes (https://github.com/Alekseon/magento2-widget-forms/issues/17)
83 |
84 | ## [102.2.3] - 2023-03-28
85 | ### Added
86 | - field containers css classes (for hyva)
87 |
88 | ## [102.2.2] - 2023-03-12
89 | ### Fixed
90 | - fix for cache issue
91 | - removed gap and fix label displaye in image input template
92 |
93 | ## [102.2.1] - 2023-03-12
94 | ### Added
95 | - "*" for required fields
96 | - cache tags
97 | ### Fixed
98 | - select default value on radio button input
99 | - stop opening first tab after submit if there is only one tab
100 |
101 | ## [102.2.0] - 2023-03-04
102 | ### Added
103 | - rating type input (stars)
104 | ### Fixed
105 | - default values for select
106 | - fix widget html code
107 |
108 | ## [102.1.6] - 2023-02-27
109 | ### Fixed
110 | - fix for backward compatibility
111 |
112 | ## [102.1.5] - 2022-11-22
113 | ### Added
114 | - class "widget-form-fields-container" for div container
115 |
116 | ## [102.1.4] - 2022-11-19
117 | ### Changed
118 | - modifications for native magento captcha
119 | ### Fixed
120 | - decreased gap between form and submit button
121 |
122 | ## [102.1.3] - 2022-10-27
123 | ### Added
124 | - email validation for logged in customers
125 | - subsribe to newsletter as customer if logged in
126 | ### Fixed
127 | - fix for install data
128 |
129 | ## [102.1.2] - 2022-10-22
130 | ### Changed
131 | - change widget block parameter identifier to form_identifier
132 |
133 | ## [102.1.1] - 2022-10-22
134 | ### Removed
135 | - removed FormSubmitFailureMessage attribute
136 | ### Added
137 | - added FormSubmitSuccessTitle attribute
138 | ### Changed
139 | - changes in displaying success/error messages on form submit
140 |
141 | ## [102.1.0] - 2022-10-22
142 | ### Fixed
143 | - fix infinite loading on submit where returned server error
144 | ## Added
145 | - current product default value
146 | - customer email default value
147 | - hidden text input type block
148 | - form identifier parameter for widget
149 | - create getter methods for success and failure message
150 | - current cms page default value provider
151 | - default text defaul value provider
152 |
153 | ## [102.0.23]
154 | ### Fixed
155 | - fix for warning in isSelected method for Select Field
156 | - fix validation for newsletter email
157 | ### Changed
158 | - TextFormAttribute source extends from CustomFormBuilder module
159 |
160 | ## [102.0.22] - 2022-10-06
161 | ### Fixed
162 | - compatibility to attribute default values
163 |
164 | ## [102.0.21] - 2022-10-05
165 | ### Added
166 | - compatibility to attribute default values
167 |
168 | ## [102.0.19] - 2022-10-04
169 | ### Changed
170 | - changed composer requirements
171 | - modification for input validations
172 |
173 | ## [102.0.18] - 2022-09-27
174 | ### Added
175 | - images input
176 | - max length for textarea
177 |
178 | ## [102.0.17] - 2022-09-02
179 | ### Added
180 | - new template checkbox_vertical for multiselected checkbox
181 |
182 | ## [102.0.16] - 2022-09-02
183 | ### Added
184 | - allow to set tempate on frontend block by di.xml
185 |
186 | ## [102.0.15] - 2022-08-04
187 | ### Fixed
188 | - fixed Magento 2.4.4 issue with closing the short tag in knockout templates
189 |
190 | ## [102.0.14] - 2022-07-07
191 | ### Fixed
192 | - form_key is now passed to Form from frontend
193 |
194 | ## [102.0.13] - 2022-07-07
195 | ### Added
196 | - added input=date field to frontend
197 |
198 | ## [102.0.12] - 2022-06-15
199 | ### Fixed
200 | - changed web template to render title and description as html
201 |
202 | ## [102.0.11] - 2022-06-14
203 | ### Fixed
204 | - template rendering checkbox input when it is boolean type
205 |
206 | ## [102.0.10] - 2022-06-01
207 | ### Added
208 | - added css className to the form wrapper element
209 |
210 | ## [102.0.9] - 2022-05-31
211 | ### Added
212 | - added form submit failure message
213 | ### Changed
214 | - form submit success message is now wysiwyg field
215 | ### Fixed
216 | - some typos
217 |
218 | ## [102.0.8] - 2022-05-02
219 | ### Added
220 | - checkbox intup block type for multiselect
221 | - subscribe to newsetter
222 | ### Changed
223 | - Removed widget forms from menu. Now its done by CustomFormsBuilder module
224 |
225 | ## [102.0.7] - 2022-04-14
226 | ### Fixed
227 | - fix for widgets with non existing forms
228 | - fix for non validated items in admin menu, for example with too long title
229 |
230 | ## [102.0.5] - 2022-04-01
231 | ### Added
232 | - multiselect input
233 |
234 | ## [102.0.4] - 2022-04-01
235 | ### Added
236 | - require for checkbox input
237 |
238 | ## [102.0.3]
239 | ### Changed
240 | - rewrited widget forms to ui component on frontend
241 | - changes to be campatible for recaptcha module
242 | ### Added
243 | - empty option for select input
244 | - log error during form submition
245 | - form input types options (checkbox and radio buttons)
246 |
247 | ## [102.0.2] - 2020-10-15
248 | ### Added
249 | - Added compatibility with Magento 2.4.0
250 |
251 | ## [101.0.0] - 2020-04-27
252 | ### Added
253 | - init
254 |
255 |
--------------------------------------------------------------------------------
/Controller/Form/Submit.php:
--------------------------------------------------------------------------------
1 | request = $context->getRequest();
79 | $this->response = $context->getResponse();
80 | $this->eventManager = $context->getEventManager();
81 | $this->formRecordFactory = $formRecordFactory;
82 | $this->jsonFactory = $jsonFactory;
83 | $this->formRepository = $formRepository;
84 | $this->formKeyValidator = $formKeyValidator;
85 | $this->templateFilter = $templateFilter;
86 | $this->logger = $logger;
87 | $this->customerSession = $customerSession;
88 | }
89 |
90 | /**
91 | * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
92 | */
93 | public function execute()
94 | {
95 | $resultJson = $this->jsonFactory->create();
96 |
97 | try {
98 | $form = $this->getForm();
99 | $this->validateData();
100 | $post = $this->getRequest()->getPost();
101 | $formRecord = $this->formRecordFactory->create();
102 | $formRecord->getResource()->setCurrentForm($form);
103 | $formRecord->setStoreId((int) $form->getStoreId());
104 | $formRecord->setFormId($form->getId());
105 | $formFields = $form->getFieldsCollection();
106 | foreach ($formFields as $field) {
107 | $fieldCode = $field->getAttributeCode();
108 | $value = $post[$fieldCode] ?? $field->getDefaultValue();
109 | $formRecord->setData($fieldCode, $value);
110 | }
111 |
112 | $formRecord->getResource()->save($formRecord);
113 | $this->eventManager->dispatch(
114 | 'alekseon_widget_form_after_submit',
115 | [
116 | 'form_record' => $formRecord,
117 | 'form' => $form,
118 | ]
119 | );
120 | $resultJson->setData(
121 | [
122 | 'errors' => false,
123 | 'title' => $this->getSuccessTitle($formRecord),
124 | 'message' => $this->getSuccessMessage($formRecord),
125 | ]
126 | );
127 | $this->customerSession->setWidgetFormsSubmitFormId($form->getId());
128 | } catch (LocalizedException $e) {
129 | $resultJson->setData(
130 | [
131 | 'errors' => true,
132 | 'message' => $e->getMessage()
133 | ]
134 | );
135 | } catch (\Exception $e) {
136 | $this->logger->error('Widget Form Error during submit action: ' . $e->getMessage());
137 | $resultJson->setData(
138 | [
139 | 'errors' => true,
140 | 'message' => __('We are unable to process your request. Please, try again later.'),
141 | ]
142 | );
143 | }
144 |
145 | return $resultJson;
146 | }
147 |
148 | /**
149 | * @param $form
150 | * @return string
151 | */
152 | public function getSuccessMessage($formRecord)
153 | {
154 | $successMessage = $formRecord->getForm()->getFormSubmitSuccessMessage();
155 | if ($successMessage) {
156 | $successMessage = $this->templateFilter->filter($successMessage);
157 | } else {
158 | $successMessage = __('Thank You!');
159 | }
160 | return (string) $successMessage;
161 | }
162 |
163 | /**
164 | * @param $form
165 | * @return string
166 | */
167 | public function getSuccessTitle($formRecord)
168 | {
169 | $successTitle = $formRecord->getForm()->getFormSubmitSuccessTitle();
170 | if (!$successTitle) {
171 | $successTitle = __('Success');
172 | }
173 | return (string) $successTitle;
174 | }
175 |
176 | /**
177 | * @return void
178 | * @throws LocalizedException
179 | */
180 | public function validateData()
181 | {
182 | if (!$this->formKeyValidator->validate($this->getRequest())) {
183 | throw new LocalizedException(__('Invalid Form Key. Please refresh the page.'));
184 | }
185 |
186 | if ($this->getRequest()->getParam('hideit')) {
187 | throw new LocalizedException(__('Interrupted Data'));
188 | }
189 | }
190 |
191 | /**
192 | *
193 | */
194 | public function getForm()
195 | {
196 | $formId = $this->getRequest()->getParam('form_id');
197 | $form = $this->formRepository->getById($formId);
198 | return $form;
199 | }
200 |
201 | /**
202 | * @return \Magento\Framework\App\RequestInterface
203 | */
204 | public function getRequest()
205 | {
206 | return $this->request;
207 | }
208 |
209 | /**
210 | * @return \Magento\Framework\App\ResponseInterface
211 | */
212 | public function getResponse()
213 | {
214 | return $this->response;
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/Setup/Patch/Data/CreateWidgetFormsAttributesPatch.php:
--------------------------------------------------------------------------------
1 | moduleDataSetup = $moduleDataSetup;
47 | $this->eavSetupFactory = $eavSetupFactory;
48 | $this->formAttributeRepository = $formAttributeRepository;
49 | $this->formFactory = $formFactory;
50 | }
51 |
52 | /**
53 | * @inheritdoc
54 | */
55 | public function apply()
56 | {
57 | $this->moduleDataSetup->getConnection()->startSetup();
58 |
59 | $eavSetup = $this->eavSetupFactory->create();
60 | $eavSetup->setAttributeRepository($this->formAttributeRepository);
61 |
62 | /**
63 | * remove attributes used in old versions of module
64 | */
65 | $eavSetup->deleteAttribute('form_submit_failure_message');
66 |
67 | $this->createWidgetFormAttributes($eavSetup);
68 | $this->createNewsletterAttributes($eavSetup);
69 | $this->createMultistepAttribites($eavSetup);
70 |
71 | $this->moduleDataSetup->getConnection()->endSetup();
72 | return $this;
73 | }
74 |
75 | /**
76 | * @param $eavSetup
77 | * @return void
78 | */
79 | private function createWidgetFormAttributes($eavSetup)
80 | {
81 | $eavSetup->createAttribute(
82 | 'can_use_for_widget',
83 | [
84 | 'frontend_input' => 'boolean',
85 | 'frontend_label' => 'Can use as frontend widget',
86 | 'visible_in_grid' => true,
87 | 'is_required' => true,
88 | 'sort_order' => 50,
89 | 'scope' => Scopes::SCOPE_GLOBAL,
90 | ]
91 | );
92 |
93 | $eavSetup->createAttribute(
94 | 'frontend_form_description',
95 | [
96 | 'frontend_input' => 'textarea',
97 | 'frontend_label' => 'Frontend Form Description',
98 | 'visible_in_grid' => false,
99 | 'is_required' => false,
100 | 'sort_order' => 10,
101 | 'group_code' => 'widget_form_attribute',
102 | 'scope' => Scopes::SCOPE_STORE,
103 | ]
104 | );
105 |
106 | $eavSetup->createAttribute(
107 | 'submit_button_label',
108 | [
109 | 'frontend_input' => 'text',
110 | 'frontend_label' => 'Submit Button Label',
111 | 'visible_in_grid' => false,
112 | 'is_required' => false,
113 | 'sort_order' => 20,
114 | 'group_code' => 'widget_form_attribute',
115 | 'scope' => Scopes::SCOPE_STORE,
116 | ]
117 | );
118 |
119 | $eavSetup->createOrUpdateAttribute(
120 | 'form_submit_success_message',
121 | [
122 | 'frontend_input' => 'textarea',
123 | 'frontend_label' => 'Form Submit Success Message',
124 | 'visible_in_grid' => false,
125 | 'is_required' => false,
126 | 'sort_order' => 30,
127 | 'group_code' => 'widget_form_attribute',
128 | 'scope' => Scopes::SCOPE_STORE,
129 | 'is_wysiwyg_enabled' => true,
130 | ]
131 | );
132 |
133 | $eavSetup->createOrUpdateAttribute(
134 | 'form_submit_success_title',
135 | [
136 | 'frontend_input' => 'text',
137 | 'frontend_label' => 'Form Submit Success Title',
138 | 'visible_in_grid' => false,
139 | 'is_required' => false,
140 | 'sort_order' => 29,
141 | 'group_code' => 'widget_form_attribute',
142 | 'scope' => Scopes::SCOPE_STORE,
143 | ]
144 | );
145 | }
146 |
147 | private function createNewsletterAttributes($eavSetup)
148 | {
149 | $eavSetup->createAttribute(
150 | 'subscribe_to_newsletter',
151 | [
152 | 'frontend_input' => 'boolean',
153 | 'frontend_label' => 'Subscribe to newletter',
154 | 'visible_in_grid' => false,
155 | 'is_required' => false,
156 | 'sort_order' => 10,
157 | 'scope' => Scopes::SCOPE_GLOBAL,
158 | 'group_code' => 'newsletter',
159 | ]
160 | );
161 |
162 | $eavSetup->createAttribute(
163 | 'newsletter_email',
164 | [
165 | 'frontend_input' => 'select',
166 | 'frontend_label' => 'Email field',
167 | 'backend_type' => 'varchar',
168 | 'source_model' => 'Alekseon\WidgetForms\Model\Attribute\Source\TextFormAttributes',
169 | 'visible_in_grid' => false,
170 | 'is_required' => false,
171 | 'sort_order' => 20,
172 | 'scope' => Scopes::SCOPE_GLOBAL,
173 | 'group_code' => 'newsletter',
174 | ]
175 | );
176 | }
177 |
178 | /**
179 | * @param $eavSetup
180 | * @return void
181 | * @throws \Magento\Framework\Exception\NoSuchEntityException
182 | */
183 | private function createMultistepAttribites($eavSetup)
184 | {
185 | $eavSetup->createOrUpdateAttribute(
186 | 'enable_multiple_steps',
187 | [
188 | 'frontend_input' => 'boolean',
189 | 'frontend_label' => 'Enable Multiple Steps',
190 | 'visible_in_grid' => false,
191 | 'is_required' => true,
192 | 'sort_order' => 50,
193 | 'group_code' => 'widget_form_attribute',
194 | 'scope' => Scopes::SCOPE_GLOBAL,
195 | 'note' => 'If Yes, display tabs as separated steps',
196 | ]
197 | );
198 |
199 | // this attribute "enable_multiple_steps" was created with typo in code in old version of module
200 | $wrongAttribute = $this->formAttributeRepository->getByAttributeCode('enable_multpiple_steps', true);
201 | if ($wrongAttribute && $wrongAttribute->getId()) {
202 | $formsWithEnabledSteps = $this->formFactory->create()->getCollection()
203 | ->addAttributeToFilter('enable_multpiple_steps', 1);
204 |
205 | foreach ($formsWithEnabledSteps as $form) {
206 | $form->setEnableMultipleSteps(1);
207 | $form->saveAttributeValue('enable_multiple_steps');
208 | }
209 |
210 | $eavSetup->deleteAttribute('enable_multpiple_steps');
211 | }
212 | }
213 |
214 | /**
215 | * @inheritdoc
216 | */
217 | public static function getDependencies()
218 | {
219 | return [];
220 | }
221 |
222 | /**
223 | * @inheritdoc
224 | */
225 | public function revert()
226 | {
227 | $this->moduleDataSetup->getConnection()->startSetup();
228 |
229 | $eavSetup = $this->eavSetupFactory->create();
230 | $eavSetup->setAttributeRepository($this->formAttributeRepository);
231 |
232 | $eavSetup->deleteAttribute('can_use_for_widget');
233 | $eavSetup->deleteAttribute('frontend_form_description');
234 | $eavSetup->deleteAttribute('submit_button_label');
235 | $eavSetup->deleteAttribute('form_submit_success_title');
236 | $eavSetup->deleteAttribute('form_submit_success_message');
237 | $eavSetup->deleteAttribute('subscribe_to_newsletter');
238 | $eavSetup->deleteAttribute('newsletter_email');
239 | $eavSetup->deleteAttribute('enable_multiple_steps');
240 |
241 | $this->moduleDataSetup->getConnection()->endSetup();
242 | }
243 |
244 | /**
245 | * @inheritdoc
246 | */
247 | public function getAliases()
248 | {
249 | return [];
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/Block/WidgetForm.php:
--------------------------------------------------------------------------------
1 | formRepository = $formRepository;
82 | $this->formKey = $formKey;
83 | $this->eventManager = $eventManager;
84 | $this->jsonHexTag = $jsonHexTag;
85 | parent::__construct($context, $data);
86 | }
87 |
88 | /**
89 | * @inheritDoc
90 | */
91 | protected function _toHtml()
92 | {
93 | $form = $this->getForm();
94 | if ($form) {
95 | $this->addTabs();
96 | $this->addFields();
97 | $this->eventManager->dispatch(
98 | 'alekseon_widget_form_prepare_layout',
99 | [
100 | 'widget_block' => $this,
101 | 'form' => $this->getForm(),
102 | ]
103 | );
104 | }
105 | return parent::_toHtml();
106 | }
107 |
108 | /**
109 | * @param string $alias
110 | * @return BlocksContainer
111 | */
112 | public function getBlocksContainer(string $alias)
113 | {
114 | $containerAlias = 'form_' . $this->getForm()->getId() . '_' . $alias;
115 | /** @var BlocksContainer $blocksContainer */
116 | $blocksContainer = $this->getChildBlock($containerAlias);
117 | if (!$blocksContainer) {
118 | $blocksContainer = $this->addChild(
119 | $containerAlias,
120 | BlocksContainer::class
121 | );
122 | }
123 | return $blocksContainer;
124 | }
125 |
126 | /**
127 | * @return void
128 | */
129 | private function addTabs()
130 | {
131 | if ($this->tabBlocks == null) {
132 | $this->tabBlocks = [];
133 | $tabs = [];
134 |
135 | if ($this->getForm()->getEnableMultipleSteps()) {
136 | $formTabs = $this->getForm()->getFormTabs();
137 | /** @var FormTab $tab */
138 | foreach ($formTabs as $tab) {
139 | $tabs[$tab->getId()] = $tab;
140 | }
141 | }
142 |
143 | if (empty($tabs)) {
144 | // backward compatible, to be sure there is always at least one tab
145 | $tab = $this->getForm()->addFormTab();
146 | $tab->setId(1);
147 | $tabs[$tab->getId()] = $tab;
148 | }
149 |
150 | $firstTab = reset($tabs);
151 | $firstTab->setIsFirstTab(true);
152 |
153 | $lastTab = end($tabs);
154 | $lastTab->setIsLastTab(true);
155 | $tabsContainer = $this->getBlocksContainer('tabs_container');
156 |
157 | $tabsCounter = 0;
158 | /** @var FormTab $tab */
159 | foreach ($tabs as $tabCode => $tab) {
160 | $tabsCounter ++;
161 | $fieldBlockAlias = 'form_' . $this->getForm()->getId() . '_tab_' . $tabCode;
162 | $tab->setTabSequenceNumber($tabsCounter);
163 | $this->tabBlocks[$tabCode] = $tabsContainer->addChild(
164 | $fieldBlockAlias,
165 | Tab::class,
166 | [
167 | 'form' => $this->getForm(),
168 | 'tab' => $tab,
169 | ]
170 | );
171 | $this->tabSequence[$tabsCounter] = $tabCode;
172 | }
173 | }
174 | }
175 |
176 | /**
177 | * @return void
178 | */
179 | private function addFields()
180 | {
181 | $fields = $this->getFormFieldsCollection();
182 | /** @var Attribute $attribute */
183 | foreach ($fields as $attribute) {
184 | $tabCode = $attribute ? $attribute->getGroupCode() : '';
185 | /** @var Tab $tabBlock */
186 | $tabBlock = $this->tabBlocks[$tabCode] ?? reset($this->tabBlocks);
187 | $fieldBlockAlias = 'form_field_' . $attribute->getAttributeCode();
188 | $tabBlock->addChild(
189 | $fieldBlockAlias,
190 | \Alekseon\CustomFormsFrontend\Block\Form\Field::class,
191 | [
192 | 'attribute' => $attribute
193 | ]
194 | );
195 | }
196 | }
197 |
198 | /**
199 | * @return \Alekseon\CustomFormsBuilder\Model\ResourceModel\FormRecord\Attribute\Collection
200 | */
201 | private function getFormFieldsCollection()
202 | {
203 | if ($this->formFieldsCollection === null) {
204 | $form = $this->getForm();
205 | $this->formFieldsCollection = $form->getFieldsCollection();
206 | }
207 | return $this->formFieldsCollection;
208 | }
209 |
210 | /**
211 | * @param $tabSequenceNumber
212 | * @return false|mixed
213 | */
214 | public function getTabBlock($tabSequenceNumber)
215 | {
216 | $tabCode = $this->tabSequence[$tabSequenceNumber] ?? false;
217 | return $tabCode ? $this->tabBlocks[$tabCode] : false;
218 | }
219 |
220 | /**
221 | * @return int|null
222 | */
223 | public function getTabsCounter()
224 | {
225 | return count($this->tabSequence);
226 | }
227 |
228 | /**
229 | * @return false|string
230 | */
231 | public function getTabsJson()
232 | {
233 | return $this->jsonHexTag->serialize($this->tabSequence);
234 | }
235 |
236 | /**
237 | * @return \Alekseon\CustomFormsBuilder\Model\Form|false
238 | */
239 | public function getForm()
240 | {
241 | if ($this->form === null) {
242 | $identifier = $this->getData('form_identifier');
243 | $form = false;
244 | if ($identifier) {
245 | try {
246 | $form = $this->formRepository->getByIdentifier($identifier, null, true);
247 | } catch (\Exception $e) {}
248 | } else {
249 | $formId = (int)$this->getData('form_id');
250 | if ($formId) {
251 | try {
252 | $form = $this->formRepository->getById($formId, null, true);
253 | } catch (\Exception $e) {}
254 | }
255 | }
256 |
257 | if ($form && $form->getCanUseForWidget()) {
258 | $this->form = $form;
259 | } else {
260 | $this->form = false;
261 | }
262 | }
263 |
264 | return $this->form;
265 | }
266 |
267 | /**
268 | * @return false|string
269 | */
270 | public function getFormTitle()
271 | {
272 | if ($this->getHideTitle()) {
273 | return false;
274 | }
275 |
276 | return $this->getForm()->getTitle();
277 | }
278 |
279 | /**
280 | * @return false|string
281 | */
282 | public function getFormDescription()
283 | {
284 | if ($this->getHideDescription()) {
285 | return false;
286 | }
287 |
288 | return $this->getForm()->getFrontendFormDescription();
289 | }
290 |
291 | /**
292 | * @return string
293 | */
294 | public function getFormKey()
295 | {
296 | return $this->formKey->getFormKey();
297 | }
298 |
299 | /**
300 | * @return int
301 | */
302 | public function getCacheLifetime(): int
303 | {
304 | return 86400;
305 | }
306 |
307 | /**
308 | * @return array
309 | */
310 | public function getCacheKeyInfo(): array
311 | {
312 | $cacheKeyInfo = parent::getCacheKeyInfo();
313 | if ($this->getForm()) {
314 | $cacheKeyInfo['widget_data'] = $this->serialize();
315 | }
316 | return $cacheKeyInfo;
317 | }
318 |
319 | /**
320 | * @return string[]
321 | */
322 | public function getIdentities(): array
323 | {
324 | return $this->getForm() ? $this->getForm()->getIdentities() : [];
325 | }
326 |
327 | /**
328 | * @return string
329 | */
330 | public function getSubmitFormUrl()
331 | {
332 | return $this->getUrl('Alekseon_WidgetForms/form/submit', [
333 | 'form_id' => $this->getForm()->getId(),
334 | ]);
335 | }
336 |
337 | /**
338 | * @return string
339 | */
340 | public function getFormWrapperClass(): string
341 | {
342 | return $this->getForm()->getIdentifier()
343 | ? 'alekseon-widget-' . $this->getForm()->getIdentifier() . '-form--wrapper'
344 | : '';
345 | }
346 |
347 | /**
348 | * @return string
349 | */
350 | public function getSuccessFormUrl()
351 | {
352 | $id = $this->getForm()->getIdentifier();
353 | if (!$id) {
354 | $id = $this->getForm()->getId();
355 | }
356 | return $this->getUrl('Alekseon_WidgetForms/form/success', [
357 | 'form_id' => $id,
358 | ]);
359 | }
360 | }
361 |
--------------------------------------------------------------------------------