From 97586d4bb7707ba47cbdb5dff853d4a626b196c8 Mon Sep 17 00:00:00 2001 From: Awilum Date: Thu, 6 Feb 2020 19:42:08 +0300 Subject: [PATCH] feat(form-plugin): add Form plugin #360 --- site/plugins/form/LICENSE.txt | 21 + site/plugins/form/README.md | 8 + .../form/app/Controllers/FormController.php | 658 ++++++++++++++++++ site/plugins/form/bootstrap.php | 40 ++ site/plugins/form/composer.json | 33 + site/plugins/form/dependencies.php | 19 + site/plugins/form/lang/en_US.yaml | 2 + site/plugins/form/lang/ru_RU.yaml | 2 + site/plugins/form/plugin.yaml | 11 + site/plugins/form/routes/web.php | 12 + site/plugins/form/settings.yaml | 1 + 11 files changed, 807 insertions(+) create mode 100755 site/plugins/form/LICENSE.txt create mode 100755 site/plugins/form/README.md create mode 100644 site/plugins/form/app/Controllers/FormController.php create mode 100644 site/plugins/form/bootstrap.php create mode 100644 site/plugins/form/composer.json create mode 100644 site/plugins/form/dependencies.php create mode 100755 site/plugins/form/lang/en_US.yaml create mode 100755 site/plugins/form/lang/ru_RU.yaml create mode 100755 site/plugins/form/plugin.yaml create mode 100644 site/plugins/form/routes/web.php create mode 100644 site/plugins/form/settings.yaml diff --git a/site/plugins/form/LICENSE.txt b/site/plugins/form/LICENSE.txt new file mode 100755 index 00000000..f628cc1e --- /dev/null +++ b/site/plugins/form/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018-2020 Sergey Romanenko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/site/plugins/form/README.md b/site/plugins/form/README.md new file mode 100755 index 00000000..b9024a96 --- /dev/null +++ b/site/plugins/form/README.md @@ -0,0 +1,8 @@ +# Form Plugin for [Flextype](http://flextype.org/) +![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square) + +Form Plugin for Flextype. + +## LICENSE +[The MIT License (MIT)](https://github.com/flextype/flextype/blob/master/LICENSE.txt) +Copyright (c) 2018-2020 [Sergey Romanenko](https://github.com/Awilum) diff --git a/site/plugins/form/app/Controllers/FormController.php b/site/plugins/form/app/Controllers/FormController.php new file mode 100644 index 00000000..18979997 --- /dev/null +++ b/site/plugins/form/app/Controllers/FormController.php @@ -0,0 +1,658 @@ + 'col w-1/12', + '2/12' => 'col w-2/12', + '3/12' => 'col w-3/12', + '4/12' => 'col w-4/12', + '5/12' => 'col w-5/12', + '6/12' => 'col w-6/12', + '7/12' => 'col w-7/12', + '8/12' => 'col w-8/12', + '9/12' => 'col w-9/12', + '10/12' => 'col w-10/12', + '12/12' => 'col w-full', + '12' => 'col w-full', + ]; + + /** + * Field class + * + * @var string + * @access private + */ + private $field_class = 'form-control'; + + /** + * Constructor + * + * @access public + */ + public function __construct($flextype) + { + $this->flextype = $flextype; + } + + /** + * Render form + * + * @param array $fieldset Fieldset + * @param array $values Fieldset values + * @param Request $request PSR7 request + * + * @return string Returns form based on fieldsets + * + * @access public + */ + public function render(array $fieldset, array $values = [], Request $request) : string + { + $form = Form::open(null, ['id' => 'form']); + $form .= $this->_csrfHiddenField(); + $form .= $this->_actionHiddenField(); + + // Go through all sections + if (count($fieldset['sections']) > 0) { + + $form .= '
'; + + // Go through all sections and create nav tabs + foreach ($fieldset['sections'] as $key => $section) { + $form .= '
'; + $form .= '
'; + + foreach ($section['fields'] as $element => $properties) { + // Set empty form field element + $form_field = ''; + + // Set element name + $field_name = $this->getElementName($element); + + // Set element id + $field_id = $this->getElementID($element); + + // Set element default value + $field_value = $this->getElementValue($element, $values, $properties); + + // Seletct field type + switch ($properties['type']) { + case 'textarea': + $form_field = $this->textareaField($field_id, $field_name, $field_value, $properties); + break; + case 'hidden': + $form_field = $this->hiddenField($field_id, $field_name, $field_value, $properties); + break; + case 'html': + $form_field = $this->htmlField($field_id, $field_name, $field_value, $properties); + break; + case 'select': + $form_field = $this->selectField($field_id, $field_name, $field_value, $properties); + break; + case 'template_select': + $form_field = $this->templateSelectField($field_id, $field_name, $field_value, $properties); + break; + case 'visibility_select': + $form_field = $this->visibilitySelectField($field_id, $field_name, $field_value, $properties); + break; + case 'heading': + $form_field = $this->headingField($field_id, $properties); + break; + case 'routable_select': + $form_field = $this->routableSelectField($field_id, $field_name, $field_value, $properties); + break; + case 'tags': + $form_field = $this->tagsField($field_id, $field_name, $field_value, $properties); + break; + case 'datetimepicker': + $form_field = $this->dateField($field_id, $field_name, $field_value, $properties); + break; + case 'media_select': + $form_field = $this->mediaSelectField($field_id, $field_name, $field_value, $properties, $request); + break; + default: + $form_field = $this->textField($field_id, $field_name, $field_value, $properties); + break; + } + + $form .= $form_field; + } + $form .= '
'; + $form .= '
'; + } + + + $form .= ''; + + $form .= '
'; + } + + $form .= Form::close(); + + return $form; + } + + /** + * Get element value + * + * @param string $element Form Element + * @param array $values Form Values + * @param array $properties Field properties + * + * @return mixed Returns form element value + * + * @access protected + */ + protected function getElementValue(string $element, array $values, array $properties) + { + if (Arr::keyExists($values, $element)) { + $field_value = Arr::get($values, $element); + } elseif(Arr::keyExists($properties, 'default')) { + $field_value = $properties['default']; + } else { + $field_value = ''; + } + + return $field_value; + } + + /** + * Get element name + * + * @param string $element Element + * + * @return string Returns form element name + * + * @access protected + */ + protected function getElementName(string $element) : string + { + $pos = strpos($element, '.'); + + if ($pos === false) { + $field_name = $element; + } else { + $field_name = str_replace('.', '][', "$element") . ']'; + } + + $pos = strpos($field_name, ']'); + + if ($pos !== false) { + $field_name = substr_replace($field_name, '', $pos, strlen(']')); + } + + return $field_name; + } + + /** + * Get element id + * + * @param string $element Element + * + * @return string Returns form element id + * + * @access protected + */ + protected function getElementID(string $element) : string + { + $pos = strpos($element, '.'); + + if ($pos === false) { + $field_name = $element; + } else { + $field_name = str_replace('.', '_', "$element"); + } + + return $field_name; + } + + /** + * Media select field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * @param Request $request PSR7 request + * + * @return string Returns field + * + * @access protected + */ + protected function mediaSelectField(string $field_id, string $field_name, $field_value, array $properties, Request $request) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + $options = $this->flextype->EntriesController->getMediaList($request->getQueryParams()['id'], false); + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class . ' js-select'; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::select($field_name, $options, $field_value, $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Template select field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function templateSelectField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class . ' js-select'; + + $_templates_list = $this->flextype['themes']->getTemplates($this->flextype['registry']->get('settings.theme')); + + $options = []; + + if (count($_templates_list) > 0) { + foreach ($_templates_list as $template) { + if ($template['type'] !== 'file' || $template['extension'] !== 'html') { + continue; + } + + $options[$template['basename']] = $template['basename']; + } + } + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::select($field_name, $options, $field_value, $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Routable select field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function routableSelectField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + $options = [true => __('admin_yes'), false => __('admin_no')]; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class . ' js-select'; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::select($field_name, $options, (is_string($field_value) ? true : ($field_value ? true : false)), $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Select field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function selectField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + $options = isset($properties['options']) ? $properties['options'] : []; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class . ' js-select'; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::select($field_name, $options, $field_value, $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Heading field + * + * @param string $field_id Field ID + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function headingField(string $field_id, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $h = isset($properties['h']) ? $properties['h'] : 3; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] . 'text-3xl border-b border-black' : 'text-3xl border-b border-black'; + + $field = '
'; + $field .= Html::heading(__($title), $h, $attributes); + $field .= '
'; + + return $field; + } + + /** + * Html field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function htmlField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class; + $attributes['class'] .= ' js-html-editor'; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::textarea($field_name, $field_value, $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Hidden field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function hiddenField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + + return Form::hidden($field_name, $field_value, $attributes); + } + + /** + * Textarea field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param string $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function textareaField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::textarea($field_name, $field_value, $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Visibility field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function visibilitySelectField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + $options = ['draft' => __('admin_entries_draft'), 'visible' => __('admin_entries_visible'), 'hidden' => __('admin_entries_hidden')]; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class . ' js-select'; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::select($field_name, $options, (! empty($field_value) ? $field_value : 'visible'), $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Text field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function textField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= Form::input($field_name, $field_value, $attributes); + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Tags field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * + * @return string Returns field + * + * @access protected + */ + protected function tagsField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + + $attributes = isset($properties['attributes']) ? $properties['attributes'] : []; + $attributes['id'] = isset($attributes['id']) ? $attributes['id'] : $field_id; + $attributes['class'] = isset($attributes['class']) ? $attributes['class'] : $this->field_class; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= ''; + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + + return $field; + } + + /** + * Date field + * + * @param string $field_id Field ID + * @param string $field_name Field name + * @param mixed $field_value Field value + * @param array $properties Field properties + * + * @return string Returns field + * + * @access protected + */ + protected function dateField(string $field_id, string $field_name, $field_value, array $properties) : string + { + $title = isset($properties['title']) ? $properties['title'] : ''; + $size = isset($properties['size']) ? $this->sizes[$properties['size']] : $this->sizes['12']; + $help = isset($properties['help']) ? $properties['help'] : ''; + + $field = '
'; + $field .= ($title ? Form::label($field_id, __($title)) : ''); + $field .= '
'; + $field .= ' +
+
+
'; + $field .= ($help ? '' . __($help) . '' : ''); + $field .= '
'; + $field .= '
'; + + return $field; + } + + /** + * _csrfHiddenField + * + * @return string Returns field + * + * @access protected + */ + protected function _csrfHiddenField() : string + { + $field = ''; + $field .= ''; + + return $field; + } + + /** + * _actionHiddenField + * + * @return string Returns field + * + * @access protected + */ + protected function _actionHiddenField() : string + { + return Form::hidden('action', 'save-form'); + } +} diff --git a/site/plugins/form/bootstrap.php b/site/plugins/form/bootstrap.php new file mode 100644 index 00000000..26501e6b --- /dev/null +++ b/site/plugins/form/bootstrap.php @@ -0,0 +1,40 @@ +composer install'); + +/** + * Register The Auto Loader + * + * Composer provides a convenient, automatically generated class loader for + * our application. We just need to utilize it! We'll simply require it + * into the script here so that we don't have to worry about manual + * loading any of our classes later on. It feels nice to relax. + * Register The Auto Loader + */ +$site_loader = require_once $site_autoload; + +/** + * Include web routes + */ +include_once 'routes/web.php'; + +/** + * Include dependencies + */ +include_once 'dependencies.php'; diff --git a/site/plugins/form/composer.json b/site/plugins/form/composer.json new file mode 100644 index 00000000..1ea3f327 --- /dev/null +++ b/site/plugins/form/composer.json @@ -0,0 +1,33 @@ +{ + "name": "flextype-plugins/form", + "type": "project", + "description": "Form plugin for Flextype", + "keywords": ["form", "plugin", "flextype", "php", "html"], + "homepage": "https://github.com/flextype", + "license": "MIT", + "authors": [ + { + "name": "Sergey Romanenko", + "email": "hello@romanenko.digital", + "homepage": "http://digital.flextype.org" + } + ], + "support": { + "issues": "https://github.com/flextype/issues" + }, + "require": { + "php": ">=7.2.0" + }, + "config": { + "apcu-autoloader": true, + "optimize-autoloader": true, + "platform": { + "php": "7.2.0" + } + }, + "autoload": { + "classmap": [ + "app" + ] + } +} diff --git a/site/plugins/form/dependencies.php b/site/plugins/form/dependencies.php new file mode 100644 index 00000000..f6ccdb9d --- /dev/null +++ b/site/plugins/form/dependencies.php @@ -0,0 +1,19 @@ +