├── .github
└── workflows
│ ├── coding-standard.yml
│ ├── integration.yml
│ └── unit.yml
├── .gitignore
├── .magento
└── dev
│ └── tests
│ └── unit
│ └── phpunit.xml
├── Block
└── Adminhtml
│ ├── Form.php
│ ├── Form
│ ├── Edit.php
│ ├── Edit
│ │ ├── Form.php
│ │ ├── Tab
│ │ │ ├── Fields.php
│ │ │ ├── Fields
│ │ │ │ └── Form.php
│ │ │ └── General.php
│ │ └── Tabs.php
│ ├── Grid.php
│ └── Grid
│ │ └── Renderer
│ │ ├── Actions.php
│ │ └── CreatedFrom.php
│ ├── FormField
│ ├── Edit.php
│ └── Edit
│ │ ├── Form.php
│ │ └── Tabs.php
│ ├── FormRecord.php
│ └── FormRecord
│ ├── Edit.php
│ ├── Edit
│ ├── Form.php
│ ├── FormInfo.php
│ ├── Tab
│ │ └── Fields.php
│ └── Tabs.php
│ └── Grid.php
├── CHANGELOG.md
├── Controller
└── Adminhtml
│ ├── Form.php
│ ├── Form
│ ├── Delete.php
│ ├── Edit.php
│ ├── Index.php
│ ├── NewAction.php
│ └── Save.php
│ ├── FormField.php
│ ├── FormField
│ ├── Edit.php
│ └── Save.php
│ ├── FormRecord.php
│ └── FormRecord
│ ├── Delete.php
│ ├── Edit.php
│ ├── ExportCsv.php
│ ├── ExportExcel.php
│ ├── Index.php
│ ├── MassDelete.php
│ ├── NewAction.php
│ └── Save.php
├── LICENCE
├── Model
├── Attribute
│ ├── InputValidator
│ │ └── PostalCode.php
│ └── Source
│ │ ├── SelectFormAttributes.php
│ │ └── TextFormAttributes.php
├── FieldOptionSources.php
├── Form.php
├── Form
│ ├── Attribute.php
│ └── AttributeRepository.php
├── FormRecord.php
├── FormRecord
│ ├── Attribute.php
│ └── AttributeRepository.php
├── FormRepository.php
├── FormTab.php
└── ResourceModel
│ ├── Form.php
│ ├── Form
│ ├── Attribute.php
│ ├── Attribute
│ │ └── Collection.php
│ └── Collection.php
│ ├── FormRecord.php
│ ├── FormRecord
│ ├── Attribute.php
│ ├── Attribute
│ │ └── Collection.php
│ └── Collection.php
│ ├── FormTab.php
│ └── FormTab
│ └── Collection.php
├── Plugin
├── AddCustomFormsToAclTreePlugin.php
└── AddCustomFormsToAdminMenuPlugin.php
├── README.md
├── Setup
└── Patch
│ ├── Data
│ └── CreateWidgetFormsAttributesPatch.php
│ └── Schema
│ └── CreateEavTablesV2.php
├── Test
└── Unit
│ └── Model
│ └── FormRepositoryTest.php
├── composer.json
├── etc
├── acl.xml
├── adminhtml
│ ├── di.xml
│ ├── menu.xml
│ ├── routes.xml
│ └── system.xml
├── db_schema.xml
├── db_schema_whitelist.json
├── di.xml
└── module.xml
├── registration.php
└── view
├── adminhtml
├── layout
│ ├── alekseon_customformsbuilder_form_edit.xml
│ ├── alekseon_customformsbuilder_form_index.xml
│ ├── alekseon_customformsbuilder_formfield_edit.xml
│ ├── alekseon_customformsbuilder_formrecord_edit.xml
│ └── alekseon_customformsbuilder_formrecord_index.xml
├── templates
│ ├── form
│ │ ├── edit
│ │ │ ├── field
│ │ │ │ └── identifier.phtml
│ │ │ └── tab
│ │ │ │ └── fields.phtml
│ │ └── wikiLink.phtml
│ └── formRecord
│ │ └── edit
│ │ └── formInfo.phtml
└── web
│ └── js
│ └── form
│ └── edit
│ ├── formFields.js
│ └── formTabs.js
└── base
├── requirejs-config.js
└── web
└── js
└── validation-mixin.js
/.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/custom-forms-builder
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_CustomFormsBuilder
35 | composer_name: alekseon/custom-forms-builder
36 | ce_version: '2.4.7'
37 |
--------------------------------------------------------------------------------
/.github/workflows/unit.yml:
--------------------------------------------------------------------------------
1 | name: M2 Unit Tests
2 | on: [push]
3 | jobs:
4 | unit-tests:
5 | name: Magento 2 Unit Tests
6 | runs-on: ubuntu-latest
7 | env:
8 | MODULE_NAME: Alekseon_CustomFormsBuilder
9 | COMPOSER_NAME: alekseon/custom-forms-builder
10 | REPOSITORY_URL: https://repo.magento.com/
11 | MAGENTO_MARKETPLACE_USERNAME: ${{ secrets.MAGENTO_MARKETPLACE_USERNAME }}
12 | MAGENTO_MARKETPLACE_PASSWORD: ${{ secrets.MAGENTO_MARKETPLACE_PASSWORD }}
13 | steps:
14 | - uses: actions/checkout@v4
15 | - uses: extdn/github-actions-m2/magento-unit-tests/8.1@master
16 | env:
17 | MAGENTO_VERSION: '2.4.7'
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .DS_Store
3 | Thumbs.db
--------------------------------------------------------------------------------
/.magento/dev/tests/unit/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | ../../../vendor/alekseon/custom-forms-builder/Test/Unit
11 |
12 |
13 |
14 | ../../../vendor/alekseon/custom-forms-builder
15 |
16 | ../../../vendor/alekseon/custom-forms-builder/Test
17 |
18 |
19 |
20 |
21 | .
22 | testsuite
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form.php:
--------------------------------------------------------------------------------
1 | _controller = 'adminhtml_form';
22 | $this->_blockGroup = 'Alekseon_CustomFormsBuilder';
23 | $this->_headerText = __('Custom Forms');
24 | $this->_addButtonLabel = __('Add New Form');
25 | parent::_construct();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Edit.php:
--------------------------------------------------------------------------------
1 | _objectId = 'entity_id';
29 | $this->_controller = 'adminhtml_form';
30 |
31 | parent::_construct();
32 |
33 | if (!$this->_authorization->isAllowed('Alekseon_CustomFormsBuilder::manage_custom_forms')) {
34 | $this->removeButton('delete');
35 | }
36 |
37 | $this->addButton(
38 | 'save_and_continue',
39 | [
40 | 'label' => __('Save and Continue'),
41 | 'class' => 'save',
42 | 'data_attribute' => [
43 | 'mage-init' => [
44 | 'button' => ['event' => 'saveAndContinueEdit', 'target' => '#edit_form'],
45 | ],
46 | ]
47 | ]
48 | );
49 | }
50 |
51 | /**
52 | * Retrieve URL for save
53 | *
54 | * @return string
55 | */
56 | public function getSaveUrl()
57 | {
58 | return $this->getUrl(
59 | '*/*/save',
60 | ['_current' => true]
61 | );
62 | }
63 |
64 | /**
65 | * @inheritdoc
66 | */
67 | public function getBackUrl()
68 | {
69 | if ($this->getRequest()->getParam('back_to_records')) {
70 | return $this->getUrl('*/formRecord/index', ['id' => $this->getRequest()->getParam('entity_id')]);
71 | } else {
72 | return parent::getBackUrl();
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Edit/Form.php:
--------------------------------------------------------------------------------
1 | _formFactory->create(
32 | [
33 | 'data' => [
34 | 'id' => 'edit_form',
35 | 'action' => $this->getData('action'),
36 | 'method' => 'post',
37 | 'enctype' => 'multipart/form-data',
38 | ]
39 | ]
40 | );
41 |
42 | $this->setForm($form);
43 | $this->getForm()->setUseContainer(true);
44 |
45 | return parent::_prepareForm();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Edit/Tab/Fields.php:
--------------------------------------------------------------------------------
1 | registry = $registry;
36 | parent::__construct($context);
37 | }
38 |
39 | /**
40 | * {@inheritdoc}
41 | */
42 | public function getTabLabel()
43 | {
44 | return __('Form Fields');
45 | }
46 |
47 | /**
48 | * {@inheritdoc}
49 | */
50 | public function getTabTitle()
51 | {
52 | return __('Form Fields');
53 | }
54 |
55 | /**
56 | * {@inheritdoc}
57 | */
58 | public function canShowTab()
59 | {
60 | return true;
61 | }
62 |
63 | /**
64 | * {@inheritdoc}
65 | */
66 | public function isHidden()
67 | {
68 | return false;
69 | }
70 |
71 |
72 | /**
73 | * @return \Magento\Backend\Block\Template
74 | */
75 | protected function _prepareLayout()
76 | {
77 | $this->addChild(
78 | 'add_new_field_button',
79 | \Magento\Backend\Block\Widget\Button::class,
80 | [
81 | 'label' => __('Add Field'),
82 | 'data_attribute' => ['action' => 'add-form-field'],
83 | 'class' => 'add',
84 | 'id' => 'add_field_button',
85 | ]
86 | );
87 |
88 | return parent::_prepareLayout();
89 | }
90 |
91 | /**
92 | * @return mixed|null
93 | */
94 | public function getCurrentForm()
95 | {
96 | return $this->registry->registry('current_form');
97 | }
98 |
99 | /**
100 | * @return array[]
101 | */
102 | public function getFormTabs()
103 | {
104 | $jsonHelper = $this->getData('jsonHelper');
105 | $formTabs = $this->getCurrentForm()->getFormTabs();
106 | $tabsData = [];
107 | foreach ($formTabs as $tab) {
108 | $tabsData[] = [
109 | 'label' => $tab->getLabel(),
110 | 'code' => $tab->getId()
111 | ];
112 | $this->lastTab = $tab;
113 | }
114 | return $jsonHelper->jsonEncode($tabsData);
115 | }
116 |
117 | /**
118 | * @return mixed
119 | */
120 | public function getActiveFormTab()
121 | {
122 | return $this->getCurrentForm()->getFirstFormTab();
123 | }
124 |
125 | /**
126 | * @return int | null
127 | */
128 | public function getLastTabId()
129 | {
130 | return $this->lastTab->getId();
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Edit/Tab/General.php:
--------------------------------------------------------------------------------
1 | dataObject) {
62 | return $this->_coreRegistry->registry('current_form');
63 | }
64 | return $this->dataObject;
65 | }
66 |
67 | /**
68 | * @inheritdoc
69 | */
70 | protected function _prepareForm()
71 | {
72 | $dataObject = $this->getDataObject();
73 |
74 | /** @var \Magento\Framework\Data\Form $form */
75 | $form = $this->_formFactory->create();
76 | $baseFieldset = $form->addFieldset('base_fieldset', ['legend' => __('Form Properties')]);
77 |
78 | if ($dataObject->getId()) {
79 | $baseFieldset->addField('entity_id', 'hidden', ['name' => 'entity_id']);
80 | }
81 |
82 | $this->addAllAttributeFields($baseFieldset, $dataObject);
83 |
84 | $baseFieldset->addField('identifier',
85 | 'text',
86 | [
87 | 'name' => 'identifier',
88 | 'label' => __('Form Identifier'),
89 | 'title' => __('Form Identifier'),
90 | 'note' => __(
91 | 'This is used internally. Make sure you don\'t use spaces or more than %1 symbols.',
92 | 255
93 | ),
94 | ]
95 | );
96 |
97 | $baseFieldset->addField('group_fields_in',
98 | 'select',
99 | [
100 | 'name' => 'group_fields_in',
101 | 'label' => __('Group Fields In'),
102 | 'title' => __('Group Fields In'),
103 | 'options' => [
104 | Form::GROUP_FEILDS_IN_FIELDSETS_OPTION => __('Fieldsets'),
105 | Form::GROUP_FIELDS_IN_TABS_OPTION => __('Tabs'),
106 | ],
107 | ]
108 | );
109 |
110 | $adminNoteFieldset = $form->addFieldset('admin_note_fieldset', ['legend' => __('Admin Note')]);
111 |
112 | $adminNoteFieldset->addField('admin_note',
113 | 'textarea',
114 | [
115 | 'name' => 'admin_note',
116 | 'label' => __('Admin Note'),
117 | 'title' => __('Admin Note'),
118 | 'note' => __('Note is not visible on frontend.'),
119 | ]
120 | );
121 |
122 | $this->setForm($form);
123 |
124 | return parent::_prepareForm();
125 | }
126 |
127 |
128 | /**
129 | * Initialize form fileds values
130 | *
131 | * @return $this
132 | */
133 | protected function _initFormValues()
134 | {
135 | $this->getForm()->addValues($this->getDataObject()->getData());
136 | return parent::_initFormValues();
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Edit/Tabs.php:
--------------------------------------------------------------------------------
1 | setId('form_tabs');
23 | $this->setDestElementId('edit_form');
24 | $this->setTitle(__('Form Information'));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Grid.php:
--------------------------------------------------------------------------------
1 | _collectionFactory = $collectionFactory;
37 | parent::__construct($context, $backendHelper, $data);
38 | }
39 |
40 | /**
41 | * @return void
42 | */
43 | protected function _construct()
44 | {
45 | parent::_construct();
46 | $this->setUseAjax(true);
47 | }
48 |
49 | /**
50 | * @return $this
51 | */
52 | protected function _prepareCollection()
53 | {
54 | $collection = $this->_collectionFactory->create();
55 | $this->setCollection($collection);
56 |
57 | return parent::_prepareCollection();
58 | }
59 |
60 | /**
61 | * @return $this
62 | * @throws \Exception
63 | */
64 | protected function _prepareColumns()
65 | {
66 | parent::_prepareColumns();
67 |
68 | $this->addColumn(
69 | 'entity_id',
70 | [
71 | 'header' => __('Form Id'),
72 | 'index' => 'entity_id',
73 | ]
74 | );
75 |
76 | $this->addAttributeColumns();
77 |
78 | $this->addColumn(
79 | 'admin_note',
80 | [
81 | 'header' => __('Admin Note'),
82 | 'index' => 'admin_note',
83 | ]
84 | );
85 |
86 | $this->addColumn(
87 | 'actions',
88 | [
89 | 'header' => __('Actions'),
90 | 'sortable' => false,
91 | 'filter' => false,
92 | 'renderer' => \Alekseon\CustomFormsBuilder\Block\Adminhtml\Form\Grid\Renderer\Actions::class,
93 | 'header_css_class' => 'col-actions',
94 | 'column_css_class' => 'col-actions'
95 | ]
96 | );
97 |
98 | return $this;
99 | }
100 |
101 | /**
102 | * @param \Magento\Framework\DataObject $row
103 | * @return string
104 | * @SuppressWarnings(PHPMD.UnusedFormalParameter)
105 | */
106 | public function getRowUrl($row)
107 | {
108 | return false;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Grid/Renderer/Actions.php:
--------------------------------------------------------------------------------
1 | getUrl('*/formRecord', ['id' => $row->getId()]) . '">' . __('Show Records') . '',
24 | '' . __('Manage Form') . ''
25 | ];
26 | return implode(' | ', $actions);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Form/Grid/Renderer/CreatedFrom.php:
--------------------------------------------------------------------------------
1 | getCreatedFromStoreId() === '0') {
22 | return __('All Store Views');
23 | }
24 | return parent::render($row);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormField/Edit.php:
--------------------------------------------------------------------------------
1 | _objectId = 'attribute_code';
29 | $this->_controller = 'adminhtml_formField';
30 |
31 | parent::_construct();
32 |
33 | $this->removeButton('back');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormField/Edit/Form.php:
--------------------------------------------------------------------------------
1 | _formFactory->create(
26 | [
27 | 'data' => [
28 | 'id' => 'edit_form',
29 | 'action' => $this->getData('action'),
30 | 'method' => 'post'
31 | ]
32 | ]
33 | );
34 |
35 | $this->setForm($form);
36 | $this->getForm()->setUseContainer(true);
37 |
38 | return parent::_prepareForm();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormField/Edit/Tabs.php:
--------------------------------------------------------------------------------
1 | setId('attribute_tabs');
23 | $this->setDestElementId('edit_form');
24 | $this->setTitle(__('Form Field Information'));
25 | }
26 |
27 | /**
28 | * @return $this
29 | * @throws \Exception
30 | */
31 | protected function _beforeToHtml()
32 | {
33 | $this->addTab(
34 | 'main',
35 | [
36 | 'label' => __('Properties'),
37 | 'title' => __('Properties'),
38 | 'content' => $this->getChildHtml('general'),
39 | 'active' => true
40 | ]
41 | );
42 |
43 | $this->addTab(
44 | 'frontend_labels',
45 | [
46 | 'label' => __('Frontend Labels'),
47 | 'title' => __('Frontend Labels'),
48 | 'content' => $this->getChildHtml('frontend_labels'),
49 | ]
50 | );
51 |
52 | return parent::_beforeToHtml();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormRecord.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
33 | parent::__construct($context, $data);
34 | }
35 |
36 | /**
37 | * @return void
38 | */
39 | protected function _construct()
40 | {
41 | $this->_controller = 'adminhtml_formRecord';
42 | $this->_blockGroup = 'Alekseon_CustomFormsBuilder';
43 | $this->_headerText = __('Custom Form Records');
44 | $this->_addButtonLabel = __('Add New Record');
45 | parent::_construct();
46 |
47 | if (!$this->getCurrentForm()->getManageFormAllowedDisallowedFlag()) {
48 | $this->addButton(
49 | 'manage_form',
50 | [
51 | 'label' => __('Manage Form'),
52 | 'onclick' => 'setLocation(\'' . $this->getManageFormUrl() . '\')',
53 | ]
54 | );
55 | }
56 |
57 | if (!$this->isAddNewRecordAllowed()) {
58 | $this->removeButton('add');
59 | }
60 | }
61 |
62 | /**
63 | * @return string
64 | */
65 | public function getCreateUrl()
66 | {
67 | return $this->getUrl('*/*/new', ['form_id' => $this->getCurrentForm()->getId()]);
68 | }
69 |
70 | /**
71 | * @return string
72 | */
73 | private function getManageFormUrl()
74 | {
75 | return $this->getUrl('*/form/edit', [
76 | 'entity_id' => $this->getCurrentForm()->getId(),
77 | 'back_to_records' => true,
78 | ]);
79 | }
80 |
81 | /**
82 | * @return mixed
83 | */
84 | public function getCurrentForm()
85 | {
86 | return $this->coreRegistry->registry('current_form');
87 | }
88 |
89 | /**
90 | *
91 | */
92 | protected function isAddNewRecordAllowed()
93 | {
94 | $manageResource = 'Alekseon_CustomFormsBuilder::manage_custom_forms';
95 | if ($this->_authorization->isAllowed($manageResource)) {
96 | return true;
97 | }
98 |
99 | $resource = 'Alekseon_CustomFormsBuilder::custom_form_' . $this->getCurrentForm()->getId() . '_save';
100 | return $this->_authorization->isAllowed($resource);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormRecord/Edit.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
42 | parent::__construct($context, $data);
43 | }
44 |
45 | /**
46 | * @return void
47 | */
48 | protected function _construct()
49 | {
50 | $this->_objectId = 'id';
51 | $this->_controller = 'adminhtml_formRecord';
52 |
53 | parent::_construct();
54 |
55 | $this->addButton(
56 | 'save_and_continue',
57 | [
58 | 'label' => __('Save and Continue'),
59 | 'class' => 'save',
60 | 'data_attribute' => [
61 | 'mage-init' => [
62 | 'button' => ['event' => 'saveAndContinueEdit', 'target' => '#edit_form'],
63 | ],
64 | ]
65 | ]
66 | );
67 |
68 | if ($this->getCurrentForm()->getSaveRecordDisallowedFlag()) {
69 | $this->removeButton('save');
70 | $this->removeButton('save_and_continue');
71 | }
72 |
73 | if ($this->getCurrentForm()->getDeleteRecordDisallowedFlag()) {
74 | $this->removeButton('delete');
75 | }
76 |
77 | $this->_formInitScripts[] = 'window.alekseonCustomFormsPostalCodes = '
78 | . $this->getPostCodeConfig()->getSerializedPostCodes() . ';';
79 | }
80 |
81 | /**
82 | * Retrieve URL for save
83 | *
84 | * @return string
85 | */
86 | public function getSaveUrl()
87 | {
88 | return $this->getUrl(
89 | '*/*/save',
90 | ['_current' => true]
91 | );
92 | }
93 |
94 | /**
95 | * @return string
96 | */
97 | public function getBackUrl()
98 | {
99 | return $this->getUrl('*/*/index', ['id' => $this->getRequest()->getParam('form_id')]);
100 | }
101 |
102 | /**
103 | * @return string
104 | */
105 | public function getDeleteUrl()
106 | {
107 | return $this->getUrl('*/*/delete',
108 | [
109 | 'id' => $this->getRequest()->getParam('id'),
110 | 'form_id' => $this->getRequest()->getParam('form_id')
111 | ]
112 | );
113 | }
114 |
115 | /**
116 | * @return mixed
117 | */
118 | public function getCurrentForm()
119 | {
120 | return $this->coreRegistry->registry('current_form');
121 | }
122 |
123 | /**
124 | * @return mixed|null
125 | */
126 | public function getCurrentRecord()
127 | {
128 | return $this->coreRegistry->registry('current_record');
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormRecord/Edit/Form.php:
--------------------------------------------------------------------------------
1 | _formFactory->create(
29 | [
30 | 'data' => [
31 | 'id' => 'edit_form',
32 | 'action' => $this->getData('action'),
33 | 'method' => 'post',
34 | 'enctype' => 'multipart/form-data',
35 | ]
36 | ]
37 | );
38 |
39 | $this->setForm($form);
40 | $this->getForm()->setUseContainer(true);
41 |
42 | return parent::_prepareForm();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormRecord/Edit/FormInfo.php:
--------------------------------------------------------------------------------
1 | getCurrentRecord()->getId()) {
24 | $this->setTitle(__('Record #') . $this->getCurrentRecord()->getId());
25 | } else {
26 | $this->setTitle(__('New Record'));
27 | }
28 | parent::_construct(); // TODO: Change the autogenerated stub
29 | }
30 |
31 | /**
32 | * @return mixed
33 | * @throws \Magento\Framework\Exception\LocalizedException
34 | */
35 | public function getCurrentRecord()
36 | {
37 | return $this->getLayout()->getBlock('form_record_edit')->getCurrentRecord();
38 | }
39 |
40 | /**
41 | * @return string|void
42 | * @throws \Magento\Framework\Exception\LocalizedException
43 | */
44 | public function getCreatedFrom()
45 | {
46 | $storeId = $this->getCurrentRecord()->getCreatedFromStoreId();
47 | if ($storeId) {
48 | try {
49 | $store = $this->_storeManager->getStore($this->getCurrentRecord()->getCreatedFromStoreId());
50 | return $store->getName();
51 | } catch (\Exception $e) {
52 | // do nothing
53 | }
54 | } elseif ($storeId === '0') {
55 | return __('All Store Views');
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormRecord/Edit/Tab/Fields.php:
--------------------------------------------------------------------------------
1 | _formFactory->create();
27 | $this->setForm($form);
28 |
29 | $formTabs = $this->getDataObject()->getForm()->getFormTabs();
30 | $currentTabLabel = '';
31 | foreach ($formTabs as $formTab) {
32 | $this->formTabCodes[$formTab->getId()] = $formTab->getId();
33 | if ($formTab->getId() == $this->getTabCode()) {
34 | $currentTabLabel = $formTab->getLabel();
35 | }
36 | }
37 |
38 | if ($this->groupFieldsInTabs()) {
39 | $fieldset = $form->addFieldset('fieldset', ['legend' => $currentTabLabel]);
40 | $this->addFields($fieldset, $this->getTabCode());
41 | } else {
42 | $this->setIsFirstTab(true);
43 | foreach ($formTabs as $formTab) {
44 | $fieldset = $form->addFieldset('fieldset_' . $formTab->getId(), ['legend' => $formTab->getLabel()]);
45 | $this->addFields($fieldset, $formTab->getId());
46 | $this->setIsFirstTab(false);
47 | }
48 | }
49 |
50 | return parent::_prepareForm();
51 | }
52 |
53 | /**
54 | * @return void
55 | */
56 | protected function addFields($fieldset, $tabCode)
57 | {
58 | $dataObject = $this->getDataObject();
59 | if ($this->getIsFirstTab()) {
60 | if ($dataObject->getId()) {
61 | $fieldset->addField('entity_id', 'hidden', ['name' => 'entity_id']);
62 | }
63 | $excluded = array_diff($this->formTabCodes, [$tabCode]);
64 | $this->addAllAttributeFields($fieldset, $dataObject, ['excluded' => $excluded]);
65 | } else {
66 | $this->addAllAttributeFields($fieldset, $dataObject, ['included' => [$tabCode]]);
67 | }
68 | }
69 |
70 | /**
71 | * @return mixed
72 | */
73 | public function getDataObject()
74 | {
75 | return $this->getLayout()->getBlock('form_record_edit')->getCurrentRecord();
76 | }
77 |
78 | /**
79 | * @return Fields
80 | */
81 | protected function _initFormValues()
82 | {
83 | $this->getForm()->addValues($this->getDataObject()->getData());
84 | return parent::_initFormValues();
85 | }
86 |
87 | /**
88 | * @return bool
89 | */
90 | public function groupFieldsInTabs()
91 | {
92 | if ($this->getDataObject()->getForm()->getGroupFieldsIn() == Form::GROUP_FIELDS_IN_TABS_OPTION) {
93 | return true;
94 | }
95 | return false;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormRecord/Edit/Tabs.php:
--------------------------------------------------------------------------------
1 | setId('form_record_tabs');
23 | $this->setDestElementId('edit_form');
24 | }
25 |
26 | /**
27 | * @return Tabs|\Magento\Backend\Block\Widget\Tabs
28 | * @throws \Exception
29 | */
30 | protected function _beforeToHtml()
31 | {
32 | if ($this->getCurrentForm()->getGroupFieldsIn() == \Alekseon\CustomFormsBuilder\Model\Form::GROUP_FIELDS_IN_TABS_OPTION) {
33 | $formTabs = $this->getCurrentForm()->getFormTabs();
34 |
35 | $firstFormTab = $this->getCurrentForm()->getFirstFormTab();
36 | foreach ($formTabs as $tab) {
37 | $isFirstTab = $firstFormTab->getId() == $tab->getId();
38 | $fieldsBlock = $this->getLayout()->createBlock(
39 | 'Alekseon\CustomFormsBuilder\Block\Adminhtml\FormRecord\Edit\Tab\Fields'
40 | );
41 | $fieldsBlock->setTabCode($tab->getId());
42 | $fieldsBlock->setIsFirstTab($isFirstTab);
43 | $this->addTab(
44 | 'form-tab-' . $tab->getId(),
45 | [
46 | 'label' => $tab->getLabel(),
47 | 'title' => $tab->getLabel(),
48 | 'active' => $isFirstTab,
49 | 'content' => $fieldsBlock->toHtml(),
50 | ]
51 | );
52 | }
53 | } else {
54 | $fieldsBlock = $this->getLayout()->createBlock(
55 | 'Alekseon\CustomFormsBuilder\Block\Adminhtml\FormRecord\Edit\Tab\Fields'
56 | );
57 | $this->addTab(
58 | 'form-tab',
59 | [
60 | 'label' => __('Record Data'),
61 | 'title' => __('Record Data'),
62 | 'active' => true,
63 | 'content' => $fieldsBlock->toHtml(),
64 | ]
65 | );
66 | }
67 |
68 | return parent::_beforeToHtml();
69 | }
70 |
71 | /**
72 | * @return mixed
73 | * @throws \Magento\Framework\Exception\LocalizedException
74 | */
75 | public function getCurrentRecord()
76 | {
77 | return $this->getLayout()->getBlock('form_record_edit')->getCurrentRecord();
78 | }
79 |
80 | /**
81 | * @return mixed
82 | * @throws \Magento\Framework\Exception\LocalizedException
83 | */
84 | public function getCurrentForm()
85 | {
86 | return $this->getLayout()->getBlock('form_record_edit')->getCurrentForm();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Block/Adminhtml/FormRecord/Grid.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
38 | parent::__construct($context, $backendHelper, $data);
39 | $this->setDefaultSort('created_at');
40 | $this->setDefaultDir('desc');
41 | }
42 |
43 | /**
44 | * @return void
45 | */
46 | protected function _construct()
47 | {
48 | parent::_construct();
49 | $this->setUseAjax(true);
50 | }
51 |
52 | /**
53 | * @return $this
54 | */
55 | protected function _prepareCollection()
56 | {
57 | $collection = $this->getCurrentForm()->getRecordCollection();
58 | $this->setCollection($collection);
59 | return parent::_prepareCollection();
60 | }
61 |
62 | /**
63 | * @return $this
64 | * @throws \Exception
65 | */
66 | protected function _prepareColumns()
67 | {
68 | parent::_prepareColumns();
69 |
70 | $this->addColumn(
71 | 'created_at',
72 | [
73 | 'header' => __('Created At'),
74 | 'index' => 'created_at',
75 | 'gmtoffset' => true,
76 | 'type' => 'datetime',
77 | 'header_css_class' => 'col-updated col-date',
78 | 'column_css_class' => 'col-updated col-date'
79 | ]
80 | );
81 |
82 | $this->addColumn(
83 | 'created_from_store_id',
84 | [
85 | 'header' => __('Created From'),
86 | 'index' => 'created_from_store_id',
87 | 'type' => 'store',
88 | 'renderer' => \Alekseon\CustomFormsBuilder\Block\Adminhtml\Form\Grid\Renderer\CreatedFrom::class
89 | ]
90 | );
91 |
92 | $this->addAttributeColumns();
93 |
94 | $this->addExportType('*/*/exportCsv', __('CSV'));
95 | $this->addExportType('*/*/exportExcel', __('Excel XML'));
96 |
97 | return $this;
98 | }
99 |
100 | /**
101 | * @return mixed
102 | */
103 | protected function getAttributes()
104 | {
105 | return $this->getCurrentForm()->getFieldsCollection();
106 | }
107 |
108 | /**
109 | * @return Grid|void
110 | */
111 | protected function _prepareMassaction()
112 | {
113 | if (!$this->getCurrentForm()->getDeleteRecordDisallowedFlag()) {
114 | $this->setMassactionIdField('entity_id');
115 | $this->getMassactionBlock()->setFormFieldName('records');
116 |
117 | $this->getMassactionBlock()->addItem(
118 | 'delete',
119 | [
120 | 'label' => __('Delete'),
121 | 'url' => $this->getUrl(
122 | '*/*/massDelete',
123 | [
124 | 'id' => $this->getCurrentForm()->getId(),
125 | ]
126 | ),
127 | 'confirm' => __('Are you sure?')
128 | ]
129 | );
130 | }
131 | }
132 |
133 | /**
134 | * @return Form
135 | */
136 | protected function getCurrentForm()
137 | {
138 | return $this->coreRegistry->registry('current_form');
139 | }
140 |
141 | /**
142 | * @param \Magento\Framework\DataObject $row
143 | * @return string
144 | */
145 | public function getRowUrl($row)
146 | {
147 | return $this->getUrl('*/*/edit',
148 | [
149 | 'id' => $row->getEntityId(),
150 | 'form_id' => $this->getCurrentForm()->getId()
151 | ]
152 | );
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | ## [Unreleased]
5 | ### Changed
6 | ### Fixed
7 | ### Added
8 |
9 | ## [102.3.14] - 2024-11-17
10 | ### Added
11 | - postal code validator
12 | - file uploader validations (moved from Alekseon_CustomFormBilder)
13 |
14 | ## [102.3.13] - 2024-09-25
15 | ### Fixed
16 | - fix getMappedAttributeCode method
17 |
18 | ## [102.3.12] - 2024-05-24
19 | ### Fixed
20 | - Translate labels (https://github.com/Alekseon/AlekseonEav/issues/45)
21 |
22 | ## [102.3.11] - 2024-05-09
23 | ### Fixed
24 | - make "Admin Note" translatable
25 |
26 | ## [102.3.10] - 2024-02-25
27 | ### Changed
28 | - Raplaced "Is Enabled" by "Input Visibility", it allows to set input visibility to: visible, only for admin or none
29 |
30 | ## [102.3.9] - 2023-12-03
31 | ### Added
32 | - Max Size param (for file input validator)
33 | - note for params
34 |
35 | ## [102.3.8] - 2023-05-22
36 | ### Added
37 | - manage form button on records view + acl permission
38 | - Yes/No option source
39 | - check if source model class exists
40 | ### Fixed
41 | - fix for saving fields in tabs for new forms
42 |
43 | ## [102.3.7] - 2023-05-09
44 | ### Changed
45 | - code quality improvements
46 | - replaced install and upgrade scripts by patches
47 | ### Fixed
48 | - hide delete massaction if no permisstion set
49 |
50 | ## [102.3.6] - 2023-05-08
51 | ### Changed
52 | - code quality improvements
53 |
54 | ## [102.3.5] - 2023-05-01
55 | ### Added
56 | - github actions
57 | - introduced strict_types
58 | ### Fixed
59 | - display default label instead of store label as fieldset label
60 | - stay on same scope view after "save and continue" form
61 | - code quality improvements
62 |
63 | ## [102.3.4] - 2023-04-22
64 | ### Fixed
65 | - fixed mass delete action
66 | - remove image file during mass delete action
67 |
68 | ## [102.3.3] - 2023-04-21
69 | ### Added
70 | - Created From Store Id for Record entity
71 | - system.xml file
72 | ### Fixed
73 | - added missing group_fields_in column to alekseon_custom_form table
74 |
75 | ## [102.3.2] - 2023-03-12
76 | ### Added
77 | - small alekseon logo
78 | - cache tags
79 | - getRecordCollection() and getRecordById() methods in Form class
80 | - filter,sort,select on form records collection by field identifier
81 | - getData from form record by field identifier
82 |
83 | ## [102.3.1] - 2023-03-04
84 | ### Fixed
85 | - removed "Options Source" input from rating and boolean fields
86 |
87 | ## [102.3.0] - 2023-03-03
88 | ### Added
89 | - possibility to disable form field
90 | - check if "is required" field is editable
91 | - scopable records grid and record edit page
92 | - group fields in tabs
93 | - added "alekseon/widget-forms-statistics" in composer
94 | ### Changed
95 | - use ajax on grids
96 |
97 | ## [102.2.3] - 2023-02-27
98 | ### Added
99 | - notification with link to wiki
100 |
101 | ## [102.2.2] - 2022-11-19
102 | ### Fixed
103 | - fix setUp() declaration in tests
104 | ### Added
105 | - admin note field
106 | - mass delete action for form records
107 |
108 | ## [102.2.1] - 2022-10-22
109 | ### Fixed
110 | - fix error during setup:upgrade for fresh installation
111 |
112 | ## [102.2.0] - 2022-10-22
113 | ### Added
114 | - form identifier
115 | - field identifier
116 | - form property in form record attribute
117 | - added alekseon/custom-forms-frontend requirerment to composer
118 | ### Changed
119 | - max length validator modifications
120 | - moved table definition to db_schema.xml
121 |
122 | ## [102.1.2] - 2022-10-13
123 | ### Changed
124 | - chenged composer requirements
125 | - small fix in setup upgrade
126 |
127 | ## [102.1.1] - 2022-10-12
128 | ### Changed
129 | - attribute_code field length in DB to 255 chars
130 | ### Added
131 | - attribute source: TextFormAttributes
132 |
133 | ## [102.1.0] - 2022-10-10
134 | ### Changed
135 | - Move new entity mail notification functionality to alekseon/custom-forms-email-notification
136 |
137 | ## [102.0.8] - 2022-10-05
138 | ### Added
139 | - compability to attribute default values
140 |
141 | ## [102.0.7] - 2022-10-04
142 | ### Changed
143 | - chenged composer requirements
144 |
145 | ## [102.0.6] - 2022-09-27
146 | ### Added
147 | - created at field for form
148 | - hashed images names and directory name for images (needs eav in version 101.0.11)
149 | - input params (needs eav in version 101.0.11)
150 |
151 | ## [102.0.5] - 2022-08-02
152 | ### Fixed
153 | - fix visibility of configuration
154 |
155 | ## [102.0.4] - 2020-05-02
156 | ### Added
157 | - csv and excel exports
158 | - show custome forms in adminhtml menu
159 | - permissions to view and save custom forms
160 |
161 | ## [102.0.3] - 2020-04-14
162 | ### Fixed
163 | - fixed issue with missing created_at column on fresh installation
164 |
165 | ## [102.0.1] - 2020-04-01
166 | ### Added
167 | - new entity notifiaction email
168 | - option sources for select attributes
169 | - form record created at column
170 | - record attribute variables for events
171 |
172 | ## [102.0.0] - 2020-10-15
173 | ### Added
174 | - Added compatibility with Magento 2.4.0
175 |
176 | ## [101.0.0] - 2020-04-27
177 | ### Added
178 | - init
179 |
180 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Form.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
40 | $this->formRepository = $formRepository;
41 | parent::__construct($context);
42 | }
43 |
44 | /**
45 | * @param string $requestParam
46 | * @param int | null $storeId
47 | * @return \Alekseon\CustomFormsBuilder\Model\Form
48 | */
49 | protected function initForm(string $requestParam = 'entity_id', int $storeId = null)
50 | {
51 | $form = $this->coreRegistry->registry('current_form');
52 | if (!$form) {
53 | $entityId = $this->getRequest()->getParam($requestParam, false);
54 | if ($storeId === null) {
55 | $storeId = $this->getRequest()->getParam('store');
56 | }
57 | $form = $this->formRepository->getById($entityId, $storeId, true);
58 | $this->coreRegistry->register('current_form', $form);
59 | }
60 | return $form;
61 | }
62 |
63 | /**
64 | * @return $this
65 | */
66 | protected function _initAction()
67 | {
68 | $this->_view->loadLayout();
69 | $this->_setActiveMenu(
70 | 'Alekseon_CustomFormsBuilder::custom_form'
71 | )->_addBreadcrumb(
72 | __('CMS'),
73 | __('CMS')
74 | )->_addBreadcrumb(
75 | __('Manage Custom Forms'),
76 | __('Manage Custom Forms')
77 | );
78 | return $this;
79 | }
80 |
81 | /**
82 | * @param string $path
83 | * @param array $params
84 | * @return mixed
85 | */
86 | protected function returnResult($path = '', array $params = [])
87 | {
88 | return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setPath($path, $params);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Form/Delete.php:
--------------------------------------------------------------------------------
1 | initForm();
24 | if ($form->getId()) {
25 | try {
26 | $form->delete();
27 | $this->messageManager->addSuccessMessage(__('You deleted the form.'));
28 | return $this->returnResult('*/*/', []);
29 | } catch (\Exception $e) {
30 | $this->messageManager->addErrorMessage($e->getMessage());
31 | return $this->returnResult('*/*/', []);
32 | }
33 | }
34 | $this->messageManager->addErrorMessage(__('We can\'t find an form to delete.'));
35 | return $this->returnResult('*/*/');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Form/Edit.php:
--------------------------------------------------------------------------------
1 | _initAction();
24 | $entity = $this->initForm();
25 |
26 | if ($entity->getId()) {
27 | $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Edit Form'). ' ' . $entity->getTitle());
28 | } else {
29 | $this->_view->getPage()->getConfig()->getTitle()->prepend(__('New Custom Form'));
30 | }
31 |
32 | $this->_view->renderLayout();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Form/Index.php:
--------------------------------------------------------------------------------
1 | _initAction();
27 | if ($this->getRequest()->getParam('isAjax')) {
28 | $this->getResponse()->setBody(
29 | $this->_view->getLayout()->getBlock('grid')->toHtml()
30 | );
31 | return;
32 | } else {
33 | $this->_view->getPage()->getConfig()->getTitle()->prepend(__('Custom Forms'));
34 | $this->_view->renderLayout();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Form/NewAction.php:
--------------------------------------------------------------------------------
1 | resultForwardFactory = $resultForwardFactory;
34 | }
35 |
36 | /**
37 | * @return \Magento\Backend\Model\View\Result\Forward
38 | */
39 | public function execute()
40 | {
41 | return $this->resultForwardFactory->create()->forward('edit');
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Form/Save.php:
--------------------------------------------------------------------------------
1 | getRequest()->getParam('back', false)) {
27 | $returnToEdit = true;
28 | }
29 |
30 | $form = false;
31 | $data = $this->getRequest()->getPostValue();
32 |
33 | if ($data) {
34 | $form = $this->initForm();
35 | $form->addData($data);
36 | $this->processTabs($form, $data);
37 |
38 | try {
39 | $form->getResource()->save($form);
40 | $this->messageManager->addSuccessMessage(__('You saved the form.'));
41 | } catch (\Exception $e) {
42 | $this->messageManager->addErrorMessage($e->getMessage());
43 | $returnToEdit = true;
44 | }
45 | }
46 |
47 | if ($returnToEdit && $form) {
48 | return $this->returnResult('*/*/edit', ['_current' => true, 'entity_id' => $form->getId()]);
49 | } else {
50 | if ($this->getRequest()->getParam('back_to_records')) {
51 | return $this->returnResult('*/formRecord/index', ['id' => $form->getId()]);
52 | } else {
53 | return $this->returnResult('*/*/');
54 | }
55 | }
56 | }
57 |
58 | /**
59 | * @param Form $form
60 | * @param array $data
61 | * @return void
62 | */
63 | private function processTabs(Form $form, array $data = [])
64 | {
65 | if (isset($data['form_tabs'])) {
66 | $fomTabs = $form->getFormTabs();
67 | /** @var FormTab $tab */
68 | foreach ($fomTabs as $tab) {
69 | if ($tab->getId() && !isset($data['form_tabs'][$tab->getId()])) {
70 | $tab->setDeleted(true);
71 | }
72 | }
73 | foreach ($data['form_tabs'] as $tabId => $tabData) {
74 | /** @var FormTab $tab */
75 | $tab = $fomTabs[$tabId] ?? false;
76 | if ($tab) {
77 | $tab->addData($tabData);
78 | } else {
79 | $tabData['tmp_tab_id'] = $tabId;
80 | $form->addFormTab($tabData);
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormField.php:
--------------------------------------------------------------------------------
1 | resultPageFactory = $resultPageFactory;
45 | $this->coreRegistry = $coreRegistry;
46 | $this->attributeRepository = $attributeRepository;
47 | parent::__construct($context);
48 | }
49 |
50 | /**
51 | * @param string $requestParam
52 | * @return bool|mixed
53 | * @throws \Magento\Framework\Exception\NoSuchEntityException
54 | */
55 | protected function initAttribute($requestParam = 'id')
56 | {
57 | $attribute = $this->coreRegistry->registry('current_attribute');
58 | if (!$attribute) {
59 | $attributeId = $this->getRequest()->getParam($requestParam, false);
60 | if ($attributeId) {
61 | $attribute = $this->attributeRepository->getById($attributeId);
62 | } else {
63 | return false;
64 | }
65 | $this->coreRegistry->register('current_attribute', $attribute);
66 | }
67 | return $attribute;
68 | }
69 |
70 | /**
71 | * @param string $path
72 | * @param array $params
73 | * @return mixed
74 | */
75 | protected function returnResult($path = '', array $params = [])
76 | {
77 | return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setPath($path, $params);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormField/Edit.php:
--------------------------------------------------------------------------------
1 | initAttribute();
25 | } catch (\Exception $e) {
26 | $this->messageManager->addErrorMessage($e->getMessage());
27 | return $this->returnResult('*/form/index');
28 | }
29 | /** @var \Magento\Backend\Model\View\Result\Page $resultPage */
30 | $resultPage = $this->resultPageFactory->create();
31 | if ($attribute) {
32 | $resultPage->getConfig()->getTitle()->prepend(__('Edit Form Field') . ' ' . $attribute->getFrontendLabel());
33 | } else {
34 | $this->messageManager->addErrorMessage(__('Form Field not found.'));
35 | return $this->returnResult('*/form/index');
36 | }
37 | return $resultPage;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormField/Save.php:
--------------------------------------------------------------------------------
1 | getRequest()->getPostValue();
25 | if ($data) {
26 | $attribute = $this->initAttribute();
27 | $attribute->addData($data);
28 | try {
29 | $this->attributeRepository->save($attribute);
30 | $this->messageManager->addSuccessMessage(__('You saved the form field.'));
31 | } catch (\Exception $e) {
32 | $this->messageManager->addErrorMessage($e->getMessage());
33 | }
34 | return $this->returnResult('*/form/edit', ['entity_id' => $attribute->getFormId()]);
35 | }
36 | return $this->returnResult('*/form/index', []);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
58 | $this->formRepository = $formRepository;
59 | $this->formRecordFactory = $formRecordFactory;
60 | $this->fileFactory = $fileFactory;
61 | $this->dataPersistor = $dataPersistor;
62 | parent::__construct($context);
63 | }
64 |
65 | /**
66 | * @return bool
67 | */
68 | protected function _isAllowed($formRequestParam = 'form_id')
69 | {
70 | $manageResource = 'Alekseon_CustomFormsBuilder::manage_custom_forms';
71 | if ($this->_authorization->isAllowed($manageResource)) {
72 | return true;
73 | }
74 |
75 | $form = $this->initForm($formRequestParam);
76 | if ($form) {
77 | $resource = $this->getIsAllowedResource($form);
78 | } else {
79 | $resource = static::ADMIN_RESOURCE;
80 | }
81 |
82 | return $this->_authorization->isAllowed($resource);
83 | }
84 |
85 | /**
86 | * @param $form
87 | * @return string
88 | */
89 | protected function getIsAllowedResource($form)
90 | {
91 | return 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId();
92 | }
93 |
94 | /**
95 | * @param string $requestParam
96 | * @return \Alekseon\CustomFormsBuilder\Model\Form
97 | * @throws \Magento\Framework\Exception\NoSuchEntityException
98 | */
99 | protected function initForm($requestParam = 'id')
100 | {
101 | $form = $this->coreRegistry->registry('current_form');
102 | if (!$form) {
103 | $fromId = $this->getRequest()->getParam($requestParam, false);
104 | $storeId = $this->getRequest()->getParam('store', null);
105 | $form = $this->formRepository->getById($fromId, $storeId, true);
106 |
107 | if (!$this->isSaveRecordAllowed($form)) {
108 | $form->setSaveRecordDisallowedFlag(true);
109 | }
110 | if (!$this->isDeleteRecordAllowed($form)) {
111 | $form->setDeleteRecordDisallowedFlag(true);
112 | }
113 | if (!$this->isManageFormAllowed($form)) {
114 | $form->setManageFormAllowedDisallowedFlag(true);
115 | }
116 |
117 | $this->coreRegistry->register('current_form', $form);
118 | }
119 | return $form;
120 | }
121 |
122 | /**
123 | * @param string $requestParam
124 | * @param string $formRequestParam
125 | * @return \Alekseon\CustomFormsBuilder\Model\FormRecord
126 | * @throws LocalizedException
127 | */
128 | protected function initRecord(string $requestParam = 'id', string $formRequestParam = 'form_id')
129 | {
130 | $record = $this->coreRegistry->registry('current_record');
131 | $form = $this->initForm($formRequestParam);
132 | if (!$record) {
133 | $recordId = $this->getRequest()->getParam($requestParam, false);
134 | $record = $form->getRecordById($recordId, true);
135 | if (!$record->getId()) {
136 | $record->setFormId($form->getId());
137 | }
138 |
139 | $data = $this->dataPersistor->get('custom_form_record');
140 | if (!empty($data)) {
141 | $record->addData($data);
142 | $this->dataPersistor->clear('custom_form_record');
143 | }
144 |
145 | $this->coreRegistry->register('current_record', $record);
146 | }
147 |
148 | if (!$form->getId() || $record->getFormId() != $form->getId()) {
149 | throw new LocalizedException(__('Incorrect Form'));
150 | }
151 |
152 | return $record;
153 | }
154 |
155 | /**
156 | * @return $this
157 | */
158 | protected function _initAction()
159 | {
160 | $this->_view->loadLayout();
161 | $this->_setActiveMenu(
162 | 'Alekseon_CustomFormsBuilder::custom_form'
163 | );
164 | return $this;
165 | }
166 |
167 | /**
168 | * @param string $path
169 | * @param array $params
170 | * @return mixed
171 | */
172 | protected function returnResult($path = '', array $params = [])
173 | {
174 | return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setPath($path, $params);
175 | }
176 |
177 | /**
178 | * @param \Alekseon\CustomFormsBuilder\Model\Form $form
179 | * @return bool
180 | */
181 | private function isSaveRecordAllowed(\Alekseon\CustomFormsBuilder\Model\Form $form)
182 | {
183 | $manageResource = 'Alekseon_CustomFormsBuilder::manage_custom_forms';
184 | if ($this->_authorization->isAllowed($manageResource)) {
185 | return true;
186 | }
187 |
188 | $resource = 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId() . '_save';
189 | return $this->_authorization->isAllowed($resource);
190 | }
191 |
192 | /**
193 | * @param \Alekseon\CustomFormsBuilder\Model\Form $form
194 | * @return bool
195 | */
196 | private function isManageFormAllowed(\Alekseon\CustomFormsBuilder\Model\Form $form)
197 | {
198 | $manageResource = 'Alekseon_CustomFormsBuilder::manage_custom_forms';
199 | if ($this->_authorization->isAllowed($manageResource)) {
200 | return true;
201 | }
202 |
203 | $resource = 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId() . '_manage_form';
204 | return $this->_authorization->isAllowed($resource);
205 | }
206 |
207 | /**
208 | * @param \Alekseon\CustomFormsBuilder\Model\Form $form
209 | * @return bool
210 | */
211 | private function isDeleteRecordAllowed(\Alekseon\CustomFormsBuilder\Model\Form $form)
212 | {
213 | return $this->isSaveRecordAllowed($form);
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/Delete.php:
--------------------------------------------------------------------------------
1 | initForm('form_id');
24 | try {
25 | $record = $this->initRecord();
26 | if ($record->getId()) {
27 | $record->delete();
28 | $this->messageManager->addSuccessMessage(__('You deleted the record.'));
29 | }
30 | return $this->returnResult('*/*', ['id' => $form->getId()]);
31 | } catch (\Exception $e) {
32 | $this->messageManager->addErrorMessage($e->getMessage());
33 | return $this->returnResult('*/*', ['id' => $form->getId()]);
34 | }
35 | }
36 |
37 | /**
38 | * @param $form
39 | * @return string
40 | */
41 | protected function getIsAllowedResource($form)
42 | {
43 | return 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId() . '_save';
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/Edit.php:
--------------------------------------------------------------------------------
1 | initForm('form_id');
24 |
25 | try {
26 | $record = $this->initRecord();
27 | } catch (\Exception $e) {
28 | $this->messageManager->addErrorMessage($e->getMessage());
29 | return $this->returnResult('*/*', ['id' => $form->getId()]);
30 | }
31 |
32 | $this->_initAction();
33 | $title = $record->getForm()->getTitle();
34 | $this->_view->getPage()->getConfig()->getTitle()->prepend($title);
35 | $this->_view->renderLayout();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/ExportCsv.php:
--------------------------------------------------------------------------------
1 | initForm();
28 |
29 | if (!$form->getId()) {
30 | $this->_forward('noroute');
31 | return;
32 | }
33 |
34 | $fileName = 'export_form_' . $form->getId() . '.csv';
35 | /** @var \Alekseon\CustomFormsBuilder\Block\Adminhtml\FormRecord\Grid $grid */
36 | $grid = $this->_view->getLayout()->createBlock(\Alekseon\CustomFormsBuilder\Block\Adminhtml\FormRecord\Grid::class);
37 | return $this->fileFactory->create($fileName, $grid->getCsvFile($fileName), DirectoryList::VAR_DIR);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/ExportExcel.php:
--------------------------------------------------------------------------------
1 | initForm();
28 |
29 | if (!$form->getId()) {
30 | $this->_forward('noroute');
31 | return;
32 | }
33 |
34 | $fileName = 'export_form_' . $form->getId() . '.xml';
35 | $grid = $this->_view->getLayout()->createBlock(\Alekseon\CustomFormsBuilder\Block\Adminhtml\FormRecord\Grid::class);
36 | return $this->fileFactory->create($fileName, $grid->getExcelFile($fileName), DirectoryList::VAR_DIR);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/Index.php:
--------------------------------------------------------------------------------
1 | initForm();
38 |
39 | if (!$form->getId()) {
40 | $this->_forward('noroute');
41 | return;
42 | }
43 |
44 | $this->_initAction();
45 |
46 | if ($this->getRequest()->getParam('isAjax')) {
47 | $this->getResponse()->setBody(
48 | $this->_view->getLayout()->getBlock('grid')->toHtml()
49 | );
50 | } else {
51 | $this->_view->getPage()->getConfig()->getTitle()->prepend($form->getTitle());
52 | $this->_view->renderLayout();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/MassDelete.php:
--------------------------------------------------------------------------------
1 | initForm();
27 |
28 | if (!$form->getId()) {
29 | $this->_forward('noroute');
30 | return;
31 | }
32 |
33 | $recordIds = $this->getRequest()->getParam('records');
34 |
35 | if (!is_array($recordIds)) {
36 | $this->messageManager->addErrorMessage(__('Please select form record(s).'));
37 | } else {
38 | try {
39 | $counter = 0;
40 | foreach ($this->getCollection() as $model) {
41 | $model->delete();
42 | $counter ++;
43 | }
44 | $this->messageManager->addSuccessMessage(
45 | __('A total of %1 record(s) have been deleted.', $counter)
46 | );
47 | } catch (LocalizedException $e) {
48 | $this->messageManager->addErrorMessage($e->getMessage());
49 | } catch (\Exception $e) {
50 | $this->messageManager->addExceptionMessage($e, __('Something went wrong while deleting these records.'));
51 | }
52 | }
53 |
54 | $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
55 | $resultRedirect->setPath('*/formRecord', ['id' => $form->getId()]);
56 | return $resultRedirect;
57 | }
58 |
59 | /**
60 | * @return \Alekseon\CustomFormsBuilder\Model\ResourceModel\FormRecord\Collection
61 | * @throws LocalizedException
62 | */
63 | protected function getCollection()
64 | {
65 | /** @var Form $form */
66 | $form = $this->coreRegistry->registry('current_form');
67 | $collection = $form->getRecordCollection();
68 | $collection->addFieldToFilter(
69 | 'entity_id',
70 | $this->getRequest()->getParam('records')
71 | );
72 |
73 | return $collection;
74 | }
75 |
76 | /**
77 | * @param $form
78 | * @return string
79 | */
80 | protected function getIsAllowedResource($form)
81 | {
82 | return 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId() . '_save';
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/NewAction.php:
--------------------------------------------------------------------------------
1 | resultForwardFactory = $resultForwardFactory;
34 | }
35 |
36 | /**
37 | * @return \Magento\Backend\Model\View\Result\Forward
38 | */
39 | public function execute()
40 | {
41 | return $this->resultForwardFactory->create()->forward('edit');
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/FormRecord/Save.php:
--------------------------------------------------------------------------------
1 | getRequest()->getParam('back', false)) {
24 | $returnToEdit = true;
25 | } else {
26 | $returnToEdit = false;
27 | }
28 |
29 | $form = $this->initForm('form_id');
30 | $data = $this->getRequest()->getPostValue();
31 | $record = $this->initRecord();
32 |
33 | if ($data) {
34 | try {
35 | $record->addData($data);
36 | $record->setFormId($form->getId());
37 | $record->getResource()->save($record);
38 | $this->dataPersistor->clear('custom_form_record');
39 | $this->messageManager->addSuccessMessage(__('You saved the record.'));
40 | } catch (\Exception $e) {
41 | $this->dataPersistor->set('custom_form_record', $data);
42 | $this->messageManager->addErrorMessage($e->getMessage());
43 | $returnToEdit = true;
44 | }
45 | }
46 |
47 | if ($returnToEdit) {
48 | if ($record->getId()) {
49 | return $this->returnResult('*/*/edit', ['_current' => true, 'id' => $record->getId()]);
50 | } else {
51 | return $this->returnResult('*/*/new', ['_current' => true]);
52 | }
53 | } else {
54 | return $this->returnResult('*/*', ['id' => $form->getId()]);
55 | }
56 | }
57 |
58 | /**
59 | * @param $form
60 | * @return string
61 | */
62 | protected function getIsAllowedResource($form)
63 | {
64 | return 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId() . '_save';
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/Model/Attribute/InputValidator/PostalCode.php:
--------------------------------------------------------------------------------
1 | optionsSource = $optionsSource;
42 | $this->postCodeConfig = $postCodeConfig;
43 | parent::__construct($data);
44 | }
45 |
46 | /**
47 | * @return string
48 | */
49 | public function getValidationFieldClass()
50 | {
51 | $countryFieldId = $this->attribute->getInputParam('post_code_country_field_id');
52 | if ($countryFieldId) {
53 | return 'alekseon-validate-postal-code';
54 | }
55 | return parent::getValidationFieldClass();
56 | }
57 |
58 | /**
59 | * @inheritDoc
60 | */
61 | public function getDataValidateParams()
62 | {
63 | $countryFieldId = $this->attribute->getInputParam('post_code_country_field_id');
64 | if ($countryFieldId) {
65 | return [
66 | 'alekseon-validate-postal-code' => $countryFieldId,
67 | ];
68 | }
69 | return parent::getDataValidateParams();
70 | }
71 |
72 | /**
73 | * @inheritDoc
74 | */
75 | public function getAdminDataValidateParams()
76 | {
77 | return $this->attribute->getInputParam('post_code_country_field_id');
78 | }
79 |
80 | /**
81 | * @inheritDoc
82 | */
83 | public function validateValue($value)
84 | {
85 | $countryFieldId = $this->attribute->getInputParam('post_code_country_field_id');
86 | if (!$countryFieldId) {
87 | return true;
88 | }
89 | $entity = $this->getEntity();
90 | $countryId = $entity->getData($countryFieldId);
91 | if (!$countryId) {
92 | return true;
93 | }
94 |
95 | $postCodes = $this->postCodeConfig->getPostCodes();
96 | $patterns = $postCodes[$countryId] ?? [];
97 |
98 | if (empty($patterns)) {
99 | return true;
100 | }
101 |
102 | foreach ($patterns as $patternData) {
103 | $pattern = $patternData['pattern'] ?? '';
104 | if (!$pattern) {
105 | continue;
106 | }
107 |
108 | if (preg_match('/' . $pattern. '/', $value)) {
109 | return true;
110 | }
111 | }
112 |
113 | return false;
114 | }
115 |
116 | /**
117 | * @return mixed
118 | */
119 | public function getInputParams()
120 | {
121 | $inputParams = parent::getInputParams();
122 | $inputParams['post_code_country_field_id'] = [
123 | 'label' => 'Country Field',
124 | 'type' => 'select',
125 | 'options' => $this->optionsSource->getOptionArray(true),
126 | 'note' => 'Used for Postal Code Validation',
127 | ];
128 | return $inputParams;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Model/Attribute/Source/SelectFormAttributes.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
32 | }
33 |
34 | /**
35 | * @inheritDoc
36 | */
37 | protected function getEmptyOptionLabel()
38 | {
39 | return __('Not Selected');
40 | }
41 |
42 | /**
43 | * @return array
44 | */
45 | public function getOptions()
46 | {
47 | $options = [];
48 |
49 | /** @var Form $form */
50 | $form = $this->coreRegistry->registry('current_form');
51 |
52 | if ($form) {
53 | $fields = $form->getFieldsCollection();
54 | foreach ($fields as $field) {
55 | if ($field->getFrontendInput() == 'select') {
56 | $options[$field->getAttributeCode()] = $field->getFrontendLabel();
57 | }
58 | }
59 | }
60 |
61 | return $options;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Model/Attribute/Source/TextFormAttributes.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
32 | }
33 |
34 | /**
35 | * @return array
36 | */
37 | public function getOptions()
38 | {
39 | $options = [];
40 |
41 | /** @var Form $form */
42 | $form = $this->coreRegistry->registry('current_form');
43 |
44 | if ($form) {
45 | $fields = $form->getFieldsCollection();
46 | foreach ($fields as $field) {
47 | if ($field->getFrontendInput() == 'text') {
48 | $options[$field->getAttributeCode()] = $field->getFrontendLabel();
49 | }
50 | }
51 | }
52 |
53 | return $options;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Model/FieldOptionSources.php:
--------------------------------------------------------------------------------
1 | optionSources = $optionSources;
37 | }
38 |
39 | /**
40 | * @param $code
41 | */
42 | public function getOptionSourceByCode($code)
43 | {
44 | $optionsSources = $this->getOptionSources();
45 | return $optionsSources[$code] ?? false;
46 | }
47 |
48 | /**
49 | * @param $sourceModel
50 | * @return string | false
51 | */
52 | public function getCodeBySourceModel($sourceModel)
53 | {
54 | $this->getOptionSources();
55 | return $this->codesBySourceModel[$sourceModel] ?? false;
56 | }
57 |
58 | /**
59 | * @return array|null
60 | */
61 | public function getOptionSources()
62 | {
63 | if ($this->optionSourcesByCodes === null) {
64 | $this->optionSourcesByCodes = [];
65 | foreach ($this->optionSources as $code => $data) {
66 | $optionSource = new \Magento\Framework\DataObject($data);
67 | $sourceModel = $optionSource->getSourceModel();
68 | if (class_exists($sourceModel)) {
69 | $optionSource->setCode($code);
70 | $this->optionSourcesByCodes[$code] = $optionSource;
71 | $this->codesBySourceModel[$sourceModel] = $code;
72 | }
73 | }
74 | }
75 | return $this->optionSourcesByCodes;
76 | }
77 |
78 | /**
79 | *
80 | */
81 | public function toOptionArray()
82 | {
83 | $options = $this->getOptionSources();
84 | $result = [[
85 | 'value' => self::DEFAULT_ATTRIBUTE_SOURCE_VALUE,
86 | 'label' => __('Default Attribute Options'),
87 | ]];
88 |
89 | foreach ($options as $code => $option) {
90 | $result[] = [
91 | 'value' => $code,
92 | 'label' => __($option->getLabel()),
93 | ];
94 | }
95 | return $result;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Model/Form.php:
--------------------------------------------------------------------------------
1 | recordAttributeRepository = $recordAttributeRepository;
73 | $this->formTabFactory = $formTabFactory;
74 | $this->formRecordFactory = $formRecordFactory;
75 | parent::__construct(
76 | $context,
77 | $registry,
78 | $resource,
79 | $resourceCollection
80 | );
81 | }
82 |
83 | /**
84 | * @return \Alekseon\AlekseonEav\Model\Entity
85 | * @throws \Magento\Framework\Exception\NoSuchEntityException
86 | * @throws \Magento\Framework\Exception\TemporaryState\CouldNotSaveException
87 | */
88 | public function afterSave()
89 | {
90 | $this->updateFields();
91 | $this->addNewFields();
92 |
93 | return parent::afterSave();
94 | }
95 |
96 | /**
97 | * @return void
98 | */
99 | private function addNewFields()
100 | {
101 | $formId = $this->getId();
102 |
103 | $newFieldsData = $this->getNewFields();
104 |
105 | if (!$formId || !is_array($newFieldsData)) {
106 | return;
107 | }
108 |
109 | $attributeFactory = $this->recordAttributeRepository->getAttributeFactory();
110 | foreach ($newFieldsData as $id => $newFieldData) {
111 | if (isset($newFieldData['frontend_label']) && $newFieldData['frontend_label']) {
112 | unset($newFieldData['id']);
113 | $attribute = $attributeFactory->create();
114 | $attribute->setData($newFieldData);
115 | $attribute->setVisibleInGrid(true);
116 | $attribute->setAttributeCode('field_' . $formId . '_' . time() . '_' . $id);
117 | $attribute->setFormId($formId);
118 | $this->updateFieldGroupCode($attribute);
119 | $this->recordAttributeRepository->save($attribute);
120 | }
121 | }
122 | }
123 |
124 | /**
125 | * @return Collection
126 | */
127 | public function getRecordCollection()
128 | {
129 | /** @var Collection $collection */
130 | $collection = $this->formRecordFactory->create()->getCollection();
131 | $collection->setStoreId($this->getStoreId());
132 | $collection->addFormFilter($this);
133 | $collection->getResource()->setCurrentForm($this);
134 | return $collection;
135 | }
136 |
137 | /**
138 | * @param $id
139 | * @return mixed
140 | */
141 | public function getRecordById($id, $graceful = false)
142 | {
143 | $record = $this->formRecordFactory->create();
144 | $record->setStoreId($this->getStoreId());
145 | $record->getResource()->setCurrentForm($this);
146 | $record->getResource()->load($record, $id);
147 | if (!$graceful && (!$record->getId() || $record->getFormId() != $this->getId())) {
148 | throw new NoSuchEntityException(__('Form record not found.'));
149 | }
150 |
151 | return $record;
152 | }
153 |
154 | /**
155 | *
156 | */
157 | private function updateFields()
158 | {
159 | $removedFields = explode(',', $this->getFormRemovedFields());
160 | $formFields = $this->getFormFields();
161 |
162 | foreach ($removedFields as $attributeId) {
163 | if ($attributeId) {
164 | $attribute = $this->recordAttributeRepository->getById($attributeId);
165 | $attribute->delete();
166 | }
167 | }
168 |
169 | if (!is_array($formFields)) {
170 | return;
171 | }
172 |
173 | foreach ($formFields as $fieldData) {
174 | $attributeId = isset($fieldData['id']) ? (int) $fieldData['id'] : false;
175 | if (!$attributeId) {
176 | continue;
177 | }
178 |
179 | if (in_array($attributeId, $removedFields)) {
180 | continue;
181 | }
182 |
183 | $attribute = $this->recordAttributeRepository->getById($attributeId);
184 | unset($fieldData['frontend_input']);
185 | $attribute->addData($fieldData);
186 | $this->updateFieldGroupCode($attribute);
187 | $this->recordAttributeRepository->save($attribute);
188 | }
189 | }
190 |
191 | /**
192 | * @param bool $withDisabled
193 | * @return ResourceModel\FormRecord\Attribute\Collection
194 | */
195 | public function getFieldsCollection(bool $withDisabled = false): ResourceModel\FormRecord\Attribute\Collection
196 | {
197 | if ($this->fieldsCollection === null) {
198 | $isAdmin = $this->_appState->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML;
199 | $attributeObject = $this->recordAttributeRepository->getAttributeFactory()->create();
200 | $this->fieldsCollection = $attributeObject->getCollection();
201 |
202 | if (!$withDisabled) {
203 | if ($isAdmin) {
204 | $this->fieldsCollection->addFieldToFilter(
205 | 'input_visibility',
206 | ['nin' => Attribute::INPUT_VISIBILITY_NONE]
207 | );
208 | } else {
209 | $this->fieldsCollection->addFieldToFilter(
210 | 'input_visibility',
211 | Attribute::INPUT_VISIBILITY_VISIBILE
212 | );
213 | }
214 | }
215 |
216 | $this->fieldsCollection->addFieldToFilter('form_id', $this->getId());
217 | $this->fieldsCollection->setOrder(
218 | 'sort_order',
219 | \Magento\Framework\Data\Collection::SORT_ORDER_ASC
220 | );
221 |
222 | }
223 | return $this->fieldsCollection;
224 | }
225 |
226 | /**
227 | * @return array
228 | */
229 | public function getFormTabs(): array
230 | {
231 | if ($this->formTabs === null) {
232 | /** @var ResourceModel\FormTab\Collection $formTabsCollection */
233 | $formTabsCollection = $this->formTabFactory->create()->getCollection();
234 | $formTabsCollection->addFormFilter($this);
235 | $this->formTabs = [];
236 | $lastTab = false;
237 | foreach ($formTabsCollection as $tab) {
238 | $this->formTabs[$tab->getId()] = $tab;
239 | $lastTab = $tab;
240 | }
241 |
242 | if (!$lastTab) {
243 | $lastTab = $this->addFormTab(
244 | [
245 | 'label' => __(self::DEFAULT_FORM_TAB_LABEL),
246 | ]
247 | );
248 | }
249 |
250 | $lastTab->setIsLastTab(true);
251 | }
252 |
253 | return $this->formTabs;
254 | }
255 |
256 | /**
257 | * @param array $tabData
258 | * @return FormTab
259 | */
260 | public function addFormTab(array $tabData = [])
261 | {
262 | $this->getFormTabs();
263 | $tab = $this->formTabFactory->create();
264 | $tab->setData($tabData);
265 | $this->formTabs[] = $tab;
266 | return $tab;
267 | }
268 |
269 | /**
270 | * @return mixed
271 | */
272 | public function getFirstFormTab()
273 | {
274 | $this->getFormTabs();
275 | return reset($this->formTabs);
276 | }
277 |
278 | /**
279 | * @return string[]
280 | */
281 | public function getIdentities(): array
282 | {
283 | return [
284 | self::CACHE_TAG . '_' . $this->getId(),
285 | ];
286 | }
287 |
288 | /**
289 | * @return string[]
290 | */
291 | public function getCacheTags()
292 | {
293 | return $this->getIdentities();
294 | }
295 |
296 | /**
297 | * @param Attribute $recordAttribute
298 | * @return void
299 | */
300 | private function updateFieldGroupCode(Attribute $recordAttribute)
301 | {
302 | if ($this->getTabIdsMap() === null) {
303 | $tabIdsMap = [];
304 | $formTabs = $this->getFormTabs();
305 | foreach ($formTabs as $tab) {
306 | if ($tab->getTmpTabId()) {
307 | $tabIdsMap[$tab->getTmpTabId()] = $tab->getId();
308 | };
309 | }
310 | $this->setTabIdsMap($tabIdsMap);
311 | }
312 |
313 | $tabIdsMap = $this->getTabIdsMap();
314 | if (isset($tabIdsMap[$recordAttribute->getGroupCode()])) {
315 | $newGroupId = $tabIdsMap[$recordAttribute->getGroupCode()];
316 | $recordAttribute->setGroupCode($newGroupId);
317 | }
318 | }
319 | }
320 |
--------------------------------------------------------------------------------
/Model/Form/Attribute.php:
--------------------------------------------------------------------------------
1 | attributeFactory = $attributeFactory;
29 | }
30 |
31 | /**
32 | * @return AttributeFactory
33 | */
34 | public function getAttributeFactory()
35 | {
36 | return $this->attributeFactory;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Model/FormRecord.php:
--------------------------------------------------------------------------------
1 | formRepository = $formRepository;
46 | parent::__construct(
47 | $context,
48 | $registry,
49 | $resource,
50 | $resourceCollection
51 | );
52 | }
53 |
54 | /**
55 | * @throws \Magento\Framework\Exception\NoSuchEntityException
56 | */
57 | public function getForm()
58 | {
59 | return $this->formRepository->getById($this->getFormId());
60 | }
61 |
62 | /**
63 | * @param Form $form
64 | * @return $this
65 | */
66 | public function setFieldIdentifierMap(Form $form)
67 | {
68 | $fields = $form->getFieldsCollection();
69 | foreach ($fields as $field) {
70 | if ($field->getIdentifier()) {
71 | $this->fieldIdentifierMap[$field->getIdentifier()] = $field->getAttributeCode();
72 | }
73 | }
74 | return $this;
75 | }
76 |
77 | /**
78 | * @param string $attributeCode
79 | * @return string
80 | */
81 | protected function getMappedAttributeCode($attributeCode)
82 | {
83 | $notMappedKeys = ['form_id'];
84 | if (in_array($attributeCode, $notMappedKeys)) {
85 | return $attributeCode;
86 | }
87 | if (!$this->getFormId()) {
88 | return $attributeCode;
89 | }
90 | if ($this->fieldIdentifierMap === null) {
91 | $this->setFieldIdentifierMap($this->getForm());
92 | }
93 | if (isset($this->fieldIdentifierMap[$attributeCode])) {
94 | $attributeCode = $this->fieldIdentifierMap[$attributeCode];
95 | }
96 | return $attributeCode;
97 | }
98 |
99 | public function getAttribute($attributeCode)
100 | {
101 | $attributeCode = $this->getMappedAttributeCode($attributeCode);
102 | return parent::getAttribute($attributeCode);
103 | }
104 |
105 | /**
106 | * @param $key
107 | * @return mixed|void|null
108 | */
109 | protected function _getData($key)
110 | {
111 | $key = $this->getMappedAttributeCode($key);
112 | return parent::_getData($key);
113 | }
114 |
115 | /**
116 | * @param $storeId
117 | * @return FormRecord
118 | */
119 | public function setStoreId($storeId)
120 | {
121 | if (!$this->getId()) {
122 | $this->setCreatedFromStoreId($storeId);
123 | }
124 | return parent::setStoreId($storeId);
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Model/FormRecord/Attribute.php:
--------------------------------------------------------------------------------
1 | fieldOptionSources = $fieldOptionSources;
67 | $this->formRepository = $formRepository;
68 | parent::__construct(
69 | $context, $registry, $inputTypeRepository, $inputValidatorRepository, $resource, $resourceCollection
70 | );
71 | }
72 |
73 | /**
74 | * @return \Alekseon\AlekseonEav\Model\Attribute
75 | */
76 | public function beforeSave()
77 | {
78 | if ($this->getAttributeCode() == 'field_' . $this->getForm()->getId() . '_' . $this->getIdentifier()) {
79 | $this->setIdentifier(null);
80 | }
81 |
82 | if ($optionSourceCode = $this->getOptionSourceCode()) {
83 | $optionSource = $this->fieldOptionSources->getOptionSourceByCode($optionSourceCode);
84 | $backendType = $this->getInputTypeModel()->getDefaultBackendType();
85 |
86 | if ($optionSource) {
87 | $this->setSourceModel($optionSource->getSourceModel());
88 | if ($optionSource->getBackendType()) {
89 | $backendType = $optionSource->getBackendType();
90 | }
91 | $this->setBackendType($backendType);
92 | }
93 |
94 | if ($optionSourceCode == FieldOptionSources::DEFAULT_ATTRIBUTE_SOURCE_VALUE) {
95 | $this->setSourceModel(null);
96 | $this->setBackendType($backendType);
97 | }
98 | }
99 |
100 | $this->setInputParams($this->getInputParams());
101 |
102 | return parent::beforeSave();
103 | }
104 |
105 |
106 | /**
107 | * @param $form
108 | * @return \Alekseon\CustomFormsBuilder\Model\Form\Attribute
109 | */
110 | public function setForm(Form $form)
111 | {
112 | $this->form = $form;
113 | return $this;
114 | }
115 |
116 | /**
117 | * @return mixed
118 | */
119 | public function getForm(): Form
120 | {
121 | if ($this->form === null) {
122 | $this->form = $this->formRepository->getById($this->getFormId());
123 | }
124 |
125 | return $this->form;
126 | }
127 |
128 | /**
129 | * @return string
130 | */
131 | public function getInputVisibility()
132 | {
133 | $options = $this->getInputVisibilityOptions();
134 | $inputVisibility = $this->getData('input_visibility');
135 | if (!isset($options[$inputVisibility])) {
136 | $inputVisibility = self::INPUT_VISIBILITY_VISIBILE;
137 | }
138 | return $inputVisibility;
139 | }
140 |
141 | /**
142 | * @return array
143 | */
144 | public function getInputVisibilityOptions()
145 | {
146 | return [
147 | self::INPUT_VISIBILITY_VISIBILE => __('Visible'),
148 | self::INPUT_VISIBILITY_NONE => __('Not Visible'),
149 | self::INPUT_VISIBILITY_ADMIN_ONLY => __('Only for Admin'),
150 | ];
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/Model/FormRecord/AttributeRepository.php:
--------------------------------------------------------------------------------
1 | attributeFactory = $attributeFactory;
29 | }
30 |
31 | /**
32 | * @return AttributeFactory
33 | */
34 | public function getAttributeFactory()
35 | {
36 | return $this->attributeFactory;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Model/FormRepository.php:
--------------------------------------------------------------------------------
1 | formFactory = $formFactory;
39 | }
40 |
41 | /**
42 | * @param $formId
43 | * @return Form
44 | * @throws NoSuchEntityException
45 | */
46 | public function getById($formId, $storeId = null, $graceful = false)
47 | {
48 | $storeKey = $storeId ?? 'null';
49 | if (!isset($this->loadedFormsByIds[$formId][$storeKey])) {
50 | $form = $this->formFactory->create();
51 | $form->setStoreId($storeId);
52 | $form->getResource()->load($form, $formId);
53 | if (!$form->getId()) {
54 | if ($graceful) {
55 | return $form;
56 | } else {
57 | throw new NoSuchEntityException(__('Form with id "%1" does not exist.', $formId));
58 | }
59 | }
60 | $this->addFormToLoaded($form, $storeKey);
61 | }
62 |
63 | return $this->loadedFormsByIds[$formId][$storeKey];
64 | }
65 |
66 | /**
67 | * @param string $identifier
68 | * @param int|null $storeId
69 | * @param bool $graceful
70 | * @return Form
71 | * @throws NoSuchEntityException
72 | */
73 | public function getByIdentifier(string $identifier, int $storeId = null, bool $graceful = true)
74 | {
75 | $storeKey = $storeId ?? 'null';
76 | if (!isset($this->loadedFormsByIdentifiers[$identifier])) {
77 | /** @var Form $form */
78 | $form = $this->formFactory->create();
79 | $form->setStoreId($storeId);
80 | $form->getResource()->load($form, $identifier, 'identifier');
81 | if (!$form->getId()) {
82 | if ($graceful) {
83 | return $form;
84 | } else {
85 | throw new NoSuchEntityException(__('Form with identifier "%1" does not exist.', $identifier));
86 | }
87 | }
88 | $this->addFormToLoaded($form, $storeKey);
89 | }
90 |
91 | $formId = $this->loadedFormsByIdentifiers[$identifier];
92 | return $this->loadedFormsByIds[$formId][$storeKey];
93 | }
94 |
95 | /**
96 | * @param $form
97 | */
98 | protected function addFormToLoaded($form, $storeKey = 'null')
99 | {
100 | $this->loadedFormsByIds[$form->getId()][$storeKey] = $form;
101 | if ($form->getIdentifier()) {
102 | $this->loadedFormsByIdentifiers[$form->getIdentifier()] = $form->getId();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Model/FormTab.php:
--------------------------------------------------------------------------------
1 | attributeCollectionFactory = $attributeCollectionFactory;
38 | parent::__construct($context, $connectionName);
39 | }
40 |
41 | /**
42 | * @return void
43 | */
44 | protected function _construct() // @codingStandardsIgnoreLine
45 | {
46 | $this->_init('alekseon_custom_form', 'entity_id');
47 | }
48 |
49 | /**
50 | * @param \Magento\Framework\Model\AbstractModel $object
51 | * @return Form
52 | * @throws \Exception
53 | */
54 | protected function _afterSave(\Magento\Framework\Model\AbstractModel $object) // @codingStandardsIgnoreLine
55 | {
56 | $formTabs = $object->getFormTabs();
57 |
58 | if ($formTabs !== null) {
59 | foreach ($formTabs as $tab) {
60 | if ($tab->getDeleted()) {
61 | $tab->getResource()->delete($tab);
62 | continue;
63 | }
64 | if (!$tab->getId()) {
65 | $tab->setFormId($object->getId());
66 | }
67 | $tab->getResource()->save($tab);
68 | }
69 | }
70 |
71 | return parent::_afterSave($object);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Model/ResourceModel/Form/Attribute.php:
--------------------------------------------------------------------------------
1 | _init(
22 | 'Alekseon\CustomFormsBuilder\Model\Form\Attribute',
23 | 'Alekseon\CustomFormsBuilder\Model\ResourceModel\Form\Attribute'
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Model/ResourceModel/Form/Collection.php:
--------------------------------------------------------------------------------
1 | _init(
22 | 'Alekseon\CustomFormsBuilder\Model\Form',
23 | 'Alekseon\CustomFormsBuilder\Model\ResourceModel\Form'
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Model/ResourceModel/FormRecord.php:
--------------------------------------------------------------------------------
1 | attributeCollectionFactory = $attributeCollectionFactory;
52 | parent::__construct($context, $connectionName);
53 | }
54 |
55 | /**
56 | * @return void
57 | */
58 | protected function _construct() // @codingStandardsIgnoreLine
59 | {
60 | $this->_init('alekseon_custom_form_record', 'entity_id');
61 | }
62 |
63 | /**
64 | * @return $this
65 | */
66 | public function loadAllAttributes()
67 | {
68 | if ($this->allAttributesLoaded) {
69 | return $this;
70 | }
71 |
72 | if (!$this->getCurrentForm()) {
73 | return $this;
74 | }
75 |
76 | $attributeCollection = $this->getCurrentForm()->getFieldsCollection();
77 |
78 | foreach ($attributeCollection as $attribute) {
79 | $this->attributes[$attribute->getAttributeCode()] = $attribute;
80 | }
81 | $this->allAttributesLoaded = true;
82 | return $this;
83 | }
84 |
85 | /**
86 | *
87 | */
88 | protected function getCurrentForm()
89 | {
90 | return $this->currentForm;
91 | }
92 |
93 | /**
94 | * @param $form
95 | */
96 | public function setCurrentForm($form)
97 | {
98 | $this->currentForm = $form;
99 | }
100 |
101 | /**
102 | * @param \Magento\Framework\Model\AbstractModel $object
103 | * @param AttributeInterface $attribute
104 | * @param string $fileName
105 | * @return string
106 | */
107 | public function getNameForUploadedFile(
108 | \Magento\Framework\Model\AbstractModel $object,
109 | AttributeInterface $attribute,
110 | string $fileName
111 | ) {
112 | $fileNameParts = explode('.', $fileName);
113 | $ext = end($fileNameParts);
114 | return hash('sha256', $attribute->getAttributeCode() . $object->getId() . time()) . '.' . $ext;
115 | }
116 |
117 | /**
118 | * @return string
119 | */
120 | public function getImagesDirName()
121 | {
122 | $imagesDirName = parent::getImagesDirName();
123 | $form = $this->getCurrentForm();
124 | if ($form) {
125 | return $imagesDirName . '/' . substr(hash('sha256', $form->getCreatedAt() . $form->getId()), 0, 10);
126 | }
127 |
128 | return $imagesDirName;
129 | }
130 |
131 | /**
132 | * @param \Magento\Framework\Model\AbstractModel $object
133 | * @return Entity
134 | */
135 | protected function _beforeDelete(\Magento\Framework\Model\AbstractModel $object)
136 | {
137 | $this->setCurrentForm($object->getForm());
138 | return parent::_beforeDelete($object);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/Model/ResourceModel/FormRecord/Attribute.php:
--------------------------------------------------------------------------------
1 | _init(
22 | 'Alekseon\CustomFormsBuilder\Model\FormRecord\Attribute',
23 | 'Alekseon\CustomFormsBuilder\Model\ResourceModel\FormRecord\Attribute'
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Model/ResourceModel/FormRecord/Collection.php:
--------------------------------------------------------------------------------
1 | _init(
28 | 'Alekseon\CustomFormsBuilder\Model\FormRecord',
29 | 'Alekseon\CustomFormsBuilder\Model\ResourceModel\FormRecord'
30 | );
31 | }
32 |
33 | /**
34 | * @param Form $form
35 | * @return $this
36 | * @throws \Magento\Framework\Exception\LocalizedException
37 | */
38 | public function addFormFilter(Form $form)
39 | {
40 | $this->addFieldToFilter('form_id', $form->getId());
41 | $this->setFieldIdentifierMap($form);
42 | return $this;
43 | }
44 |
45 | public function setFieldIdentifierMap(Form $form)
46 | {
47 | $fields = $form->getFieldsCollection();
48 | foreach ($fields as $field) {
49 | if ($field->getIdentifier()) {
50 | $this->fieldIdentifierMap[$field->getIdentifier()] = $field->getAttributeCode();
51 | }
52 | }
53 | return $this;
54 | }
55 |
56 | /**
57 | * @param string $attributeCode
58 | * @return mixed
59 | */
60 | protected function getMappedAttributeCode($attributeCode)
61 | {
62 | if (isset($this->fieldIdentifierMap[$attributeCode])) {
63 | $attributeCode = $this->fieldIdentifierMap[$attributeCode];
64 | }
65 | return $attributeCode;
66 | }
67 |
68 | /**
69 | * @param $attribute
70 | * @param $condition
71 | * @param $joinType
72 | * @return string
73 | * @throws \Magento\Framework\Exception\LocalizedException
74 | */
75 | protected function getAttributeConditionSql($attribute, $condition, $joinType = 'inner')
76 | {
77 | $attribute = $this->getMappedAttributeCode($attribute);
78 | return parent::getAttributeConditionSql($attribute, $condition, $joinType);
79 | }
80 |
81 | /**
82 | * @param $attribute
83 | * @param $direction
84 | * @return Collection
85 | * @throws \Magento\Framework\Exception\LocalizedException
86 | */
87 | public function addAttributeToSort($attribute, $direction = self::SORT_ORDER_ASC)
88 | {
89 | $attribute = $this->getMappedAttributeCode($attribute);
90 | return parent::addAttributeToSort($attribute, $direction);
91 | }
92 |
93 | /**
94 | * @param $attribute
95 | * @return Collection
96 | * @throws \Magento\Framework\Exception\LocalizedException
97 | */
98 | public function addAttributeToSelect($attribute)
99 | {
100 | if (!is_array($attribute)) {
101 | $attribute = $this->getMappedAttributeCode($attribute);
102 | }
103 | return parent::addAttributeToSelect($attribute);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Model/ResourceModel/FormTab.php:
--------------------------------------------------------------------------------
1 | _init('alekseon_custom_form_tab', 'entity_id');
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Model/ResourceModel/FormTab/Collection.php:
--------------------------------------------------------------------------------
1 | _init(
24 | 'Alekseon\CustomFormsBuilder\Model\FormTab',
25 | 'Alekseon\CustomFormsBuilder\Model\ResourceModel\FormTab'
26 | );
27 | }
28 |
29 | /**
30 | * @param Form $form
31 | * @return $this
32 | */
33 | public function addFormFilter(Form $form)
34 | {
35 | $this->addFieldToFilter('form_id', $form->getId());
36 | return $this;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Plugin/AddCustomFormsToAclTreePlugin.php:
--------------------------------------------------------------------------------
1 | formCollectionFactory = $formCollectionFactory;
37 | }
38 |
39 | /**
40 | * @param Edit $roleTabEdit
41 | * @param $tree
42 | * @return mixed
43 | * @throws \Magento\Framework\Exception\LocalizedException
44 | * @SuppressWarnings(PHPMD.UnusedFormalParameter)
45 | */
46 | public function afterBuild(TreeBuilder $treeBuilder, $result)
47 | {
48 | foreach ($result as $key => $resultElement) {
49 | if ($resultElement['id'] == 'Alekseon_CustomFormsBuilder::custom_forms') {
50 |
51 | $formCollection = $this->formCollectionFactory->create();
52 | $formCollection->addAttributeToSelect('title');
53 | $formCollection->addAttributeToFilter('show_in_menu', true);
54 |
55 | foreach ($formCollection as $form) {
56 | $defaultTitle = __('Form #%1', $form->getId());
57 |
58 | $title = (string) $form->getTitle();
59 | if (strlen($title) < 3) {
60 | $title = $defaultTitle;
61 | }
62 | if (strlen($title) > 50) {
63 | $title = substr($title, 0, 50);
64 | }
65 |
66 | $result[$key]['children'][] = [
67 | 'id' => 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId(),
68 | 'title' => $title,
69 | 'sortOrder' => 1,
70 | 'children' => [
71 | [
72 | 'id' => 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId() . '_save',
73 | 'title' => __('Save'),
74 | 'sortOrder' => 1,
75 | 'children' => [],
76 | ],
77 | [
78 | 'id' => 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId() . '_manage_form',
79 | 'title' => __('Manage Form'),
80 | 'sortOrder' => 2,
81 | 'children' => [],
82 | ]
83 | ],
84 | ];
85 | }
86 | }
87 | }
88 |
89 | return $result;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Plugin/AddCustomFormsToAdminMenuPlugin.php:
--------------------------------------------------------------------------------
1 | menuItemFactory = $menuItemFactory;
36 | $this->formCollectionFactory = $formCollectionFactory;
37 | }
38 |
39 | /**
40 | * @param $builder
41 | * @param $menu
42 | * @return mixed
43 | * @throws \Magento\Framework\Exception\LocalizedException
44 | * @SuppressWarnings(PHPMD.UnusedFormalParameter)
45 | */
46 | public function afterGetResult($builder, $menu)
47 | {
48 | $formCollection = $this->formCollectionFactory->create();
49 | $formCollection->addAttributeToSelect('title');
50 | $formCollection->addAttributeToFilter('show_in_menu', true);
51 |
52 | foreach ($formCollection as $form) {
53 | $defaultTitle = __('Form #%1', $form->getId());
54 |
55 | $title = $form->getTitle();
56 | if (strlen($title) < 3) {
57 | $title = $defaultTitle;
58 | }
59 | if (strlen($title) > 50) {
60 | $title = substr($title, 0, 50);
61 | }
62 |
63 | $params = [
64 | 'id' => 'custom_form_' . $form->getId(),
65 | 'title' => $title,
66 | 'resource' => 'Alekseon_CustomFormsBuilder::custom_form_' . $form->getId(),
67 | 'action' => 'alekseon_customFormsBuilder/formRecord/index/id/' . $form->getId(),
68 | ];
69 |
70 | try {
71 | $item = $this->menuItemFactory->create($params);
72 | } catch (\InvalidArgumentException $e) {
73 | $params['title'] = (string) $defaultTitle;
74 | $item = false;
75 | }
76 |
77 | try {
78 | if (!$item) {
79 | $item = $this->menuItemFactory->create($params);
80 | }
81 | $contentElements = $menu->get('Alekseon_CustomFormsBuilder::custom_forms');
82 | $contentElements->getChildren()->add(
83 | $item,
84 | null,
85 | 1
86 | );
87 | } catch (\Exception $e) {
88 |
89 | }
90 | }
91 |
92 | return $menu;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Alekseon_CustomFormsBuilder
7 |
8 |
9 |
10 | A Custom Form Builder for Magento 2
11 |
12 | Let you create custom forms in Admin panel
13 |
14 |
15 |
16 |
18 |
19 |
20 |
22 |
23 |
24 |
26 |
27 |
28 |
29 | ## Installation
30 |
31 | In your Magento2 root directory, you may install this package via composer:
32 |
33 | ```
34 | composer require alekseon/custom-forms-builder
35 | bin/magento setup:upgrade
36 | ```
37 |
38 | ## Dependencies
39 |
40 | This extension gives you possibility to create forms in admin panel. If you want to place them on frontend by CMS content, please check this extension: [Alekseon_WidgetForms](https://github.com/Alekseon/magento2-widget-forms)
41 |
42 |
43 | ## Support
44 |
45 | CJM Ver. | Magento 2.0 | Magento 2.1 | Magento 2.2 | Magento 2.3 | Magento 2.4
46 | --- | :---: | :---: | :---: | :---: | :---:
47 | 1.x | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark:
48 |
49 |
50 | ## Features
51 |
52 | ### Create fully customized forms in Magento2 Admin Panel
53 |
54 |
55 | Create as many forms as you need. Define the title and the fields.
56 | You can choose from field types:
57 | * Text Field
58 | * Text Area
59 | * Yes/No
60 | * Dropdown
61 | * Multiple Select
62 | * Date
63 | * Image
64 |
65 |
66 |
67 | ### Manage fields as regular attributes
68 |
69 | Thanks to the EAV structure, you can manage every field of your form similarly to how you manage regular attribute in Magento.
70 |
71 |
72 |
73 |
74 |
75 |
76 | ### Add and access your form objects easily
77 |
78 | You can view and manage the form applications by regular Magento grid
79 |
80 |
81 |
82 | ### Add Forms to CMS Pages
83 |
84 | Please refer to [Alekseon_WidgetForms](https://github.com/Alekseon/magento2-widget-forms) if you want to be able to add these forms to CMS pages for your customers.
85 |
86 | ### Email notifications
87 |
88 | @Todo
89 |
90 |
91 | ## Issue Tracking / Upcoming Features
92 |
93 | For issues, please use the [issue tracker](https://github.com/Alekseon/magento2-custom-forms-builder/issues).
94 |
95 | Issues keep this project alive and strong, so let us know if you find anything!
96 |
97 | We're planning on pumping out a ton of new features, which you can follow on our [project page](https://github.com/Alekseon/magento2-custom-forms-builder/projects/1).
98 |
99 | ### Development / Contribution
100 |
101 | If you want to contribute please follow the below instructions:
102 |
103 | 1. Create an issue and describe your idea
104 | 2. [Fork this repository](https://github.com/Alekseon/magento2-custom-forms-builder/fork)
105 | 3. Create your feature branch (`git checkout -b my-new-feature`)
106 | 4. Commit your changes
107 | 5. Publish the branch (`git push origin my-new-feature`)
108 | 6. Submit a new Pull Request for review
109 |
110 | ## Maintainers
111 |
112 | Current maintainers:
113 |
114 | * [Linek](https://github.com/Linek)
115 | * [marcinfr](https://github.com/marcinfr)
116 |
117 | See also our [contributors](https://github.com/Alekseon/magento2-custom-forms-builder/graphs/contributors)
118 |
119 |
120 | ## License
121 |
122 | [The Open Software License 3.0 (OSL-3.0)](https://opensource.org/licenses/OSL-3.0)
123 |
--------------------------------------------------------------------------------
/Setup/Patch/Data/CreateWidgetFormsAttributesPatch.php:
--------------------------------------------------------------------------------
1 | moduleDataSetup = $moduleDataSetup;
47 | $this->eavSetupFactory = $eavSetupFactory;
48 | $this->formAttributeRepository = $formAttributeRepository;
49 | }
50 |
51 | /**
52 | * @inheritdoc
53 | * @SuppressWarnings(PHPMD.UnusedFormalParameter)
54 | */
55 | public function apply()
56 | {
57 | $this->moduleDataSetup->getConnection()->startSetup();
58 |
59 | /** @var EavDataSetup $eavSetup */
60 | $eavSetup = $this->eavSetupFactory->create();
61 | $eavSetup->setAttributeRepository($this->formAttributeRepository);
62 |
63 | $this->createFormAttributes($eavSetup);
64 |
65 | $this->moduleDataSetup->getConnection()->endSetup();
66 | return $this;
67 | }
68 |
69 | /**
70 | * @param $eavSetup
71 | * @return void
72 | */
73 | private function createFormAttributes($eavSetup)
74 | {
75 | $eavSetup->createAttribute(
76 | 'title',
77 | [
78 | 'frontend_input' => 'text',
79 | 'frontend_label' => 'Title',
80 | 'visible_in_grid' => true,
81 | 'is_required' => true,
82 | 'sort_order' => 10,
83 | 'scope' => Scopes::SCOPE_STORE,
84 | ]
85 | );
86 |
87 | $eavSetup->createAttribute(
88 | 'show_in_menu',
89 | [
90 | 'frontend_input' => 'boolean',
91 | 'frontend_label' => 'Show in adminhtml menu',
92 | 'visible_in_grid' => false,
93 | 'is_required' => false,
94 | 'sort_order' => 40,
95 | 'scope' => Scopes::SCOPE_GLOBAL,
96 | 'note' => __('Menu -> Marketing -> Custom Forms'),
97 | ]
98 | );
99 | }
100 |
101 | /**
102 | * @inheritdoc
103 | */
104 | public static function getDependencies()
105 | {
106 | return [];
107 | }
108 |
109 | /**
110 | * @inheritdoc
111 | */
112 | public function revert()
113 | {
114 | $this->moduleDataSetup->getConnection()->startSetup();
115 |
116 | $eavSetup = $this->eavSetupFactory->create();
117 | $eavSetup->setAttributeRepository($this->formAttributeRepository);
118 |
119 | $eavSetup->deleteAttribute('title');
120 | $eavSetup->deleteAttribute('show_in_menu');
121 |
122 | $this->moduleDataSetup->getConnection()->endSetup();
123 | }
124 |
125 | /**
126 | * @inheritdoc
127 | */
128 | public function getAliases()
129 | {
130 | return [];
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/Setup/Patch/Schema/CreateEavTablesV2.php:
--------------------------------------------------------------------------------
1 | schemaSetup = $schemaSetup;
38 | $this->eavSetupFactory = $eavSetupFactory;
39 | }
40 |
41 | /**
42 | * @return CreateEavTables|void
43 | */
44 | public function apply()
45 | {
46 | $this->schemaSetup->startSetup();
47 | $setup = $this->schemaSetup;
48 |
49 | $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
50 |
51 | $eavSetup->createFullEavStructure(
52 | 'alekseon_custom_form_attribute',
53 | 'alekseon_custom_form_entity',
54 | null,
55 | 'alekseon_custom_form'
56 | );
57 |
58 | $eavSetup->createFullEavStructure(
59 | 'alekseon_custom_form_record_attribute',
60 | 'alekseon_custom_form_record_entity',
61 | null,
62 | 'alekseon_custom_form_record'
63 | );
64 |
65 | // fix for old module version
66 | $this->updateAttributeCodeColumnSize($setup, 'alekseon_custom_form_attribute');
67 | $this->updateAttributeCodeColumnSize($setup, 'alekseon_custom_form_record_attribute');
68 |
69 | $this->addFormIdColumn($setup);
70 | $this->addIdentifierColumn($setup);
71 | $this->addInputVisibilityColumn($setup);
72 |
73 | $this->schemaSetup->endSetup();
74 | }
75 |
76 |
77 | /**
78 | * @param SchemaSetupInterface $setup
79 | * @param string $attributeTableName
80 | * @return void
81 | */
82 | private function updateAttributeCodeColumnSize(SchemaSetupInterface $setup, string $attributeTableName)
83 | {
84 | $setup->getConnection()->modifyColumn(
85 | $setup->getTable($attributeTableName),
86 | 'attribute_code',
87 | [
88 | 'type' => Table::TYPE_TEXT,
89 | 'nullable' => false,
90 | 'default' => '',
91 | 'length' => 255,
92 | 'comment' => 'Attribute Code'
93 | ]
94 | );
95 | }
96 |
97 | /**
98 | * @param SchemaSetupInterface $setup
99 | * @return void
100 | */
101 | private function addIdentifierColumn(SchemaSetupInterface $setup)
102 | {
103 | $setup->getConnection()->addColumn(
104 | $setup->getTable('alekseon_custom_form_record_attribute'),
105 | 'identifier',
106 | [
107 | 'type' => Table::TYPE_TEXT,
108 | 'length' => 255,
109 | 'comment' => 'Identifier',
110 | 'nullable' => true,
111 | ]
112 | );
113 | $setup->getConnection()->addIndex(
114 | $setup->getTable('alekseon_custom_form_record_attribute'),
115 | $setup->getIdxName(
116 | 'alekseon_custom_form_record_attribute',
117 | ['identifier', 'form_id'],
118 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
119 | ),
120 | ['identifier', 'form_id'],
121 | \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
122 | );
123 | }
124 |
125 | /**
126 | * @param SchemaSetupInterface $setup
127 | * @return void
128 | */
129 | private function addInputVisibilityColumn(SchemaSetupInterface $setup)
130 | {
131 | $recordAttributeTable = $setup->getTable('alekseon_custom_form_record_attribute');
132 |
133 | $columnDefinition = [
134 | 'type' => Table::TYPE_SMALLINT,
135 | 'comment' => 'Input Visibility',
136 | 'nullable' => false,
137 | 'default' => 1,
138 | ];
139 |
140 | /**
141 | * rename in_enabled column to input_visibility for previous module versions
142 | * or add new column for new installations
143 | */
144 | if ($setup->getConnection()->tableColumnExists($recordAttributeTable, 'is_enabled')) {
145 | $setup->getConnection()->changeColumn(
146 | $recordAttributeTable,
147 | 'is_enabled',
148 | 'input_visibility',
149 | $columnDefinition
150 | );
151 | } else {
152 | $setup->getConnection()->addColumn(
153 | $recordAttributeTable,
154 | 'input_visibility',
155 | $columnDefinition
156 | );
157 | }
158 | }
159 |
160 | /**
161 | * @param SchemaSetupInterface $setup
162 | * @return void
163 | */
164 | private function addFormIdColumn(SchemaSetupInterface $setup)
165 | {
166 | $setup->getConnection()->addColumn(
167 | $setup->getTable('alekseon_custom_form_record_attribute'),
168 | 'form_id',
169 | [
170 | 'type' => Table::TYPE_INTEGER,
171 | 'unsigned' => true,
172 | 'nullable' => false,
173 | 'comment' => 'Form Id'
174 | ]
175 | );
176 |
177 | $setup->getConnection()->addForeignKey(
178 | $setup->getConnection()->getForeignKeyName(
179 | $setup->getTable('alekseon_custom_form_record_attribute'),
180 | 'form_id',
181 | $setup->getTable('alekseon_custom_form'),
182 | 'entity_id'
183 | ),
184 | $setup->getTable('alekseon_custom_form_record_attribute'),
185 | 'form_id',
186 | $setup->getTable('alekseon_custom_form'),
187 | 'entity_id',
188 | AdapterInterface::FK_ACTION_CASCADE
189 | );
190 | }
191 |
192 | /**
193 | * @return array
194 | */
195 | public function getAliases()
196 | {
197 | return [];
198 | }
199 |
200 | /**
201 | * @return array
202 | */
203 | public static function getDependencies()
204 | {
205 | return [];
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/Test/Unit/Model/FormRepositoryTest.php:
--------------------------------------------------------------------------------
1 | getMockBuilder(\Alekseon\CustomFormsBuilder\Model\FormFactory::class)
41 | ->disableOriginalConstructor()
42 | ->setMethods(['create'])
43 | ->getMock();
44 | $this->formResource = $this->getMockBuilder(\Alekseon\CustomFormsBuilder\Model\ResourceModel\Form::class)
45 | ->disableOriginalConstructor()
46 | ->getMock();
47 | $this->form = $this->getMockBuilder(\Alekseon\CustomFormsBuilder\Model\Form::class)->disableOriginalConstructor()->getMock();
48 |
49 | $formFactory->expects($this->any())
50 | ->method('create')
51 | ->willReturn($this->form);
52 |
53 | $this->formRepository = new FormRepository(
54 | $formFactory
55 | );
56 | }
57 |
58 | /**
59 | * @test
60 | */
61 | public function testGetByIdException()
62 | {
63 | $this->expectException('Magento\Framework\Exception\NoSuchEntityException');
64 | $formId = '123';
65 |
66 | $this->form->expects($this->once())
67 | ->method('getId')
68 | ->willReturn(false);
69 | $this->formResource->expects($this->once())
70 | ->method('load')
71 | ->with($this->form, $formId)
72 | ->willReturn($this->form);
73 | $this->form->expects($this->once())
74 | ->method('getResource')
75 | ->willReturn($this->formResource);
76 | $this->formRepository->getById($formId);
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "alekseon/custom-forms-builder",
3 | "description": "N/A",
4 | "require": {
5 | "alekseon/alekseon-eav": "^101.2.15",
6 | "alekseon/custom-forms-frontend": "*",
7 | "alekseon/custom-forms-email-notification": "*",
8 | "alekseon/widget-forms-statistics": "*"
9 | },
10 | "type": "magento2-module",
11 | "version": "102.3.14",
12 | "license": [
13 | "OSL-3.0",
14 | "AFL-3.0"
15 | ],
16 | "autoload": {
17 | "files": [
18 | "registration.php"
19 | ],
20 | "psr-4": {
21 | "Alekseon\\CustomFormsBuilder\\": ""
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/etc/adminhtml/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | -
19 |
- All Countries
20 | - Alekseon\AlekseonEav\Model\Attribute\Source\Country
21 | - varchar
22 |
23 | -
24 |
- Website Allow Countries
25 | - Alekseon\AlekseonEav\Model\Attribute\Source\WebsiteAllowCountry
26 | - varchar
27 |
28 | -
29 |
- Yes/No
30 | - Alekseon\AlekseonEav\Model\Attribute\Source\YesNo
31 | - int
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/etc/adminhtml/menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/etc/adminhtml/routes.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/etc/adminhtml/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/etc/db_schema.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
11 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
30 |
32 |
34 |
35 |
36 |
37 |
40 |
43 |
44 |
45 |
47 |
48 |
50 |
51 |
52 |
53 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/etc/db_schema_whitelist.json:
--------------------------------------------------------------------------------
1 | {
2 | "alekseon_custom_form": {
3 | "column": {
4 | "entity_id": true,
5 | "created_at": true,
6 | "identifier": true
7 | },
8 | "constraint": {
9 | "PRIMARY": true,
10 | "ALEKSEON_CUSTOM_FORM_IDENTIFIER": true
11 | }
12 | },
13 | "alekseon_custom_form_record": {
14 | "column": {
15 | "entity_id": true,
16 | "form_id": true,
17 | "created_at": true
18 | },
19 | "constraint": {
20 | "PRIMARY": true,
21 | "ALEKSEON_CUSTOM_FORM_RECORD_FORM_ID_ALEKSEON_CUSTOM_FORM_ENTT_ID": true
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 | -
13 |
- Max Length
14 | - Alekseon\AlekseonEav\Model\Attribute\InputValidator\MaxLengthFactory
15 | -
16 |
- text
17 | - textarea
18 |
19 | -
20 |
-
21 |
- Max Length
22 |
23 |
24 |
25 | -
26 |
- Max File Size In MB
27 | - Alekseon\AlekseonEav\Model\Attribute\InputValidator\MaxFileSizeFactory
28 | -
29 |
- image
30 |
31 | -
32 |
-
33 |
- Max Size
34 | - In Mb
35 |
36 |
37 |
38 | -
39 |
- Postal Code
40 | - Alekseon\CustomFormsBuilder\Model\Attribute\InputValidator\PostalCodeFactory
41 | -
42 |
- text
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/registration.php:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | 1
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | general_tab
34 | form_general_tab
35 |
36 |
37 | fields_tab
38 | form_fields_tab
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/view/adminhtml/layout/alekseon_customformsbuilder_form_index.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/view/adminhtml/layout/alekseon_customformsbuilder_formfield_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/view/adminhtml/layout/alekseon_customformsbuilder_formrecord_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 1
18 |
19 |
20 |
21 |
22 |
23 |
24 | Magento\Customer\Block\DataProviders\PostCodesPatternsAttributeData
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/view/adminhtml/layout/alekseon_customformsbuilder_formrecord_index.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 | 1
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/view/adminhtml/templates/form/edit/field/identifier.phtml:
--------------------------------------------------------------------------------
1 |
7 | getSettings() ?>
8 |
9 |
13 | = __('Identifier') ?> :
14 |
15 | = $settings['identifier'] ?? '' ?>
16 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/view/adminhtml/templates/form/edit/tab/fields.phtml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
12 |
13 |
14 | -
15 |
16 |
17 | -
18 | +
19 |
20 |
21 |
22 |
23 |
29 | = /* @noEscape */ $block->getChildHtml('form_fields_tab_form') ?>
30 | = /* @noEscape */ $block->getChildHtml('add_new_field_button') ?>
31 |
32 |
44 |
57 |
--------------------------------------------------------------------------------
/view/adminhtml/templates/form/wikiLink.phtml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 | Need help? Visit
11 |
12 | WIKI page
13 |
14 | to find more information about custom forms or contact us
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/view/adminhtml/templates/formRecord/edit/formInfo.phtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
= $block->getTitle() ?>
4 | = __('Created at') ?>: = $block->formatDate($block->getCurrentRecord()->getCreatedAt(), \IntlDateFormatter::MEDIUM) ?>
5 | getCreatedFrom()): ?>
6 |
7 | = __('Created from') ?>: = $block->getCreatedFrom() ?>
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/view/adminhtml/web/js/form/edit/formFields.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright © Alekseon sp. z o.o.
3 | * http://www.alekseon.com/
4 | */
5 | define([
6 | 'jquery',
7 | 'Magento_Ui/js/modal/confirm',
8 | 'mage/translate'
9 | ], function ($, confirm, $t) {
10 | 'use strict';
11 |
12 | var formFields = {
13 |
14 | init: function (config) {
15 | this.newFieldsCounter = 0;
16 | this.newFieldTemplate = $('#' + config.newFieldTemplateId)[0];
17 |
18 | this.formContainer = $('#' + config.formContainerId + ' .form-inline')[0];
19 | this.newFieldButton = $('#' + config.newFieldButtonId);
20 | this.formRemovedFieldsInputId = $('#' + config.formRemovedFieldsInputId);
21 | this.hideNewFieldTemplate();
22 | this.addNewFieldButtonEvent();
23 | this.addFieldsEvents();
24 | },
25 |
26 | addNewField: function () {
27 | this.newFieldsCounter ++;
28 | var self = this;
29 | var newField = this.newFieldTemplate.clone(true);
30 |
31 | $(newField).find("input, select, textarea").each(function() {
32 | var fieldCode = $(this).data('fieldcode');
33 | $(this).attr("name", "new_fields[" + self.newFieldsCounter + "][" + fieldCode + "]");
34 | });
35 |
36 | var removeButton = $(newField).find('.delete-field-button')[0];
37 | this.addRemoveFieldEvent(removeButton);
38 |
39 | var changeTabButton = $(newField).find('.form-field-change-tab-button')[0];
40 | this.addChangeTabButtonEvent(changeTabButton);
41 |
42 | this.formContainer.appendChild(newField);
43 |
44 | $(document).trigger('form-new-field', [newField]);
45 | $(newField).slideDown();
46 | },
47 |
48 | addNewFieldButtonEvent: function () {
49 | this.newFieldButton.click(function () {
50 | formFields.addNewField();
51 | return false;
52 | });
53 | },
54 |
55 | hideNewFieldTemplate: function () {
56 | this.newFieldTemplate.hide();
57 | },
58 |
59 | addFieldsEvents: function () {
60 | var self = this;
61 | $(this.formContainer).find('.delete-field-button').each(function() {
62 | self.addRemoveFieldEvent(this);
63 | });
64 | $(this.formContainer).find('.form-field-change-tab-button').each(function() {
65 | self.addChangeTabButtonEvent(this);
66 | });
67 | },
68 |
69 | addChangeTabButtonEvent: function (changeTabButton) {
70 | $(changeTabButton).click(function () {
71 | $(document).trigger('form-field-change-tab-click', [this]);
72 | return false;
73 | });
74 | },
75 |
76 | addRemoveFieldEvent: function (removeButton) {
77 | var self = this;
78 | $(removeButton).click(function () {
79 | confirm({
80 | content: $t('Are You Sure?'),
81 | actions: {
82 | confirm: function () {
83 | var fieldsetWrapper = $(removeButton).closest('.fieldset-wrapper');
84 | var fieldsetId = self.getFieldsetId($(removeButton));
85 | if (fieldsetId !== 'new_field') {
86 | var removedIds = [];
87 | var removedIdsVal = $(self.formRemovedFieldsInputId).val();
88 | if (removedIdsVal) {
89 | removedIds = removedIdsVal.split(',');
90 | }
91 | removedIds.push(fieldsetId);
92 | $(self.formRemovedFieldsInputId).val(removedIds.join(','));
93 | }
94 |
95 | fieldsetWrapper.slideUp("slow", function () {
96 | this.remove();
97 | });
98 | }
99 | }
100 | });
101 | return false;
102 | });
103 | },
104 |
105 | getFieldsetId: function (fieldsetChildElement) {
106 | var fieldsetWrapper = fieldsetChildElement.closest('.fieldset-wrapper');
107 | var fieldsetId = $(fieldsetWrapper.find('fieldset')[0]).attr('id').substr('form_field_'.length);
108 | return fieldsetId;
109 | }
110 | };
111 |
112 | return function (config) {
113 | $(document).ready(function () {
114 | formFields.init(config);
115 | });
116 | };
117 | });
118 |
--------------------------------------------------------------------------------
/view/adminhtml/web/js/form/edit/formTabs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright © Alekseon sp. z o.o.
3 | * http://www.alekseon.com/
4 | */
5 | define([
6 | 'jquery',
7 | 'Magento_Ui/js/modal/confirm',
8 | 'mage/translate'
9 | ], function ($, confirm, $t) {
10 | 'use strict';
11 |
12 | var formTabs = {
13 |
14 | init: function (config) {
15 | this.formContainer = $('#' + config.formContainerId);
16 | this.tabs = {};
17 | this.newTabLabel = config.newTabLabel;
18 | this.activeTab = config.activeTab;
19 | this.lastTabNumber = config.lastTabNumber;
20 | this.initTabs(config.formTabs);
21 | this.onTabChange();
22 | this.initChangeTabButtons();
23 | },
24 |
25 | initChangeTabButtons: function()
26 | {
27 | var self = this;
28 | $(document).on(
29 | "form-field-change-tab-click",
30 | function(e, clickedButton) {
31 | self.onChangeTabButtonClick(clickedButton);
32 | }
33 | );
34 |
35 | $(window).click(function(e) {
36 | if (!$(e.target).hasClass('change-tab-select')) {
37 | self.hideChangeButtonSelects();
38 | }
39 | });
40 | },
41 |
42 | onChangeTabButtonClick: function(clickedButton)
43 | {
44 | var self = this;
45 | this.hideChangeButtonSelects();
46 | var select = $(clickedButton).parent().find('.change-tab-select');
47 | select.empty();
48 | $.each(this.tabs, function () {
49 | select.append(new Option(this.label, this.id));
50 | });
51 | select.val(this.activeTab);
52 | select.on('change', function() {
53 | var fieldset = select.closest('.fieldset');
54 | self.setFieldTab(fieldset, this.value);
55 | self.onTabChange();
56 | });
57 | select.show();
58 | $(clickedButton).parent().find('.form-field-change-tab-button').hide();
59 | },
60 |
61 | setFieldTab: function(fieldset, tabId)
62 | {
63 | $(fieldset.find('.group-code')[0]).val(tabId);
64 | fieldset.removeClass('form_tab_' + this.activeTab);
65 | fieldset.addClass('form_tab_' + tabId);
66 | },
67 |
68 | hideChangeButtonSelects: function()
69 | {
70 | $('.form-field-change-tab-button').show();
71 | $('.change-tab-select').hide();
72 | },
73 |
74 | initTabs: function (tabsJson) {
75 | var self = this;
76 | $.each(tabsJson, function() {
77 | if (!self.firstTabId) {
78 | self.firstTabId = this.code;
79 | }
80 | self.addTab(this.label, this.code);
81 | });
82 | this.addNewTabClickEvent();
83 | $(document).on(
84 | "form-new-field",
85 | function(e, newField) {
86 | var fieldset = $(newField).find('.fieldset')[0];
87 | self.setFieldTab($(fieldset), self.activeTab);
88 | }
89 | );
90 | },
91 |
92 | onTabChange: function () {
93 | var self = this;
94 | $(this.formContainer).find('.fieldset' ).each(function() {
95 | $(this).closest('.fieldset-wrapper').hide();
96 | });
97 |
98 | $(this.formContainer).find('.fieldset.' + 'form_tab_' + this.activeTab).each(function() {
99 | $(this).closest('.fieldset-wrapper').show();
100 | });
101 |
102 | $.each(self.tabs, function() {
103 | this.tab.removeClass('ui-state-active');
104 | });
105 |
106 | var tab = self.tabs[self.activeTab];
107 | tab.tab.addClass('ui-state-active');
108 |
109 | this.hideChangeButtonSelects();
110 | $('.tab-settings').hide();
111 | $('#tab-settings-' + this.activeTab).show();
112 | },
113 |
114 | addNewTabClickEvent: function () {
115 | var self = this;
116 | var addNewButton = $('#add_tab_button');
117 | addNewButton.click(function () {
118 | self.lastTabNumber ++;
119 | var newTab = self.addTab(self.newTabLabel);
120 | self.activeTab = newTab.attr("data-id");
121 | self.onTabChange();
122 | return false;
123 | });
124 | addNewButton.show();
125 | },
126 |
127 | addOnClickTabEvent: function (tab) {
128 | var self = this;
129 | tab.click(function () {
130 | self.activeTab = $(this).parent().attr("data-id");
131 | self.onTabChange();
132 | return false;
133 | });
134 | },
135 |
136 | addTab: function (label, tabId=null) {
137 | var self = this;
138 | var tabTemplate = $('#tab-template')[0];
139 | var newTab = tabTemplate.clone(true);
140 | $(tabTemplate).parent()[0].insertBefore(newTab, $('#add_tab_button')[0]);
141 | newTab = $(newTab);
142 | if (!tabId) {
143 | tabId = this.lastTabNumber;
144 | }
145 | newTab.attr("data-id", tabId);
146 | newTab.removeAttr('id');
147 | var tabLink = newTab.find(".tab-item-link");
148 | tabLink.title = label;
149 | tabLink.text(label);
150 | this.addOnClickTabEvent(tabLink);
151 | var newSettings = $('#tab-settings-template')[0].clone(true);
152 | newSettings.id = "tab-settings-" + tabId;
153 | var labelInput = $(newSettings).find(".label-input");
154 | labelInput.val(label);
155 | labelInput.attr('name', 'form_tabs[' + tabId + '][label]');
156 | $("#tabs-settings-container")[0].appendChild(newSettings);
157 |
158 | if (tabId != this.firstTabId) {
159 | var removeTabButton = $(newSettings).find('.form-remove-tab')[0];
160 | $(removeTabButton).parent().show();
161 | $(removeTabButton).click(function() {
162 | self.removeTab(tabId);
163 | return false;
164 | });
165 | }
166 |
167 | this.tabs[newTab.attr("data-id")] = {
168 | "tab": newTab,
169 | "link": tabLink,
170 | "settings": newSettings,
171 | "label": label,
172 | "id": tabId
173 | };
174 | newTab.show();
175 |
176 | return newTab;
177 | },
178 |
179 | removeTab: function(tabId) {
180 | var self = this;
181 | var selectTab = $('