diff --git a/flextype/core/Entries.php b/flextype/core/Entries.php
index 25b952f9..073dbeb5 100755
--- a/flextype/core/Entries.php
+++ b/flextype/core/Entries.php
@@ -101,7 +101,6 @@ class Entries
{
// If requested entry file founded then process it
if ($_entry = $this->read($id)) {
-
// Create unique entry cache_id
// Entry Cache ID = entry + entry file + entry file time stamp
if ($timestamp = Filesystem::getTimestamp($_entry['file_path'])) {
@@ -466,7 +465,7 @@ class Entries
/**
* Read entry
*
- * @param string $id Entry ID
+ * @param string $id Entry ID
* @param bool $raw Return raw or decoded content
*
* @return bool|array Array of file path, decoded file data and file parser,
diff --git a/flextype/core/Forms.php b/flextype/core/Forms.php
new file mode 100644
index 00000000..338a5b11
--- /dev/null
+++ b/flextype/core/Forms.php
@@ -0,0 +1,371 @@
+ 'col-1',
+ '2/12' => 'col-2',
+ '3/12' => 'col-3',
+ '4/12' => 'col-4',
+ '5/12' => 'col-5',
+ '6/12' => 'col-6',
+ '7/12' => 'col-7',
+ '8/12' => 'col-8',
+ '9/12' => 'col-9',
+ '10/12' => 'col-19',
+ '12/12' => 'col-11',
+ '12' => 'col-12',
+ ];
+
+ /**
+ * 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
+ * @param Response $response PSR7 response
+ *
+ * @return string Returns form based on fieldsets
+ *
+ * @access public
+ */
+ public function render(array $fieldset, array $values = [], Request $request, Response $response) : string
+ {
+ $form = Form::open(null, ['id' => 'form']);
+ $form .= $this->_csrfHiddenField();
+ $form .= $this->_actionHiddenField();
+
+ if (count($fieldset['sections']) > 0) {
+ $form .= '
';
+
+ foreach ($fieldset['sections'] as $key => $section) {
+ $form .= '
';
+ $form .= '
';
+
+ foreach ($section['fields'] as $element => $property) {
+ // Create attributes
+ $property['attributes'] = Arr::keyExists($property, 'attributes') ? $property['attributes'] : [];
+
+ // Create attribute class
+ $property['attributes']['class'] = Arr::keyExists($property, 'attributes.class') ? $this->field_class . ' ' . $property['attributes']['class'] : $this->field_class;
+
+ // Create attribute size
+ $property['size'] = Arr::keyExists($property, 'size') ? $this->sizes[$property['size']] : $this->sizes['12'];
+
+ // Create attribute value
+ $property['value'] = Arr::keyExists($property, 'value') ? $property['value'] : '';
+
+ // Create attribute value
+ $property['label'] = Arr::keyExists($property, 'label') ? $property['label'] : true;
+
+ // Set element name
+ $element_name = $this->getElementName($element);
+
+ // Set element value
+ $form_value = Arr::keyExists($values, $element) ? Arr::get($values, $element) : $property['value'];
+
+ // Set form element
+ $form_element = '';
+
+ // Form elements
+ switch ($property['type']) {
+ // Simple text-input, for multi-line fields.
+ case 'textarea':
+ $form_element = $this->textareaField($element_name, $form_value, $property);
+ break;
+ // The hidden field is like the text field, except it's hidden from the content editor.
+ case 'hidden':
+ $form_element = $this->hiddenField($element_name, $form_value, $property);
+ break;
+ // A WYSIWYG HTML field.
+ case 'html':
+ $form_element = $this->htmlField($element_name, $form_value, $property);
+ break;
+ // Selectbox field
+ case 'select':
+ $form_element = $this->selectField($element_name, $property['options'], $form_value, $property);
+ break;
+ // Template select field for selecting entry template
+ case 'template_select':
+ $form_element = $this->templateSelectField($element_name, [], $form_value, $property);
+ break;
+ // Visibility select field for selecting entry visibility state
+ case 'visibility_select':
+ $form_element = $this->visibilitySelectField($element_name, ['draft' => __('admin_entries_draft'), 'visible' => __('admin_entries_visible'), 'hidden' => __('admin_entries_hidden')], (! empty($form_value) ? $form_value : 'visible'), $property);
+ break;
+ // Simple text-input, for single-line fields.
+ default:
+ $form_element = $this->textField($element_name, $form_value, $property);
+ break;
+ }
+
+ if ($property['label'] === true) {
+ $form_label = Form::label($element, __($property['title']));
+ } else {
+ $form_label = '';
+ }
+
+ $form .= '
';
+ $form .= $form_label . $form_element;
+ $form .= '
';
+ }
+ $form .= '
';
+ $form .= '
';
+ }
+ $form .= '
';
+ }
+
+ $form .= Form::close();
+
+ return $form;
+ }
+
+ /**
+ * 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) {
+ $element_name = $element;
+ } else {
+ $element_name = str_replace('.', '][', "$element") . ']';
+ }
+
+ $pos = strpos($element_name, ']');
+
+ if ($pos !== false) {
+ $element_name = substr_replace($element_name, '', $pos, strlen(']'));
+ }
+
+ return $element_name;
+ }
+
+ /**
+ * Template select field
+ *
+ * @param string $name Field name
+ * @param array $options Field options
+ * @param string $value Field value
+ * @param array $property Field property
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function templateSelectField($name, $options, $value, $property)
+ {
+ $_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'];
+ }
+ }
+
+ return Form::select($name, $options, $value, $property['attributes']);
+ }
+
+ /**
+ * Select field
+ *
+ * @param string $name Field name
+ * @param array $options Field options
+ * @param string $value Field value
+ * @param array $property Field property
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function selectField($name, $options, $value, $property)
+ {
+ return Form::select($name, $options, $value, $property['attributes']);
+ }
+
+ /**
+ * Html field
+ *
+ * @param string $name Field name
+ * @param string $value Field value
+ * @param array $property Field property
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function htmlField($name, $value, $property)
+ {
+ $property['attributes']['class'] .= ' js-html-editor';
+
+ return Form::textarea($name, $value, $property['attributes']);
+ }
+
+
+ /**
+ * Hidden field
+ *
+ * @param string $name Field name
+ * @param string $value Field value
+ * @param array $property Field property
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function hiddenField($name, $value, $property)
+ {
+ return Form::hidden($name, $value, $property['attributes']);
+ }
+
+ /**
+ * Textarea field
+ *
+ * @param string $name Field name
+ * @param string $value Field value
+ * @param array $property Field property
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function textareaField($name, $value, $property)
+ {
+ return Form::textarea($name, $value, $property['attributes']);
+ }
+
+ /**
+ * Visibility field
+ *
+ * @param string $name Field name
+ * @param array $options Field options
+ * @param string $value Field value
+ * @param array $property Field property
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function visibilitySelectField($name, $options, $value, $property)
+ {
+ return Form::select($name, $options, $value, $property['attributes']);
+ }
+
+ /**
+ * Text field
+ *
+ * @param string $name Field name
+ * @param string $value Field value
+ * @param array $property Field property
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function textField($name, $value, $property)
+ {
+ return Form::input($name, $value, $property['attributes']);
+ }
+
+ /**
+ * _csrfHiddenField
+ *
+ * @return string Returns field
+ *
+ * @access protected
+ */
+ protected function _csrfHiddenField()
+ {
+ $field = '';
- foreach ($fieldset['sections'] as $key => $section) {
- $form .= '
';
- $form .= '
';
- foreach ($section['fields'] as $element => $property) {
- // Create attributes
- $property['attributes'] = Arr::keyExists($property, 'attributes') ? $property['attributes'] : [];
- // Create attribute class
- $property['attributes']['class'] = Arr::keyExists($property, 'attributes.class') ? 'form-control ' . $property['attributes']['class'] : 'form-control';
- // Create attribute size
- $property['size'] = Arr::keyExists($property, 'size') ? $property['size'] : 'col-12';
- // Create attribute value
- $property['value'] = Arr::keyExists($property, 'value') ? $property['value'] : '';
- $pos = strpos($element, '.');
- if ($pos === false) {
- $form_element_name = $element;
- } else {
- $form_element_name = str_replace(".", "][", "$element") . ']';
- }
- $pos = strpos($form_element_name, ']');
- if ($pos !== false) {
- $form_element_name = substr_replace($form_element_name, '', $pos, strlen(']'));
- }
- // Form value
- $form_value = Arr::keyExists($values, $element) ? Arr::get($values, $element) : $property['value'];
- // Form label
- $form_label = Form::label($element, __($property['title']));
- // Form elements
- switch ($property['type']) {
- // Simple text-input, for multi-line fields.
- case 'textarea':
- $form_element = Form::textarea($element, $form_value, $property['attributes']);
- break;
- // The hidden field is like the text field, except it's hidden from the content editor.
- case 'hidden':
- $form_element = Form::hidden($element, $form_value);
- break;
- // A WYSIWYG HTML field.
- case 'html':
- $property['attributes']['class'] .= ' js-html-editor';
- $form_element = Form::textarea($element, $form_value, $property['attributes']);
- break;
- // Selectbox field
- case 'select':
- $form_element = Form::select($form_element_name, $property['options'], $form_value, $property['attributes']);
- break;
- // Template select field for selecting entry template
- case 'template_select':
- if ($this->registry->has('settings.theme')) {
-
- $_templates_list = $this->themes->getTemplates($this->registry->get('settings.theme'));
-
- $templates_list = [];
-
- if (count($_templates_list) > 0) {
- foreach ($_templates_list as $template) {
- if ($template['type'] == 'file' && $template['extension'] == 'html') {
- $templates_list[$template['basename']] = $template['basename'];
- }
- }
- }
-
- $form_element = Form::select($form_element_name, $templates_list, $form_value, $property['attributes']);
- }
- break;
- // Visibility select field for selecting entry visibility state
- case 'visibility_select':
- $form_element = Form::select($form_element_name, ['draft' => __('admin_entries_draft'), 'visible' => __('admin_entries_visible'), 'hidden' => __('admin_entries_hidden')], (!empty($form_value) ? $form_value : 'visible'), $property['attributes']);
- break;
- // Media select field
- case 'media_select':
- $form_element = Form::select($form_element_name, $this->getMediaList($request->getQueryParams()['id'], false), $form_value, $property['attributes']);
- break;
- // Simple text-input, for single-line fields.
- default:
- $form_element = Form::input($form_element_name, $form_value, $property['attributes']);
- break;
- }
- // Render form elments with labels
- if ($property['type'] == 'hidden') {
- $form .= $form_element;
- } else {
- $form .= '
';
- $form .= $form_label . $form_element;
- $form .= '
';
- }
- }
- $form .= '
';
- $form .= '
';
- }
- $form .= '
';
- }
- $form .= Form::close();
- return $form;
- }
-
/**
* Edit entry
*
@@ -816,7 +697,7 @@ class EntriesController extends Controller
'parts' => $parts,
'i' => count($parts),
'last' => Arr::last($parts),
- 'form' => $this->fetchForm($fieldsets, $entry, $request),
+ 'form' => $this->forms->render($fieldsets, $entry, $request, $response),
'menu_item' => 'entries',
'links' => [
'entries' => [