From 8417999e042d93ecf4fffac5791bb2424f543b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Kh=C3=BCny?= Date: Tue, 6 Sep 2016 16:52:08 +0200 Subject: [PATCH 01/39] Fixed MailChimp-Key parameter in FormController (#85) * Fixed MailChimp-Key parameter in FormController * Fixed Changelog --- CHANGELOG.md | 4 ++++ Controller/FormController.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 827075c..02fe9b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## dev-develop + + - BUGFIX #85 Fixed MailChimp-Key parameter in FormController + ## 1.0.0-RC4 - BUGFIX #80 Fixed getCustomerDeactivateMails and getNotifyDeactivateMails Method diff --git a/Controller/FormController.php b/Controller/FormController.php index 97d61e5..74b8aae 100644 --- a/Controller/FormController.php +++ b/Controller/FormController.php @@ -214,7 +214,7 @@ public function cgetTemplateAction(Request $request) public function getMailChimpLists() { $lists = []; - $apiKey = $this->getParameter('mailchimp_api_key'); + $apiKey = $this->getParameter('l91_sulu_form.mailchimp_api_key'); // if mailchimp class doesn't exist or no key is set return empty list if (!class_exists('DrewM\MailChimp\MailChimp') || !$apiKey) { From a2a4121a9e0e4656c2b5c299438b49e62655c7d7 Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 15 Sep 2016 15:03:30 +0200 Subject: [PATCH 02/39] Added last flag for grid and update documentation and backend clean up (#92) --- CHANGELOG.md | 2 + Controller/FormController.php | 11 +- Form/Type/DynamicFormType.php | 51 ++++ README.md | 20 +- Resources/doc/dynamic.md | 66 ++++- .../public/js/components/forms/list/main.js | 4 +- .../forms/fields/default-field.html.twig | 244 +++++++++++------- .../forms/fields/types/freetext.html.twig | 2 + .../forms/fields/types/headline.html.twig | 7 +- .../views/forms/fields/types/spacer.html.twig | 20 +- Resources/views/forms/template.html.twig | 91 +------ 11 files changed, 302 insertions(+), 216 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02fe9b9..f4474be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## dev-develop + - FEATURE #92 Clean up the backend view + - FEATURE #92 Added last flag for grid and update documentation - BUGFIX #85 Fixed MailChimp-Key parameter in FormController ## 1.0.0-RC4 diff --git a/Controller/FormController.php b/Controller/FormController.php index 74b8aae..4adbb01 100644 --- a/Controller/FormController.php +++ b/Controller/FormController.php @@ -14,7 +14,6 @@ use Sulu\Component\Rest\ListBuilder\Doctrine\FieldDescriptor\DoctrineFieldDescriptor; use Sulu\Component\Rest\ListBuilder\Doctrine\FieldDescriptor\DoctrineJoinDescriptor; use Sulu\Component\Rest\ListBuilder\ListRepresentation; -use Sulu\Component\Rest\ListBuilder\ListRestHelper; use Sulu\Component\Rest\RestHelperInterface; use Sulu\Component\Security\SecuredControllerInterface; use Symfony\Component\HttpFoundation\Request; @@ -58,8 +57,8 @@ public function getFieldDescriptors($locale, $filters) Form::class, 'public.id', [], - false, - true + true, + false ); $fieldDescriptors['title'] = new DoctrineCaseFieldDescriptor( @@ -86,7 +85,9 @@ public function getFieldDescriptors($locale, $filters) ), ] ), - 'public.title' + 'public.title', + false, + true ); $fieldDescriptors['changed'] = new DoctrineCaseFieldDescriptor( @@ -424,7 +425,7 @@ protected function getFilters(Request $request) { $filters = $request->query->all(); - $listRestHelper = new ListRestHelper($request); + $listRestHelper = $this->get('sulu_core.list_rest_helper'); unset($filters['page']); unset($filters['limit']); diff --git a/Form/Type/DynamicFormType.php b/Form/Type/DynamicFormType.php index 130299d..7bd0824 100644 --- a/Form/Type/DynamicFormType.php +++ b/Form/Type/DynamicFormType.php @@ -78,6 +78,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) throw new \Exception('The form with the ID "' . $this->formEntity->getId() . '" does not exist for the locale "' . $this->locale . '"!'); } + $currentWidthValue = 0; + foreach ($this->formEntity->getFields() as $field) { $translation = $field->getTranslation($this->locale); $name = $field->getKey(); @@ -100,9 +102,12 @@ public function buildForm(FormBuilderInterface $builder, array $options) $width = $field->getWidth(); } + $lastWidth = $this->getLastWidth($currentWidthValue, $width); + $options['label'] = $title; $options['required'] = $field->getRequired(); $options['attr']['width'] = $width; + $options['attr']['lastWidth'] = $lastWidth; $options['attr']['placeholder'] = $placeholder; // required @@ -358,4 +363,50 @@ public function getTranslation() { return $this->formEntity->getTranslation($this->locale, false, true); } + + /** + * @param int $currentWidthValue + * @param string $width + * + * @return bool + */ + private function getLastWidth(&$currentWidthValue, $width) + { + switch ($width) { + case 'one-sixth': + $itemWidth = 2; + break; + case 'five-sixths': + $itemWidth = 10; + break; + case 'one-quarter': + $itemWidth = 3; + break; + case 'three-quarters': + $itemWidth = 9; + break; + case 'one-third': + $itemWidth = 4; + break; + case 'two-thirds': + $itemWidth = 8; + break; + case 'half': + $itemWidth = 6; + break; + case 'full': + $itemWidth = 12; + break; + default: + $itemWidth = 12; + } + + $currentWidthValue += $itemWidth; + + if ($currentWidthValue % 12 == 0) { + return true; + } + + return false; + } } diff --git a/README.md b/README.md index 7a7940e..04a2f73 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The `mail` dispatching is handled by the bundle. Use composer to install this Bundle: -``` json +```json { "require": { "l91/sulu-form-bundle": "1.0.*" @@ -35,15 +35,9 @@ Add to AbstractKernel (app/AbstractKernel.php) new L91\Sulu\Bundle\FormBundle\L91SuluFormBundle(), ``` -Execute following command to update your database - -```bash -app/console doctrine:schema:update --force -``` - ## Config -add the following config to `app/config/config.yml` +Add the following config to `app/config/config.yml` ```yml framework: @@ -55,9 +49,17 @@ l91_sulu_form: to: %parameter_recommended_for_to% ``` +## Create Database + +Execute following command to update your database + +```bash +app/console doctrine:schema:update --force +``` + ## Routing -add the following lines to `app/config/admin/routing.yml` +Add the following lines to `app/config/admin/routing.yml` ``` xml l91_sulu_form_api: diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index 91b47d9..b13d6c7 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -33,8 +33,8 @@ https://github.com/symfony/symfony/blob/v2.7.0/src/Symfony/Bridge/Twig/Resources {% if app.request.get('send') != 'true' %} {# FORM THEME #} - {% form_theme form 'ClientWebsiteBundle:forms:theme.html.twig' %} - {{ form(form) }} + {% form_theme content.form 'ClientWebsiteBundle:forms:theme.html.twig' %} + {{ form(content.form) }} {% else %} {{ view.form.entity.successText|raw }} {% endif %} @@ -45,18 +45,27 @@ https://github.com/symfony/symfony/blob/v2.7.0/src/Symfony/Bridge/Twig/Resources ## Theme ```twig -+{%- block _dynamic_form__token_widget -%} -+ {% set type = type|default('hidden') %} -+ -+{% endblock %} +{%- block _dynamic_form__token_widget -%} + {% set type = type|default('hidden') %} + +{% endblock %} -{%- block hidden_row -%} - {% set width = attr.width|default('half')|replace({ - 'half': 'one-half', - 'full': 'one-whole' - }) %} +{%- block form_row -%} + {% set className = 'form-item form-width-' ~ attr.width|default('full') %} + + {% if attr.lastWidth|default(false) %} + {% set className = className ~ ' form-width-last' %} + {% endif %} -
+
+ {{- form_label(form) -}} + {{- form_errors(form) -}} + {{- form_widget(form) -}} +
+{%- endblock -%} + +{%- block hidden_row -%} +
{% if attr.type|default('') == 'spacer' %}
{# SPACER #} @@ -67,13 +76,14 @@ https://github.com/symfony/symfony/blob/v2.7.0/src/Symfony/Bridge/Twig/Resources
{% elseif attr.type|default('') == 'headline' %}
-

{{ attr.headline }}

+

{{ label }}

{% else %} {{ form_widget(form) }} {% endif %}
{%- endblock hidden_row -%} + ``` ## Issues @@ -87,6 +97,35 @@ Please check to following issue before using it in production: To create a dynamic form (which is selectable in the property type `form_select`) simply click on the magic icon in the Sulu backend navigation and create a new form. +## Emails + +Create the emails template in the a folder . + +form-notify.html.twig + +```twig +{% for field in formEntity.fields|default([]) %} + {% set value = field.value %} + + {# get formatted value #} + {% if value is iterable %} + {% set value = value|json_encode %} + {% elseif value.timestamp is defined %} + {% set value = value|date('d.m.Y') %} + {% endif %} + + {% if value is not empty %} + {{ field.title|default('') }}: {{ value }}
+ {% endif %} +{% endfor %} +``` + +form-notify.html.twig + +```twig +{{ formEntity.mailText|default('')|raw }} +``` + ## List Tab - Export To visualise a tab in the Sulu template, simply add following lines to your Bundles `services.xml`: @@ -98,4 +137,3 @@ To visualise a tab in the Sulu template, simply add following lines to your Bund ``` **Now a tab should be visible with a list you can export** - diff --git a/Resources/public/js/components/forms/list/main.js b/Resources/public/js/components/forms/list/main.js index e29dbc6..12c4de5 100644 --- a/Resources/public/js/components/forms/list/main.js +++ b/Resources/public/js/components/forms/list/main.js @@ -89,14 +89,14 @@ define(['l91suluform/collections/forms'], function (Collection) { // options for the content (datagrid) el: this.$find('#' + constants.listId), instanceName: this.instanceName, - url: constants.endPointUrl + '?locale=' + this.options.language + '&flat=true', + url: constants.endPointUrl + '?locale=' + this.options.language + '&flat=true&sortBy=title&sortOrder=asc', resultKey: constants.toolbarKey, searchFields: constants.toolbarSearchFields, viewOptions: { table: { icons: [ { - column: 'id', + column: 'title', icon: 'pencil', align: 'left', callback: this.edit.bind(this) diff --git a/Resources/views/forms/fields/default-field.html.twig b/Resources/views/forms/fields/default-field.html.twig index a4f5ec3..8629bcd 100644 --- a/Resources/views/forms/fields/default-field.html.twig +++ b/Resources/views/forms/fields/default-field.html.twig @@ -1,104 +1,160 @@ -{% block title_width %} -
-
- {% block title %} -
- - - -
- -
+ diff --git a/Resources/views/forms/fields/types/freetext.html.twig b/Resources/views/forms/fields/types/freetext.html.twig index 0207f25..626886d 100644 --- a/Resources/views/forms/fields/types/freetext.html.twig +++ b/Resources/views/forms/fields/types/freetext.html.twig @@ -1,5 +1,7 @@ {% extends "L91SuluFormBundle:forms:fields/default-field.html.twig" %} +{% block required %}{% endblock %} + {% block title %}
-

+

<%= translate('l91_sulu_form.website_configuration') %>

@@ -43,7 +43,7 @@
-

+

<%= translate('l91_sulu_form.email_configuration') %>

@@ -210,7 +210,7 @@
-

+

<%= translate('l91_sulu_form.form_fields') %>

@@ -261,90 +261,7 @@ data-mapper-empty-class="empty"> {% for type in types %} - + {% include 'L91SuluFormBundle:forms:fields/types/' ~ type|lower ~ '.html.twig' %} {% endfor %}
From d5edbb9ecbae399d0e0a9741027b3b9caa4835e6 Mon Sep 17 00:00:00 2001 From: comemanu Date: Fri, 16 Sep 2016 15:18:41 +0200 Subject: [PATCH 03/39] Fix inversedBy value at FormField#form property (#96) * Fix inversedBy value at FormField#form property Fixing error , invalid entity : The mappings L91\Sulu\Bundle\FormBundle\Entity\Form#fields and L91\Sulu\Bundle\FormBundle\Entity\FormField#form are inconsistent with each other. * Update CHANGELOG.md --- CHANGELOG.md | 2 +- Resources/config/doctrine/FormField.orm.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4474be..700bf1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## dev-develop - + - BUGFIX #96 Fix inversedBy value at FormField#form property - FEATURE #92 Clean up the backend view - FEATURE #92 Added last flag for grid and update documentation - BUGFIX #85 Fixed MailChimp-Key parameter in FormController diff --git a/Resources/config/doctrine/FormField.orm.xml b/Resources/config/doctrine/FormField.orm.xml index 96d4c1b..de44095 100644 --- a/Resources/config/doctrine/FormField.orm.xml +++ b/Resources/config/doctrine/FormField.orm.xml @@ -25,7 +25,7 @@ + inversed-by="fields"> From d5db5e67715540ba7b00844f8125624420a9d7b8 Mon Sep 17 00:00:00 2001 From: L91 Date: Fri, 16 Sep 2016 15:24:10 +0200 Subject: [PATCH 04/39] fixed edit symbol on list (#97) --- CHANGELOG.md | 1 + Resources/public/dist/components/forms/list/main.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 700bf1c..e7a9590 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #97 Fixed edit symbol on list - BUGFIX #96 Fix inversedBy value at FormField#form property - FEATURE #92 Clean up the backend view - FEATURE #92 Added last flag for grid and update documentation diff --git a/Resources/public/dist/components/forms/list/main.js b/Resources/public/dist/components/forms/list/main.js index 94d2bd0..6286360 100644 --- a/Resources/public/dist/components/forms/list/main.js +++ b/Resources/public/dist/components/forms/list/main.js @@ -1 +1 @@ -define(["l91suluform/collections/forms"],function(a){"use strict";var b=new a,c={toolbarId:"form-toolbar",listId:"form-list",lastClickedEventSettingsKey:"l91suluformformLastClicked",endPointUrl:b.url(),toolbarKey:"forms",toolbarSearchFields:["title"],fieldsAction:b.fieldsUrl(),eventPrefix:"l91.sulu.form.forms.",translatePrefix:"l91_sulu_form.forms."};return{view:!0,layout:{content:{width:"max"}},header:function(){return{title:c.translatePrefix+"title",noBack:!0,toolbar:{languageChanger:{preSelected:this.options.language},buttons:{add:{},deleteSelected:{}}}}},initialize:function(){this.sandbox.sulu.triggerDeleteSuccessLabel(c.translatePrefix+"success_delete"),this.bindCustomEvents(),this.render()},bindCustomEvents:function(){this.sandbox.on("sulu.toolbar.add",this.add.bind(this)),this.sandbox.on("sulu.toolbar.delete",this.deleteSelected.bind(this)),this.sandbox.on("husky.datagrid.item.click",this.saveLastClickedEvent.bind(this)),this.sandbox.on("husky.datagrid.number.selections",this.activateDeleteButton.bind(this))},activateDeleteButton:function(a){a?this.sandbox.emit("sulu.header.toolbar.item.enable","deleteSelected",!0):this.sandbox.emit("sulu.header.toolbar.item.disable","deleteSelected",!1)},render:function(){this.sandbox.dom.html(this.$el,'
'),this.sandbox.sulu.initListToolbarAndList.call(this,c.toolbarKey,c.fieldsAction,{el:this.$find("#"+c.toolbarId),template:"default",instanceName:this.instanceName},{el:this.$find("#"+c.listId),instanceName:this.instanceName,url:c.endPointUrl+"?locale="+this.options.language+"&flat=true",resultKey:c.toolbarKey,searchFields:c.toolbarSearchFields,viewOptions:{table:{icons:[{column:"id",icon:"pencil",align:"left",callback:this.edit.bind(this)}],rowClickSelect:!0,highlightSelected:!0,fullWidth:!0}}})},add:function(){this.sandbox.emit(c.eventPrefix+"navigate-add")},edit:function(a){this.saveLastClickedEvent(a),this.sandbox.emit(c.eventPrefix+"navigate-to",a)},saveLastClickedEvent:function(a){a&&this.sandbox.sulu.saveUserSetting(c.lastClickedEventSettingsKey,a)},deleteSelected:function(){this.sandbox.emit("husky.datagrid.items.get-selected",function(a){this.sandbox.emit(c.eventPrefix+"delete",a,function(a){this.sandbox.emit("husky.datagrid.record.remove",a)}.bind(this),function(){this.sandbox.emit("sulu.labels.success.show",c.translatePrefix+"delete.success","labels.success")}.bind(this))}.bind(this))}}}); \ No newline at end of file +define(["l91suluform/collections/forms"],function(a){"use strict";var b=new a,c={toolbarId:"form-toolbar",listId:"form-list",lastClickedEventSettingsKey:"l91suluformformLastClicked",endPointUrl:b.url(),toolbarKey:"forms",toolbarSearchFields:["title"],fieldsAction:b.fieldsUrl(),eventPrefix:"l91.sulu.form.forms.",translatePrefix:"l91_sulu_form.forms."};return{view:!0,layout:{content:{width:"max"}},header:function(){return{title:c.translatePrefix+"title",noBack:!0,toolbar:{languageChanger:{preSelected:this.options.language},buttons:{add:{},deleteSelected:{}}}}},initialize:function(){this.sandbox.sulu.triggerDeleteSuccessLabel(c.translatePrefix+"success_delete"),this.bindCustomEvents(),this.render()},bindCustomEvents:function(){this.sandbox.on("sulu.toolbar.add",this.add.bind(this)),this.sandbox.on("sulu.toolbar.delete",this.deleteSelected.bind(this)),this.sandbox.on("husky.datagrid.item.click",this.saveLastClickedEvent.bind(this)),this.sandbox.on("husky.datagrid.number.selections",this.activateDeleteButton.bind(this))},activateDeleteButton:function(a){a?this.sandbox.emit("sulu.header.toolbar.item.enable","deleteSelected",!0):this.sandbox.emit("sulu.header.toolbar.item.disable","deleteSelected",!1)},render:function(){this.sandbox.dom.html(this.$el,'
'),this.sandbox.sulu.initListToolbarAndList.call(this,c.toolbarKey,c.fieldsAction,{el:this.$find("#"+c.toolbarId),template:"default",instanceName:this.instanceName},{el:this.$find("#"+c.listId),instanceName:this.instanceName,url:c.endPointUrl+"?locale="+this.options.language+"&flat=true&sortBy=title&sortOrder=asc",resultKey:c.toolbarKey,searchFields:c.toolbarSearchFields,viewOptions:{table:{icons:[{column:"title",icon:"pencil",align:"left",callback:this.edit.bind(this)}],rowClickSelect:!0,highlightSelected:!0,fullWidth:!0}}})},add:function(){this.sandbox.emit(c.eventPrefix+"navigate-add")},edit:function(a){this.saveLastClickedEvent(a),this.sandbox.emit(c.eventPrefix+"navigate-to",a)},saveLastClickedEvent:function(a){a&&this.sandbox.sulu.saveUserSetting(c.lastClickedEventSettingsKey,a)},deleteSelected:function(){this.sandbox.emit("husky.datagrid.items.get-selected",function(a){this.sandbox.emit(c.eventPrefix+"delete",a,function(a){this.sandbox.emit("husky.datagrid.record.remove",a)}.bind(this),function(){this.sandbox.emit("sulu.labels.success.show",c.translatePrefix+"delete.success","labels.success")}.bind(this))}.bind(this))}}}); \ No newline at end of file From 44f3bd52c88f2c02643b5b6180eb4e526868d73c Mon Sep 17 00:00:00 2001 From: L91 Date: Tue, 20 Sep 2016 11:20:47 +0200 Subject: [PATCH 05/39] Fix csrf token when using varnish (#99) --- CHANGELOG.md | 1 + Controller/FormWebsiteController.php | 21 +++++++++++++++++---- Resources/doc/dynamic.md | 3 +-- Resources/doc/static.md | 3 +-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7a9590..9a11594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #98 Fixed csrf token esi for varnish - BUGFIX #97 Fixed edit symbol on list - BUGFIX #96 Fix inversedBy value at FormField#form property - FEATURE #92 Clean up the backend view diff --git a/Controller/FormWebsiteController.php b/Controller/FormWebsiteController.php index ea4dfe2..6fef888 100644 --- a/Controller/FormWebsiteController.php +++ b/Controller/FormWebsiteController.php @@ -132,12 +132,25 @@ public function onlyAction(Request $request, $key) */ public function tokenAction(Request $request) { - $response = new Response( - $this->getFormHandler()->getToken( - $request->get('form') - ) + $formName = $request->get('form'); + $csrfToken = $this->getFormHandler()->getToken( + $request->get('form') ); + $content = $csrfToken; + + // this should be the default behaviour in future because for varnish its needed + if ($request->get('html')) { + $content = sprintf( + '', + $formName, + $formName, + $csrfToken + ); + } + + $response = new Response($content); + /* Deactivate Cache for this token action */ $response->setSharedMaxAge(0); $response->setMaxAge(0); diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index b13d6c7..a3b036d 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -46,8 +46,7 @@ https://github.com/symfony/symfony/blob/v2.7.0/src/Symfony/Bridge/Twig/Resources ```twig {%- block _dynamic_form__token_widget -%} - {% set type = type|default('hidden') %} - + {{ render_esi(controller('L91SuluFormBundle:FormWebsite:token', { 'form': form.parent.vars.name, 'html': true })) }} {% endblock %} {%- block form_row -%} diff --git a/Resources/doc/static.md b/Resources/doc/static.md index 5951a81..fe4f5f0 100644 --- a/Resources/doc/static.md +++ b/Resources/doc/static.md @@ -223,8 +223,7 @@ ClientWebsiteBundle:forms:theme.html.twig: ``` twig {% block token_widget %} - {% set type = type|default('hidden') %} - + { render_esi(controller('L91SuluFormBundle:FormWebsite:token', { 'form': 'form_type_alias', 'html': true })) }} {% endblock token_widget %} ``` From ad2c18c4a418378a9fdec144b516f38bf6b2b632 Mon Sep 17 00:00:00 2001 From: L91 Date: Tue, 20 Sep 2016 15:22:01 +0200 Subject: [PATCH 06/39] added page based list output (#100) --- CHANGELOG.md | 3 ++- Controller/ListController.php | 7 ++----- Provider/DynamicProvider.php | 6 +++++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a11594..71aefde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog ## dev-develop - - BUGFIX #98 Fixed csrf token esi for varnish + - FEATURE #100 Added page based list output + - BUGFIX #99 Fixed csrf token esi for varnish - BUGFIX #97 Fixed edit symbol on list - BUGFIX #96 Fix inversedBy value at FormField#form property - FEATURE #92 Clean up the backend view diff --git a/Controller/ListController.php b/Controller/ListController.php index 455ce1c..306f49f 100644 --- a/Controller/ListController.php +++ b/Controller/ListController.php @@ -65,11 +65,8 @@ public function cgetAction(Request $request) if (isset($fieldDescriptors['uuid'])) { $listBuilder->where($fieldDescriptors['uuid'], $uuid); } - if (isset($fieldDescriptors['webspace'])) { - $listBuilder->where($fieldDescriptors['webspace'], $webspace); - } - if (isset($fieldDescriptors['locale'])) { - $listBuilder->where($fieldDescriptors['locale'], $locale); + if (isset($fieldDescriptors['webspaceKey'])) { + $listBuilder->where($fieldDescriptors['webspaceKey'], $webspace); } if (isset($fieldDescriptors['template'])) { $listBuilder->where($fieldDescriptors['template'], $template); diff --git a/Provider/DynamicProvider.php b/Provider/DynamicProvider.php index 730c915..a2b08e3 100644 --- a/Provider/DynamicProvider.php +++ b/Provider/DynamicProvider.php @@ -14,6 +14,9 @@ public function getFieldDescriptors($webspace, $locale, $uuid) { $fieldDescriptors = [ 'id' => $this->createFieldDescriptor('id', '', 'public.id'), + 'uuid' => $this->createFieldDescriptor('uuid', '', 'uuid', true), + 'webspaceKey' => $this->createFieldDescriptor('webspaceKey', '', 'webspaceKey', true), + 'locale' => $this->createFieldDescriptor('locale', '', 'locale'), 'firstName' => $this->createFieldDescriptor('firstName'), 'lastName' => $this->createFieldDescriptor('lastName'), 'email' => $this->createFieldDescriptor('email'), @@ -33,8 +36,9 @@ public function getFieldDescriptors($webspace, $locale, $uuid) /** * @param string $name - * @param bool $disabled * @param string $type + * @param string $translationKey + * @param bool $disabled * * @return DoctrineFieldDescriptor */ From 0e96bbb4ffd43553993eaf3c8b5340b4dacca1e6 Mon Sep 17 00:00:00 2001 From: L91 Date: Tue, 20 Sep 2016 17:51:22 +0200 Subject: [PATCH 07/39] change mail settings options to toggler (#101) --- CHANGELOG.md | 39 +++++++-------- Resources/views/forms/template.html.twig | 61 ++++++++++++++---------- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71aefde..2ff5752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,33 @@ # Changelog ## dev-develop - - FEATURE #100 Added page based list output - - BUGFIX #99 Fixed csrf token esi for varnish - - BUGFIX #97 Fixed edit symbol on list - - BUGFIX #96 Fix inversedBy value at FormField#form property - - FEATURE #92 Clean up the backend view - - FEATURE #92 Added last flag for grid and update documentation - - BUGFIX #85 Fixed MailChimp-Key parameter in FormController + - ENHANCEMENT #101 Change mail settings options to toggler + - FEATURE #100 Added page based list output + - BUGFIX #99 Fixed csrf token esi for varnish + - BUGFIX #97 Fixed edit symbol on list + - BUGFIX #96 Fix inversedBy value at FormField#form property + - FEATURE #92 Clean up the backend view + - FEATURE #92 Added last flag for grid and update documentation + - BUGFIX #85 Fixed MailChimp-Key parameter in FormController ## 1.0.0-RC4 - - BUGFIX #80 Fixed getCustomerDeactivateMails and getNotifyDeactivateMails Method - - BUGFIX #79 Fixed resolver of configureOptions in AbstractType + - BUGFIX #80 Fixed getCustomerDeactivateMails and getNotifyDeactivateMails Method + - BUGFIX #79 Fixed resolver of configureOptions in AbstractType ## 1.0.0-RC3 - - FEATURE #74 Added mailchimp field type (requires https://github.com/drewm/mailchimp-api) - - BUGFIX #76 Fixed csrf token generation in esi - - BUGFIX #75 Fixed csrf token generation for dynamic form - - FEATURE #73 Added type sort after translation function + - FEATURE #74 Added mailchimp field type (requires https://github.com/drewm/mailchimp-api) + - BUGFIX #76 Fixed csrf token generation in esi + - BUGFIX #75 Fixed csrf token generation for dynamic form + - FEATURE #73 Added type sort after translation function ## 1.0.0-RC2 - - BUGFIX #70 Fixed token esi response header - - BUGFIX #71 Fixed customer emails for dynamic forms - - FEATURE #68 Added checkboxes to deactivate notify and success emails - - FEATURE #67 Added sixths widths to fields - - BUGFIX #66 Fixed that dynamic is related to a form - - BUGFIX #65 Unlimited title column and changed string to text + - BUGFIX #70 Fixed token esi response header + - BUGFIX #71 Fixed customer emails for dynamic forms + - FEATURE #68 Added checkboxes to deactivate notify and success emails + - FEATURE #67 Added sixths widths to fields + - BUGFIX #66 Fixed that dynamic is related to a form + - BUGFIX #65 Unlimited title column and changed string to text diff --git a/Resources/views/forms/template.html.twig b/Resources/views/forms/template.html.twig index 1aca783..949155e 100644 --- a/Resources/views/forms/template.html.twig +++ b/Resources/views/forms/template.html.twig @@ -160,47 +160,60 @@
+
-
-
-
From 1c541f30230e09e416818353f2aa8747b7ea1fa9 Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 22 Sep 2016 17:18:49 +0200 Subject: [PATCH 08/39] added recaptcha support with ewz recaptcha bundle (#102) --- CHANGELOG.md | 1 + Controller/FormController.php | 15 ++- Entity/Dynamic.php | 2 + Form/Type/DynamicFormType.php | 12 +- README.md | 1 + Resources/doc/dynamic.md | 23 ++++ Resources/doc/mailchimp.md | 4 +- Resources/doc/recaptcha.md | 44 +++++++ Resources/translations/messages.de.xliff | 108 +----------------- Resources/translations/messages.en.xliff | 108 +----------------- Resources/translations/messages.fr.xliff | 108 +----------------- Resources/translations/sulu/backend.de.xlf | 4 + Resources/translations/sulu/backend.en.xlf | 4 + Resources/translations/sulu/backend.fr.xlf | 4 + .../forms/fields/types/recaptcha.html.twig | 28 +++++ 15 files changed, 136 insertions(+), 330 deletions(-) create mode 100644 Resources/doc/recaptcha.md create mode 100644 Resources/views/forms/fields/types/recaptcha.html.twig diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ff5752..c0957f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - FEATURE #102 Added recaptcha support with EWZRecaptchaBundle - ENHANCEMENT #101 Change mail settings options to toggler - FEATURE #100 Added page based list output - BUGFIX #99 Fixed csrf token esi for varnish diff --git a/Controller/FormController.php b/Controller/FormController.php index 4adbb01..7eeb7df 100644 --- a/Controller/FormController.php +++ b/Controller/FormController.php @@ -2,7 +2,6 @@ namespace L91\Sulu\Bundle\FormBundle\Controller; -use DrewM\MailChimp\MailChimp; use FOS\RestBundle\Controller\FOSRestController; use FOS\RestBundle\Routing\ClassResourceInterface; use L91\Sulu\Bundle\FormBundle\Entity\Dynamic; @@ -194,7 +193,11 @@ public function cgetTemplateAction(Request $request) $types = Dynamic::$TYPES; if (!empty($mailChimpLists)) { - $types = array_merge(Dynamic::$TYPES, [Dynamic::TYPE_MAILCHIMP]); + $types[] = Dynamic::TYPE_MAILCHIMP; + } + + if (class_exists(\EWZ\Bundle\RecaptchaBundle\Form\Type\RecaptchaType::class)) { + $types[] = Dynamic::TYPE_RECAPTCHA; } return $this->render( @@ -218,11 +221,11 @@ public function getMailChimpLists() $apiKey = $this->getParameter('l91_sulu_form.mailchimp_api_key'); // if mailchimp class doesn't exist or no key is set return empty list - if (!class_exists('DrewM\MailChimp\MailChimp') || !$apiKey) { + if (!class_exists(\DrewM\MailChimp\MailChimp::class) || !$apiKey) { return $lists; } - $mailChimp = new MailChimp($apiKey); + $mailChimp = new \DrewM\MailChimp\MailChimp($apiKey); $response = $mailChimp->get('lists'); if (!isset($response['lists'])) { @@ -251,13 +254,13 @@ public function getSortedTypes($types = []) $sortedTypes = []; foreach ($types as $key => $type) { - $translation = $translator->trans('l91_sulu_form.type.' . $type); + $translation = $translator->trans('l91_sulu_form.type.' . strtolower($type), [], 'backend'); $sortedTypes[$translation . $key] = $type; } ksort($sortedTypes); - return $sortedTypes; + return array_values($sortedTypes); } /** diff --git a/Entity/Dynamic.php b/Entity/Dynamic.php index 24bb5f6..832d171 100644 --- a/Entity/Dynamic.php +++ b/Entity/Dynamic.php @@ -32,7 +32,9 @@ class Dynamic implements TimestampableInterface const TYPE_DROPDOWN = 'dropdown'; const TYPE_DROPDOWN_MULTIPLE = 'dropdownMultiple'; const TYPE_RADIO_BUTTONS = 'radioButtons'; + const TYPE_MAILCHIMP = 'mailchimp'; + const TYPE_RECAPTCHA = 'recaptcha'; /** * @var int diff --git a/Form/Type/DynamicFormType.php b/Form/Type/DynamicFormType.php index 7bd0824..b2b97b4 100644 --- a/Form/Type/DynamicFormType.php +++ b/Form/Type/DynamicFormType.php @@ -104,7 +104,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $lastWidth = $this->getLastWidth($currentWidthValue, $width); - $options['label'] = $title; + $options['label'] = $title ?: false; $options['required'] = $field->getRequired(); $options['attr']['width'] = $width; $options['attr']['lastWidth'] = $lastWidth; @@ -154,6 +154,16 @@ public function buildForm(FormBuilderInterface $builder, array $options) case Dynamic::TYPE_MAILCHIMP: $type = CheckboxType::class; break; + case Dynamic::TYPE_RECAPTCHA: + // use in this way the recaptcha bundle could maybe not exists + $type = \EWZ\Bundle\RecaptchaBundle\Form\Type\RecaptchaType::class; + $options['mapped'] = false; + $options['constraints'][] = new \EWZ\Bundle\RecaptchaBundle\Validator\Constraints\IsTrue(); + $options['attr']['options'] = [ + 'theme' => 'light', + 'type' => 'image', + ]; + break; case Dynamic::TYPE_CHECKBOX_MULTIPLE: $type = $this->createChoiceType($translation, $options, true, true); break; diff --git a/README.md b/README.md index 04a2f73..ca17928 100644 --- a/README.md +++ b/README.md @@ -80,3 +80,4 @@ Make sure you've set the correct permissions in the Sulu backend for this bundle ## Additional form fields - [Mailchimp](Resources/doc/mailchimp.md "Mailchimp Form Field") +- [Recaptcha](Resources/doc/recaptcha.md "Recaptcha Form Field") diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index a3b036d..1081a80 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -83,6 +83,29 @@ https://github.com/symfony/symfony/blob/v2.7.0/src/Symfony/Bridge/Twig/Resources {%- endblock hidden_row -%} +{%- block form_label -%} + {% if label is not same as(false) -%} + {% if not compound -%} + {% set label_attr = label_attr|merge({'for': id}) %} + {%- endif -%} + {% if required -%} + {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %} + {%- endif -%} + {% if label is empty -%} + {%- if label_format is not empty -%} + {% set label = label_format|replace({ + '%name%': name, + '%id%': id, + }) %} + {%- else -%} + {% set label = name|humanize %} + {%- endif -%} + {%- endif -%} + + {{ label|raw }} + + {%- endif -%} +{%- endblock form_label -%} ``` ## Issues diff --git a/Resources/doc/mailchimp.md b/Resources/doc/mailchimp.md index b524cc4..f9a7be1 100644 --- a/Resources/doc/mailchimp.md +++ b/Resources/doc/mailchimp.md @@ -2,11 +2,11 @@ The following is showing an example how you can use the Mailchimp form field to add customers to your Mailchimp lists. -## Requiered Bundles +## Installation First of all you need to install drewn's Mailchimp API, if this bundle is missing the Mailchimp Fieldtype won't be available. -``` json +```json { "require": { "drewm/mailchimp-api": "^2.2" diff --git a/Resources/doc/recaptcha.md b/Resources/doc/recaptcha.md new file mode 100644 index 0000000..4a6aeed --- /dev/null +++ b/Resources/doc/recaptcha.md @@ -0,0 +1,44 @@ +# Recaptcha Form Field + +The following is showing how you can use the Recaptcha form field. + +## Installation + +First of all you need to install ewz's RecaptchaBundle, if this bundle is missing it will not work. + +```json +{ + "require": { + "excelwebzone/recaptcha-bundle": "^1.4" + } +} +``` + +or + +```bash +composer require excelwebzone/recaptcha-bundle:^1.4 +``` + +**Register Bundle in `app/AbstractKernel.php`** + +Add the bundle the the AbstractKernel. + +```php +$bundles = [ + new EWZ\Bundle\RecaptchaBundle\EWZRecaptchaBundle(), +]; +``` + +## Config + +add the following config to `app/config/config.yml` + +```yml +ewz_recaptcha: + public_key: + private_key: +``` + +Visit [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/intro/index.html) to get the public and private key. +or visit [https://developers.google.com/recaptcha/docs/faq](https://developers.google.com/recaptcha/docs/faq) to get test keys. diff --git a/Resources/translations/messages.de.xliff b/Resources/translations/messages.de.xliff index 904e5b8..0d9e582 100644 --- a/Resources/translations/messages.de.xliff +++ b/Resources/translations/messages.de.xliff @@ -14,112 +14,6 @@ l91_sulu_form.created Erstellt am - - - - l91_sulu_form.type.salutation - Anrede - - - l91_sulu_form.type.title - Titel - - - l91_sulu_form.type.firstName - Vorname - - - l91_sulu_form.type.lastName - Nachname - - - l91_sulu_form.type.email - E-Mail - - - l91_sulu_form.type.phone - Telefon - - - l91_sulu_form.type.fax - Fax - - - l91_sulu_form.type.street - Straße - - - l91_sulu_form.type.zip - PLZ - - - l91_sulu_form.type.city - Stadt - - - l91_sulu_form.type.state - Bundesland - - - l91_sulu_form.type.country - Land - - - l91_sulu_form.type.function - Funktion - - - l91_sulu_form.type.company - Firma - - - l91_sulu_form.type.text - Einzeiliges Textfeld - - - l91_sulu_form.type.textarea - Mehrzeiliges Textfeld - - - l91_sulu_form.type.date - Datum - - - l91_sulu_form.type.headline - Überschrift - - - l91_sulu_form.type.attachment - Anhang - - - l91_sulu_form.type.checkbox - Checkbox - - - l91_sulu_form.type.checkboxMultiple - Checkboxes - - - l91_sulu_form.type.dropdown - Dropdown - - - l91_sulu_form.type.dropdownMultiple - Dropdown (Mehrfachauswahl) - - - l91_sulu_form.type.radioButtons - Radio Buttons - - - l91_sulu_form.type.freeText - Freier Text - - - l91_sulu_form.type.spacer - Leerraum - - \ No newline at end of file + diff --git a/Resources/translations/messages.en.xliff b/Resources/translations/messages.en.xliff index 76a6517..a01a283 100644 --- a/Resources/translations/messages.en.xliff +++ b/Resources/translations/messages.en.xliff @@ -14,112 +14,6 @@ l91_sulu_form.created Created on - - - - l91_sulu_form.type.salutation - Salutation - - - l91_sulu_form.type.title - Title - - - l91_sulu_form.type.firstName - Firstname - - - l91_sulu_form.type.lastName - Lastname - - - l91_sulu_form.type.email - E-Mail - - - l91_sulu_form.type.phone - Phone - - - l91_sulu_form.type.fax - Fax - - - l91_sulu_form.type.street - Street - - - l91_sulu_form.type.zip - Zip - - - l91_sulu_form.type.city - City - - - l91_sulu_form.type.state - State - - - l91_sulu_form.type.country - Country - - - l91_sulu_form.type.function - Function - - - l91_sulu_form.type.company - Company - - - l91_sulu_form.type.text - Simple Textfield - - - l91_sulu_form.type.textarea - Multiline Textfield - - - l91_sulu_form.type.date - Date - - - l91_sulu_form.type.headline - Headline - - - l91_sulu_form.type.attachment - Attachment - - - l91_sulu_form.type.checkbox - Checkbox - - - l91_sulu_form.type.checkboxMultiple - Checkboxes - - - l91_sulu_form.type.dropdown - Select - - - l91_sulu_form.type.dropdownMultiple - Select (multiple) - - - l91_sulu_form.type.radioButtons - Radio Buttons - - - l91_sulu_form.type.freeText - Free Text - - - l91_sulu_form.type.spacer - Spacer - - \ No newline at end of file + diff --git a/Resources/translations/messages.fr.xliff b/Resources/translations/messages.fr.xliff index 3143a25..3b7f17f 100644 --- a/Resources/translations/messages.fr.xliff +++ b/Resources/translations/messages.fr.xliff @@ -14,112 +14,6 @@ l91_sulu_form.created Créer le - - - - l91_sulu_form.type.salutation - Salutation - - - l91_sulu_form.type.title - Titre - - - l91_sulu_form.type.firstName - Prénom - - - l91_sulu_form.type.lastName - Nom de famille - - - l91_sulu_form.type.email - E-Mail - - - l91_sulu_form.type.phone - Téléphone - - - l91_sulu_form.type.fax - Fax - - - l91_sulu_form.type.street - Rue - - - l91_sulu_form.type.zip - Code postal - - - l91_sulu_form.type.city - Ville - - - l91_sulu_form.type.state - Etat - - - l91_sulu_form.type.country - Pays - - - l91_sulu_form.type.function - Fonction - - - l91_sulu_form.type.company - Compagnie - - - l91_sulu_form.type.text - Simple Textfield - - - l91_sulu_form.type.textarea - Multiline Textfield - - - l91_sulu_form.type.date - Date - - - l91_sulu_form.type.headline - Gros titre - - - l91_sulu_form.type.attachment - Attachement - - - l91_sulu_form.type.checkbox - Checkbox - - - l91_sulu_form.type.checkboxMultiple - Checkboxes - - - l91_sulu_form.type.dropdown - Select - - - l91_sulu_form.type.dropdownMultiple - Select (multiple) - - - l91_sulu_form.type.radioButtons - Radio Buttons - - - l91_sulu_form.type.freeText - Free Text - - - l91_sulu_form.type.spacer - Spacer - - \ No newline at end of file + diff --git a/Resources/translations/sulu/backend.de.xlf b/Resources/translations/sulu/backend.de.xlf index 4ba51d0..5bea9f9 100644 --- a/Resources/translations/sulu/backend.de.xlf +++ b/Resources/translations/sulu/backend.de.xlf @@ -215,6 +215,10 @@ l91_sulu_form.mailchimp_list Mailchimp Liste + + l91_sulu_form.type.recaptcha + Captcha + diff --git a/Resources/translations/sulu/backend.en.xlf b/Resources/translations/sulu/backend.en.xlf index ac00699..06ada35 100644 --- a/Resources/translations/sulu/backend.en.xlf +++ b/Resources/translations/sulu/backend.en.xlf @@ -215,6 +215,10 @@ l91_sulu_form.mailchimp_list Mailchimp List + + l91_sulu_form.type.recaptcha + Captcha + diff --git a/Resources/translations/sulu/backend.fr.xlf b/Resources/translations/sulu/backend.fr.xlf index 4312bd3..7cdae65 100644 --- a/Resources/translations/sulu/backend.fr.xlf +++ b/Resources/translations/sulu/backend.fr.xlf @@ -214,6 +214,10 @@ l91_sulu_form.mailchimp_list Mailchimp List + + l91_sulu_form.type.recaptcha + Captcha + diff --git a/Resources/views/forms/fields/types/recaptcha.html.twig b/Resources/views/forms/fields/types/recaptcha.html.twig new file mode 100644 index 0000000..77f2624 --- /dev/null +++ b/Resources/views/forms/fields/types/recaptcha.html.twig @@ -0,0 +1,28 @@ +{% extends "L91SuluFormBundle:forms:fields/default-field.html.twig" %} + +{% block required %}{% endblock %} + +{% block title %} +
+ + + +
+ +
+
+{% endblock %} + +{% block placeholder_default %} +{% endblock %} + +{% block extended %} +{% endblock %} From 2f4c5e60aa9f7f01cfe061a7fb65f00c120517fa Mon Sep 17 00:00:00 2001 From: L91 Date: Tue, 27 Sep 2016 10:27:25 +0200 Subject: [PATCH 09/39] added new form layout (#105) --- CHANGELOG.md | 1 + Resources/public/css/main.css | 5 + Resources/public/css/main.min.css | 1 + .../public/dist/components/forms/form/main.js | 2 +- Resources/public/dist/main.js | 2 +- .../public/js/components/forms/form/main.js | 10 +- Resources/public/js/main.js | 81 +-- Resources/public/scss/main.scss | 8 + Resources/views/forms/template.html.twig | 475 +++++++++--------- 9 files changed, 312 insertions(+), 273 deletions(-) create mode 100644 Resources/public/css/main.css create mode 100644 Resources/public/css/main.min.css create mode 100644 Resources/public/scss/main.scss diff --git a/CHANGELOG.md b/CHANGELOG.md index c0957f9..3b56f55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - ENHANCEMENT #103 Added new form layout - FEATURE #102 Added recaptcha support with EWZRecaptchaBundle - ENHANCEMENT #101 Change mail settings options to toggler - FEATURE #100 Added page based list output diff --git a/Resources/public/css/main.css b/Resources/public/css/main.css new file mode 100644 index 0000000..75d27e7 --- /dev/null +++ b/Resources/public/css/main.css @@ -0,0 +1,5 @@ +/* line 3, ../scss/main.scss */ +#form-form .highlight-section .content { + padding-top: 20px; + padding-bottom: 20px; +} diff --git a/Resources/public/css/main.min.css b/Resources/public/css/main.min.css new file mode 100644 index 0000000..6fa771d --- /dev/null +++ b/Resources/public/css/main.min.css @@ -0,0 +1 @@ +#form-form .highlight-section .content{padding-top:20px;padding-bottom:20px} \ No newline at end of file diff --git a/Resources/public/dist/components/forms/form/main.js b/Resources/public/dist/components/forms/form/main.js index 351f2cb..b8f7851 100644 --- a/Resources/public/dist/components/forms/form/main.js +++ b/Resources/public/dist/components/forms/form/main.js @@ -1 +1 @@ -define(function(){"use strict";var a={activeTab:"general",data:{},instanceName:"form",newTitle:"l91_sulu_form.forms.new_form"},b={general:{name:"general",url:"/admin/api/l91/forms/template",formSelector:"#form-form"}},c="l91_sulu_form.forms.",d="l91.sulu.form.forms.";return{view:!0,templates:$.map(b,function(a){return[a.url]}),initialize:function(){this.options=this.sandbox.util.extend(!0,{},a,this.options),this.saved=!0,this.bindCustomEvents(),this.render()},bindCustomEvents:function(){this.sandbox.on("sulu.header.back",function(){this.sandbox.emit(d+"navigate-list")}.bind(this)),this.sandbox.on("sulu.toolbar.save",this.save.bind(this)),this.sandbox.on("sulu.toolbar.delete",this["delete"].bind(this))},render:function(){this.setHeaderInfos(),this.renderForm(b[this.options.activeTab].url)},renderForm:function(a){var b=this.getActiveFormSelector();this.sandbox.dom.html(this.$el,this.renderTemplate(a)),this.sandbox.form.create(b),this.sandbox.form.setData(b,this.options.data).then(function(){this.sandbox.start(b),this.bindFormEvents(),this.sandbox.dom.find("input[autofocus]").first().focus()}.bind(this))},bindFormEvents:function(){var a=this.getActiveFormSelector();this.sandbox.dom.on(a,"keyup",this.activateSaveButton.bind(this),"input, textarea"),this.sandbox.dom.on(a,"change",this.activateSaveButton.bind(this),'input[type="checkbox"], select'),this.sandbox.on("husky.select.width.selected.item",this.activateSaveButton.bind(this)),this.sandbox.on("husky.ckeditor.changed",this.activateSaveButton.bind(this)),this.sandbox.on("sulu.content.changed",this.activateSaveButton.bind(this)),this.sandbox.on("husky.overlay.alert.closed",this.activateSaveButton.bind(this)),this.initSortableBlock(),this.sandbox.dom.on(a,"form-add",function(a,b,c,d){var e=this.sandbox.dom.children(this.$find('[data-mapper-property="'+b+'"]')),f=void 0!==d&&e.length>d?e[d]:this.sandbox.dom.last(e);this.sandbox.start(f),this.initSortableBlock()}.bind(this)),this.sandbox.dom.on(a,"init-sortable",function(a){this.initSortableBlock(),this.sandbox.emit("sulu.content.changed")}.bind(this))},initSortableBlock:function(){var a,b=this.sandbox.dom.find(".sortable",this.$el);b&&b.length>0&&(this.sandbox.dom.sortable(b,"destroy"),a=this.sandbox.dom.sortable(b,{handle:".move",forcePlaceholderSize:!0}),this.sandbox.dom.unbind(a,"sortupdate"),a.bind("sortupdate",function(a){this.sandbox.emit("sulu.content.changed")}.bind(this)))},getActiveFormSelector:function(){return b[this.options.activeTab].formSelector},activateSaveButton:function(){this.saved===!0&&(this.sandbox.emit("sulu.header.toolbar.item.enable","save",!1),this.saved=!1)},setHeaderInfos:function(){this.sandbox.emit("sulu.header.set-title",this.options.data.title||this.options.newTitle),this.options.data.id||this.sandbox.emit("sulu.header.toolbar.item.disable","settings",!1)},"delete":function(){this.options.data.id&&this.sandbox.emit(d+"delete",[this.options.data.id],null,function(){this.sandbox.sulu.unlockDeleteSuccessLabel(),this.sandbox.emit(d+"navigate-list")}.bind(this))},save:function(){var a=this.getActiveFormSelector();if(this.sandbox.form.validate(a)){var b=this.sandbox.form.getData(a);b.id=this.options.data.id,b.locale=this.options.data.locale,this.options.data=b,this.sandbox.emit("sulu.header.toolbar.item.loading","save"),this.sandbox.emit(d+"save",this.options.data,this.savedCallback.bind(this,!this.options.data.id))}},savedCallback:function(a,b,e){e===!0?(this.setHeaderInfos(),this.sandbox.emit("sulu.header.toolbar.item.disable","save",!0),this.saved=!0,a===!0?this.sandbox.emit(d+"navigate-to",b.id):this.sandbox.emit(d+"navigate-to",b.id),this.sandbox.emit("sulu.labels.success.show",c+"save.success","labels.success")):(this.sandbox.emit("sulu.header.toolbar.item.enable","save",!1),1===b.code?this.sandbox.emit("sulu.labels.error.show",c+"save.error-unique","labels.error"):this.sandbox.emit("sulu.labels.error.show",c+"save.error","labels.error"))}}}); \ No newline at end of file +define(function(){"use strict";var a={activeTab:"general",data:{},instanceName:"form",newTitle:"l91_sulu_form.forms.new_form"},b={general:{name:"general",url:"/admin/api/l91/forms/template",formSelector:"#form-form"}},c="l91_sulu_form.forms.",d="l91.sulu.form.forms.";return{view:!0,layout:{content:{width:"fixed",topSpace:!0,leftSpace:!1,rightSpace:!1}},templates:$.map(b,function(a){return[a.url]}),initialize:function(){this.options=this.sandbox.util.extend(!0,{},a,this.options),this.saved=!0,this.bindCustomEvents(),this.render()},bindCustomEvents:function(){this.sandbox.on("sulu.header.back",function(){this.sandbox.emit(d+"navigate-list")}.bind(this)),this.sandbox.on("sulu.toolbar.save",this.save.bind(this)),this.sandbox.on("sulu.toolbar.delete",this["delete"].bind(this))},render:function(){this.setHeaderInfos(),this.renderForm(b[this.options.activeTab].url)},renderForm:function(a){var b=this.getActiveFormSelector();this.sandbox.dom.html(this.$el,this.renderTemplate(a)),this.sandbox.form.create(b),this.sandbox.form.setData(b,this.options.data).then(function(){this.sandbox.start(b),this.bindFormEvents(),this.sandbox.dom.find("input[autofocus]").first().focus()}.bind(this))},bindFormEvents:function(){var a=this.getActiveFormSelector();this.sandbox.dom.on(a,"keyup",this.activateSaveButton.bind(this),"input, textarea"),this.sandbox.dom.on(a,"change",this.activateSaveButton.bind(this),'input[type="checkbox"], select'),this.sandbox.on("husky.select.width.selected.item",this.activateSaveButton.bind(this)),this.sandbox.on("husky.ckeditor.changed",this.activateSaveButton.bind(this)),this.sandbox.on("sulu.content.changed",this.activateSaveButton.bind(this)),this.sandbox.on("husky.overlay.alert.closed",this.activateSaveButton.bind(this)),this.initSortableBlock(),this.sandbox.dom.on(a,"form-add",function(a,b,c,d){var e=this.sandbox.dom.children(this.$find('[data-mapper-property="'+b+'"]')),f=void 0!==d&&e.length>d?e[d]:this.sandbox.dom.last(e);this.sandbox.start(f),this.initSortableBlock()}.bind(this)),this.sandbox.dom.on(a,"init-sortable",function(a){this.initSortableBlock(),this.sandbox.emit("sulu.content.changed")}.bind(this))},initSortableBlock:function(){var a,b=this.sandbox.dom.find(".sortable",this.$el);b&&b.length>0&&(this.sandbox.dom.sortable(b,"destroy"),a=this.sandbox.dom.sortable(b,{handle:".move",forcePlaceholderSize:!0}),this.sandbox.dom.unbind(a,"sortupdate"),a.bind("sortupdate",function(a){this.sandbox.emit("sulu.content.changed")}.bind(this)))},getActiveFormSelector:function(){return b[this.options.activeTab].formSelector},activateSaveButton:function(){this.saved===!0&&(this.sandbox.emit("sulu.header.toolbar.item.enable","save",!1),this.saved=!1)},setHeaderInfos:function(){this.options.data.id||this.sandbox.emit("sulu.header.toolbar.item.disable","settings",!1)},"delete":function(){this.options.data.id&&this.sandbox.emit(d+"delete",[this.options.data.id],null,function(){this.sandbox.sulu.unlockDeleteSuccessLabel(),this.sandbox.emit(d+"navigate-list")}.bind(this))},save:function(){var a=this.getActiveFormSelector();if(this.sandbox.form.validate(a)){var b=this.sandbox.form.getData(a);b.id=this.options.data.id,b.locale=this.options.data.locale,this.options.data=b,this.sandbox.emit("sulu.header.toolbar.item.loading","save"),this.sandbox.emit(d+"save",this.options.data,this.savedCallback.bind(this,!this.options.data.id))}},savedCallback:function(a,b,e){e===!0?(this.setHeaderInfos(),this.sandbox.emit("sulu.header.toolbar.item.disable","save",!0),this.saved=!0,a===!0?this.sandbox.emit(d+"navigate-to",b.id):this.sandbox.emit(d+"navigate-to",b.id),this.sandbox.emit("sulu.labels.success.show",c+"save.success","labels.success")):(this.sandbox.emit("sulu.header.toolbar.item.enable","save",!1),1===b.code?this.sandbox.emit("sulu.labels.error.show",c+"save.error-unique","labels.error"):this.sandbox.emit("sulu.labels.error.show",c+"save.error","labels.error"))}}}); \ No newline at end of file diff --git a/Resources/public/dist/main.js b/Resources/public/dist/main.js index 3908f09..2269176 100644 --- a/Resources/public/dist/main.js +++ b/Resources/public/dist/main.js @@ -1 +1 @@ -require.config({paths:{l91suluform:"../../l91suluform/dist","type/formSelect":"../../l91suluform/dist/validation/types/formSelect","type/select-type-custom":"../../l91suluform/dist/validation/types/select-type-custom"}}),define({name:"L91SuluFormBundle",initialize:function(a){"use strict";function b(){return c.sulu.getUserSetting("contentLanguage")||c.sulu.user.locale}var c=a.sandbox;a.components.addSource("l91suluform","/bundles/l91suluform/dist/components"),c.mvc.routes.push({route:"l91/forms",callback:function(){var a=b();c.emit("sulu.router.navigate","l91/forms/"+a)}}),c.mvc.routes.push({route:"l91/forms/:language",callback:function(a){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/add/:content",callback:function(a,b){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/edit::id/:content",callback:function(a,b,c){return'
'}})}}); \ No newline at end of file +require.config({paths:{l91suluform:"../../l91suluform/dist",l91suluformcss:"../../l91suluform/css","type/formSelect":"../../l91suluform/dist/validation/types/formSelect","type/select-type-custom":"../../l91suluform/dist/validation/types/select-type-custom"}}),define(["css!l91suluformcss/main"],function(){return{name:"L91SuluFormBundle",initialize:function(a){"use strict";function b(){return c.sulu.getUserSetting("contentLanguage")||c.sulu.user.locale}var c=a.sandbox;a.components.addSource("l91suluform","/bundles/l91suluform/dist/components"),c.mvc.routes.push({route:"l91/forms",callback:function(){var a=b();c.emit("sulu.router.navigate","l91/forms/"+a)}}),c.mvc.routes.push({route:"l91/forms/:language",callback:function(a){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/add/:content",callback:function(a,b){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/edit::id/:content",callback:function(a,b,c){return'
'}})}}}); \ No newline at end of file diff --git a/Resources/public/js/components/forms/form/main.js b/Resources/public/js/components/forms/form/main.js index 141aab1..a7cd709 100644 --- a/Resources/public/js/components/forms/form/main.js +++ b/Resources/public/js/components/forms/form/main.js @@ -27,6 +27,15 @@ define(function () { return { view: true, + layout: { + content: { + width: 'fixed', + topSpace: true, + leftSpace: false, + rightSpace: false + } + }, + templates: $.map(tabs, function(value) { return [value['url']]; }), @@ -152,7 +161,6 @@ define(function () { * like breadcrumb or title */ setHeaderInfos: function () { - this.sandbox.emit('sulu.header.set-title', this.options.data.title || this.options.newTitle); if (!this.options.data.id) { this.sandbox.emit('sulu.header.toolbar.item.disable', 'settings', false); } diff --git a/Resources/public/js/main.js b/Resources/public/js/main.js index 4cf58af..0ea1b98 100644 --- a/Resources/public/js/main.js +++ b/Resources/public/js/main.js @@ -5,57 +5,60 @@ require.config({ paths: { l91suluform: '../../l91suluform/js', + l91suluformcss: '../../l91suluform/css', "type/formSelect": '../../l91suluform/js/validation/types/formSelect', "type/select-type-custom": '../../l91suluform/js/validation/types/select-type-custom' } }); -define({ - name: "L91SuluFormBundle", +define(['css!l91suluformcss/main'], function() { + return { + name: "L91SuluFormBundle", - initialize: function(app) { - 'use strict'; - var sandbox = app.sandbox; + initialize: function(app) { + 'use strict'; + var sandbox = app.sandbox; - app.components.addSource('l91suluform', '/bundles/l91suluform/js/components'); + app.components.addSource('l91suluform', '/bundles/l91suluform/js/components'); - function getContentLanguage() { - // FIXME do not use user locale as default use default language of system instead - return sandbox.sulu.getUserSetting('contentLanguage') || sandbox.sulu.user.locale; - } - - // no language redirect: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. - sandbox.mvc.routes.push({ - route: 'l91/forms', - callback: function () { - var language = getContentLanguage(); - sandbox.emit('sulu.router.navigate', 'l91/forms/' + language); + function getContentLanguage() { + // FIXME do not use user locale as default use default language of system instead + return sandbox.sulu.getUserSetting('contentLanguage') || sandbox.sulu.user.locale; } - }); - // list all entities: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. - sandbox.mvc.routes.push({ - route: 'l91/forms/:language', - callback: function (language) { - return '
'; - } - }); + // no language redirect: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. + sandbox.mvc.routes.push({ + route: 'l91/forms', + callback: function () { + var language = getContentLanguage(); + sandbox.emit('sulu.router.navigate', 'l91/forms/' + language); + } + }); - // add entity: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. - sandbox.mvc.routes.push({ - route: 'l91/forms/:language/add/:content', - callback: function (language, content) { - return '
'; - } - }); + // list all entities: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. + sandbox.mvc.routes.push({ + route: 'l91/forms/:language', + callback: function (language) { + return '
'; + } + }); - // edit entity: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. - sandbox.mvc.routes.push({ - route: 'l91/forms/:language/edit::id/:content', - callback: function (language, id, content) { - return '
'; - } - }); + // add entity: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. + sandbox.mvc.routes.push({ + route: 'l91/forms/:language/add/:content', + callback: function (language, content) { + return '
'; + } + }); + + // edit entity: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. + sandbox.mvc.routes.push({ + route: 'l91/forms/:language/edit::id/:content', + callback: function (language, id, content) { + return '
'; + } + }); + } } }); diff --git a/Resources/public/scss/main.scss b/Resources/public/scss/main.scss new file mode 100644 index 0000000..ccaa94c --- /dev/null +++ b/Resources/public/scss/main.scss @@ -0,0 +1,8 @@ +#form-form { + .highlight-section { + .content { + padding-top: 20px; + padding-bottom: 20px; + } + } +} diff --git a/Resources/views/forms/template.html.twig b/Resources/views/forms/template.html.twig index 949155e..7ce6ab3 100644 --- a/Resources/views/forms/template.html.twig +++ b/Resources/views/forms/template.html.twig @@ -1,286 +1,299 @@ -
-
-
-
-
- + +
+
+
+
+
+
+
+
+ -
+ +
+
+
+
-

- <%= translate('l91_sulu_form.website_configuration') %> -

-
-
-
- +
+
+
+

+ <%= translate('l91_sulu_form.website_configuration') %> +

+
+
+
+ - + +
-
-

- <%= translate('l91_sulu_form.email_configuration') %> -

-
-
-
- +

+ <%= translate('l91_sulu_form.email_configuration') %> +

+
+
+
+ -
+
+
-
-
-
-
- +
+
+
+ -
+
+
-
-
-
- +
+
+ -
+
+
-
-
-
-
- +
+
+
+ -
+
+
-
-
-
- +
+
+ -
+
+
-
-
-
-
- +
+
+
+ - + +
-
- -
-
-
- + +
+
+
+ -
-
+
+
+
-
-
-
- +
+
+ -
-
+
+
+
-
-
-
- +
+
+ -
-
+
+
+
-
-
-
-
-
-

- <%= translate('l91_sulu_form.form_fields') %> -

+
+
+
+
+

+ <%= translate('l91_sulu_form.form_fields') %> +

- {% set blockId = 'fields' %} + {% set blockId = 'fields' %} -
-
{#class="text-blocks-header"#} -
- <%= translate('sulu.content.collapse.blocks') %> +
+
{#class="text-blocks-header"#} +
+ <%= translate('sulu.content.collapse.blocks') %> +
+
+ <%= translate('sulu.content.expand.blocks') %> +
+
-
- <%= translate('sulu.content.expand.blocks') %> -
-
-
- + #form-form .grid-row.dropdown-list.dropdown-shadow.husky-select-dropdown-container { + height: 200px; + } + -
", - "tpl": "{{ type }}-{{ blockId }}-tpl" - }{% if not loop.last %},{% endif %} - {% endfor %} - ]' - data-type-min="0" - data-type-max="999" - data-type-default="{{ types|first }}" - data-mapper-property="{{ blockId }}" - data-mapper-full-class="full" - data-mapper-empty-class="empty"> + { + "data": "{{ type }}", + "title": "<%= translate('{{ 'l91_sulu_form.type.'~ type|lower }}') %>", + "tpl": "{{ type }}-{{ blockId }}-tpl" + }{% if not loop.last %},{% endif %} + {% endfor %} + ]' + data-type-min="0" + data-type-max="999" + data-type-default="{{ types|first }}" + data-mapper-property="{{ blockId }}" + data-mapper-full-class="full" + data-mapper-empty-class="empty"> - {% for type in types %} - {% include 'L91SuluFormBundle:forms:fields/types/' ~ type|lower ~ '.html.twig' %} - {% endfor %} -
+ {% for type in types %} + {% include 'L91SuluFormBundle:forms:fields/types/' ~ type|lower ~ '.html.twig' %} + {% endfor %} +
- +
From 07d7ddf640ea56c909ae0052558b4f5f441ff248 Mon Sep 17 00:00:00 2001 From: L91 Date: Tue, 27 Sep 2016 10:29:54 +0200 Subject: [PATCH 10/39] fixed date field and add birthday option (#106) --- CHANGELOG.md | 1 + Form/Type/DynamicFormType.php | 7 ++++++- Resources/translations/sulu/backend.de.xlf | 8 ++++++-- Resources/translations/sulu/backend.en.xlf | 8 ++++++-- Resources/translations/sulu/backend.fr.xlf | 8 ++++++-- .../views/forms/fields/types/date.html.twig | 19 +++++++++++++++++-- 6 files changed, 42 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b56f55..720aa04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #104 Fixed datefield and add birthday option - ENHANCEMENT #103 Added new form layout - FEATURE #102 Added recaptcha support with EWZRecaptchaBundle - ENHANCEMENT #101 Change mail settings options to toggler diff --git a/Form/Type/DynamicFormType.php b/Form/Type/DynamicFormType.php index b2b97b4..8b0febc 100644 --- a/Form/Type/DynamicFormType.php +++ b/Form/Type/DynamicFormType.php @@ -6,6 +6,7 @@ use L91\Sulu\Bundle\FormBundle\Entity\Form; use L91\Sulu\Bundle\FormBundle\Entity\FormFieldTranslation; use L91\Sulu\Bundle\FormBundle\Entity\FormTranslation; +use Symfony\Component\Form\Extension\Core\Type\BirthdayType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\CountryType; @@ -143,7 +144,11 @@ public function buildForm(FormBuilderInterface $builder, array $options) break; case Dynamic::TYPE_DATE: $type = DateType::class; - $options['widget'] = 'single_text'; + if ($translation && $translation->getOption('birthday')) { + $type = BirthdayType::class; + } + $options['format'] = \IntlDateFormatter::LONG; + break; case Dynamic::TYPE_ATTACHMENT: $type = FileType::class; diff --git a/Resources/translations/sulu/backend.de.xlf b/Resources/translations/sulu/backend.de.xlf index 5bea9f9..8379040 100644 --- a/Resources/translations/sulu/backend.de.xlf +++ b/Resources/translations/sulu/backend.de.xlf @@ -145,6 +145,10 @@ l91_sulu_form.type.mailchimp Mailchimp + + l91_sulu_form.type.recaptcha + Captcha + @@ -216,8 +220,8 @@ Mailchimp Liste - l91_sulu_form.type.recaptcha - Captcha + l91_sulu_form.birthday + Geburtstag diff --git a/Resources/translations/sulu/backend.en.xlf b/Resources/translations/sulu/backend.en.xlf index 06ada35..d37e49f 100644 --- a/Resources/translations/sulu/backend.en.xlf +++ b/Resources/translations/sulu/backend.en.xlf @@ -145,6 +145,10 @@ l91_sulu_form.type.mailchimp Mailchimp + + l91_sulu_form.type.recaptcha + Captcha + @@ -216,8 +220,8 @@ Mailchimp List - l91_sulu_form.type.recaptcha - Captcha + l91_sulu_form.birthday + Birthday diff --git a/Resources/translations/sulu/backend.fr.xlf b/Resources/translations/sulu/backend.fr.xlf index 7cdae65..9ad08ed 100644 --- a/Resources/translations/sulu/backend.fr.xlf +++ b/Resources/translations/sulu/backend.fr.xlf @@ -144,6 +144,10 @@ l91_sulu_form.type.mailchimp Mailchimp + + l91_sulu_form.type.recaptcha + Captcha + @@ -215,8 +219,8 @@ Mailchimp List - l91_sulu_form.type.recaptcha - Captcha + l91_sulu_form.birthday + Birthday diff --git a/Resources/views/forms/fields/types/date.html.twig b/Resources/views/forms/fields/types/date.html.twig index 7dbf99a..ef5da63 100644 --- a/Resources/views/forms/fields/types/date.html.twig +++ b/Resources/views/forms/fields/types/date.html.twig @@ -1,12 +1,12 @@ {% extends "L91SuluFormBundle:forms:fields/default-field.html.twig" %} {% block default %} -
+
-
+ +
+ + +
+
{% endblock %} {% block extended %} From defae29723a99e4952f161ee2d36c4a522c58527 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Tue, 27 Sep 2016 10:43:09 +0200 Subject: [PATCH 11/39] fix changelog pr links --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 720aa04..daed8bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Changelog ## dev-develop - - BUGFIX #104 Fixed datefield and add birthday option - - ENHANCEMENT #103 Added new form layout + - BUGFIX #106 Fixed datefield and add birthday option + - ENHANCEMENT #105 Added new form layout - FEATURE #102 Added recaptcha support with EWZRecaptchaBundle - ENHANCEMENT #101 Change mail settings options to toggler - FEATURE #100 Added page based list output From 36a7cd11562ed0c9f64752b37707cc2771e0baca Mon Sep 17 00:00:00 2001 From: L91 Date: Tue, 18 Oct 2016 13:13:53 +0200 Subject: [PATCH 12/39] fixed id of serialized dynamic array (#112) --- CHANGELOG.md | 1 + Content/Types/FormSelect.php | 5 ++-- Entity/Form.php | 3 ++- Event/DynFormSavedEvent.php | 40 +++++++++++++++++++++++++++---- Event/MailchimpListSubscriber.php | 2 +- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index daed8bf..4c28567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #112 Fixed id of serialized dynamic array - BUGFIX #106 Fixed datefield and add birthday option - ENHANCEMENT #105 Added new form layout - FEATURE #102 Added recaptcha support with EWZRecaptchaBundle diff --git a/Content/Types/FormSelect.php b/Content/Types/FormSelect.php index 2b1965c..59d63e2 100644 --- a/Content/Types/FormSelect.php +++ b/Content/Types/FormSelect.php @@ -149,7 +149,8 @@ public function getContentData(PropertyInterface $property) $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $serializedObject = $formEntity->serializeForLocale($locale, $form->getData()); + $dynamic = $form->getData(); + $serializedObject = $formEntity->serializeForLocale($locale, $dynamic); // save $this->formHandler->handle( @@ -160,7 +161,7 @@ public function getContentData(PropertyInterface $property) ] ); - $event = new DynFormSavedEvent($serializedObject); + $event = new DynFormSavedEvent($serializedObject, $dynamic); $this->eventDispatcher->dispatch(DynFormSavedEvent::NAME, $event); // Do redirect after success diff --git a/Entity/Form.php b/Entity/Form.php index cefa6b0..3186f04 100644 --- a/Entity/Form.php +++ b/Entity/Form.php @@ -212,7 +212,8 @@ public function serializeForLocale($locale, Dynamic $dynamic = null) $translation = $this->getTranslation($locale, false, true); return [ - 'id' => $this->getId(), + 'id' => $dynamic ? $dynamic->id : null, + 'formId' => $this->getId(), 'title' => $translation->getTitle(), 'subject' => $translation->getSubject(), 'mailText' => $translation->getMailText(), diff --git a/Event/DynFormSavedEvent.php b/Event/DynFormSavedEvent.php index 557e33e..93c51cf 100644 --- a/Event/DynFormSavedEvent.php +++ b/Event/DynFormSavedEvent.php @@ -2,6 +2,7 @@ namespace L91\Sulu\Bundle\FormBundle\Event; +use L91\Sulu\Bundle\FormBundle\Entity\Dynamic; use Symfony\Component\EventDispatcher\Event; class DynFormSavedEvent extends Event @@ -11,25 +12,54 @@ class DynFormSavedEvent extends Event /** * @var array */ - protected $formSelect; + protected $data; + + /** + * @var Dynamic + */ + protected $dynamic; /** * DynFormSavedEvent constructor. * - * @param $formSelect + * @param array $data + * @param Dynamic $dynamic will be required in the future */ - public function __construct($formSelect) + public function __construct($data, $dynamic = null) { - $this->formSelect = $formSelect; + $this->data = $data; + $this->dynamic = $dynamic; } /** * Get FormSelect. * + * @deprecated use the getData function + * * @return array */ public function getFormSelect() { - return $this->formSelect; + return $this->data; + } + + /** + * Get data. + * + * @return array + */ + public function getData() + { + return $this->data; + } + + /** + * Get dynamic. + * + * @return Dynamic|null + */ + public function getDynamic() + { + return $this->dynamic; } } diff --git a/Event/MailchimpListSubscriber.php b/Event/MailchimpListSubscriber.php index 5c4b474..29fc535 100644 --- a/Event/MailchimpListSubscriber.php +++ b/Event/MailchimpListSubscriber.php @@ -37,7 +37,7 @@ public static function getSubscribedEvents() */ public function listSubscribe(DynFormSavedEvent $event) { - $form = $event->getFormSelect(); + $form = $event->getData(); $email = ''; $fname = ''; $lname = ''; From 733ab3ace2947a937ca59f03bcac721adfaf8420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Kh=C3=BCny?= Date: Thu, 3 Nov 2016 14:33:22 +0100 Subject: [PATCH 13/39] Bugfix/mailchimp parameter (#113) * Changed Parameter name and fixed reading * Changelog * Fixed docu code --- CHANGELOG.md | 1 + Controller/FormController.php | 2 +- DependencyInjection/L91SuluFormExtension.php | 3 +-- Resources/doc/dynamic.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c28567..77af081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #113 Fixed naming of mailchimp parameters - BUGFIX #112 Fixed id of serialized dynamic array - BUGFIX #106 Fixed datefield and add birthday option - ENHANCEMENT #105 Added new form layout diff --git a/Controller/FormController.php b/Controller/FormController.php index 7eeb7df..6323f04 100644 --- a/Controller/FormController.php +++ b/Controller/FormController.php @@ -218,7 +218,7 @@ public function cgetTemplateAction(Request $request) public function getMailChimpLists() { $lists = []; - $apiKey = $this->getParameter('l91_sulu_form.mailchimp_api_key'); + $apiKey = $this->getParameter('l91.sulu.form.mailchimp_api_key'); // if mailchimp class doesn't exist or no key is set return empty list if (!class_exists(\DrewM\MailChimp\MailChimp::class) || !$apiKey) { diff --git a/DependencyInjection/L91SuluFormExtension.php b/DependencyInjection/L91SuluFormExtension.php index e28b84c..793281d 100644 --- a/DependencyInjection/L91SuluFormExtension.php +++ b/DependencyInjection/L91SuluFormExtension.php @@ -50,8 +50,7 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('l91.sulu.form.mail.from', $config['mail_helper']['from']); $container->setParameter('l91.sulu.form.mail.to', $config['mail_helper']['to']); $container->setParameter('l91.sulu.form.ajax_templates', $config['ajax_templates']); - - $container->setParameter('l91_sulu_form.mailchimp_api_key', $config['mailchimp_api_key']); + $container->setParameter('l91.sulu.form.mailchimp_api_key', $config['mailchimp_api_key']); $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.xml'); diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index 1081a80..2734043 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -75,7 +75,7 @@ https://github.com/symfony/symfony/blob/v2.7.0/src/Symfony/Bridge/Twig/Resources
{% elseif attr.type|default('') == 'headline' %}
-

{{ label }}

+

{{ label }}

{% else %} {{ form_widget(form) }} From 8209d66e7ecd7222af84f14c020df6bc60cb4df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Kh=C3=BCny?= Date: Tue, 8 Nov 2016 13:57:09 +0100 Subject: [PATCH 14/39] Multiple Choices can be more then string max length (#114) * Multiple Checkboxes can be more then string max length --- CHANGELOG.md | 1 + Resources/config/doctrine/Dynamic.orm.xml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77af081..0fd72e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #114 Fixed multiple choices to text type columns - BUGFIX #113 Fixed naming of mailchimp parameters - BUGFIX #112 Fixed id of serialized dynamic array - BUGFIX #106 Fixed datefield and add birthday option diff --git a/Resources/config/doctrine/Dynamic.orm.xml b/Resources/config/doctrine/Dynamic.orm.xml index 89bc637..9c255f0 100644 --- a/Resources/config/doctrine/Dynamic.orm.xml +++ b/Resources/config/doctrine/Dynamic.orm.xml @@ -30,9 +30,9 @@ - + - + From 013f6b0e901ce725ca2f832a9621e4da78281ec0 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Tue, 8 Nov 2016 17:09:08 +0100 Subject: [PATCH 15/39] added options for attachment validation --- CHANGELOG.md | 1 + Form/Type/DynamicFormType.php | 46 +++++++++++++++ Resources/translations/sulu/backend.de.xlf | 27 +++++++++ Resources/translations/sulu/backend.en.xlf | 27 +++++++++ Resources/translations/sulu/backend.fr.xlf | 27 +++++++++ .../forms/fields/types/attachment.html.twig | 59 +++++++++++++++++++ .../views/forms/fields/types/date.html.twig | 6 +- 7 files changed, 191 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd72e7..66f64c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - FEATURE #115 Added options for attachment validation - BUGFIX #114 Fixed multiple choices to text type columns - BUGFIX #113 Fixed naming of mailchimp parameters - BUGFIX #112 Fixed id of serialized dynamic array diff --git a/Form/Type/DynamicFormType.php b/Form/Type/DynamicFormType.php index 8b0febc..a25c356 100644 --- a/Form/Type/DynamicFormType.php +++ b/Form/Type/DynamicFormType.php @@ -18,6 +18,11 @@ use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Validator\Constraints\All; +use Symfony\Component\Validator\Constraints\Count; +use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\Constraints\File; +use Symfony\Component\Validator\Constraints\Image; use Symfony\Component\Validator\Constraints\NotBlank; class DynamicFormType extends AbstractType @@ -141,6 +146,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) break; case Dynamic::TYPE_EMAIL: $type = EmailType::class; + $options['constraints'][] = new Email(); break; case Dynamic::TYPE_DATE: $type = DateType::class; @@ -153,6 +159,46 @@ public function buildForm(FormBuilderInterface $builder, array $options) case Dynamic::TYPE_ATTACHMENT: $type = FileType::class; $options['mapped'] = false; + $allConstraints = []; + + // Mime Types Filter + if ($translation->getOption('type') === ['image']) { + $fileConstraint = new Image(); + } else { + $mimeTypes = []; + + if (is_array($translation->getOption('type'))) { + foreach ($translation->getOption('type') as $attachmentType) { + $mimeTypes[] = $attachmentType . '/*'; + } + } + + $fileConstraint = new File([ + 'mimeTypes' => $mimeTypes, + ]); + + $options['attr']['accept'] = implode(',', $mimeTypes); + } + + $allConstraints[] = $fileConstraint; + + // Required for Files + if ($field->getRequired()) { + $allConstraints[] = new NotBlank(); + } + + // File Constraint + $options['constraints'][] = new All([ + 'constraints' => $allConstraints, + ]); + + // Max File Constraint + if ($translation->getOption('max')) { + $options['constraints'][] = new Count([ + 'max' => (int) $translation->getOption('max'), + ]); + } + $options['multiple'] = true; break; case Dynamic::TYPE_CHECKBOX: diff --git a/Resources/translations/sulu/backend.de.xlf b/Resources/translations/sulu/backend.de.xlf index 8379040..ffe315b 100644 --- a/Resources/translations/sulu/backend.de.xlf +++ b/Resources/translations/sulu/backend.de.xlf @@ -257,6 +257,33 @@ l91_sulu_form.width.five-sixths Fünf Sechstel + + + + l91_sulu_form.attachment_restrict + Dateitypen beschränken + + + l91_sulu_form.attachment_restrict.hint + Bei keiner Auswahl sind alle Dateitypen möglich. + + + l91_sulu_form.attachment.image + Bilder + + + l91_sulu_form.attachment.audio + Audios + + + l91_sulu_form.attachment.video + Videos + + + + l91_sulu_form.attachment_max + Maximale Anzahl + diff --git a/Resources/translations/sulu/backend.en.xlf b/Resources/translations/sulu/backend.en.xlf index d37e49f..5609796 100644 --- a/Resources/translations/sulu/backend.en.xlf +++ b/Resources/translations/sulu/backend.en.xlf @@ -257,6 +257,33 @@ l91_sulu_form.width.five-sixths five sixths + + + + l91_sulu_form.attachment_restrict + Restrict file types + + + l91_sulu_form.attachment_restrict.hint + No choice will allow all file types. + + + l91_sulu_form.attachment.image + Images + + + l91_sulu_form.attachment.audio + Audio + + + l91_sulu_form.attachment.video + Videos + + + + l91_sulu_form.attachment_max + Maximale amount + diff --git a/Resources/translations/sulu/backend.fr.xlf b/Resources/translations/sulu/backend.fr.xlf index 9ad08ed..2d40353 100644 --- a/Resources/translations/sulu/backend.fr.xlf +++ b/Resources/translations/sulu/backend.fr.xlf @@ -256,6 +256,33 @@ l91_sulu_form.width.five-sixths cinq sixièmes + + + + l91_sulu_form.attachment_restrict + Restrict file types + + + l91_sulu_form.attachment_restrict.hint + No choice will allow all file types. + + + l91_sulu_form.attachment.image + Images + + + l91_sulu_form.attachment.audio + Audio + + + l91_sulu_form.attachment.video + Videos + + + + l91_sulu_form.attachment_max + Maximale amount + diff --git a/Resources/views/forms/fields/types/attachment.html.twig b/Resources/views/forms/fields/types/attachment.html.twig index 5cba4f0..97d1404 100644 --- a/Resources/views/forms/fields/types/attachment.html.twig +++ b/Resources/views/forms/fields/types/attachment.html.twig @@ -4,4 +4,63 @@ {% endblock %} {% block extended %} +
+
+
+ + + {% set types = [ + 'image', + 'audio', + 'video', + ] %} + +
+ {% for type in types %} + + {% endfor %} +
+ +
+ +
+ <%= translate('l91_sulu_form.attachment_restrict.hint') %> +
+
+ +
+ + + + +
+
+
+
{% endblock %} diff --git a/Resources/views/forms/fields/types/date.html.twig b/Resources/views/forms/fields/types/date.html.twig index ef5da63..3c0f0b7 100644 --- a/Resources/views/forms/fields/types/date.html.twig +++ b/Resources/views/forms/fields/types/date.html.twig @@ -22,11 +22,11 @@
-
{% endblock %} From 36e965dd4c3d2d7237def558b9e834079eb2e60c Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 9 Nov 2016 16:29:20 +0100 Subject: [PATCH 16/39] add max files and accept mimetypes to frontend attributes --- Form/Type/DynamicFormType.php | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Form/Type/DynamicFormType.php b/Form/Type/DynamicFormType.php index a25c356..4be85ab 100644 --- a/Form/Type/DynamicFormType.php +++ b/Form/Type/DynamicFormType.php @@ -162,22 +162,23 @@ public function buildForm(FormBuilderInterface $builder, array $options) $allConstraints = []; // Mime Types Filter - if ($translation->getOption('type') === ['image']) { - $fileConstraint = new Image(); - } else { - $mimeTypes = []; + $mimeTypes = []; - if (is_array($translation->getOption('type'))) { - foreach ($translation->getOption('type') as $attachmentType) { - $mimeTypes[] = $attachmentType . '/*'; - } + if (is_array($translation->getOption('type'))) { + foreach ($translation->getOption('type') as $attachmentType) { + $mimeTypes[] = $attachmentType . '/*'; } + } + + $options['attr']['accept'] = implode(',', $mimeTypes); + // File Constraint + if ($translation->getOption('type') === ['image']) { + $fileConstraint = new Image(); + } else { $fileConstraint = new File([ 'mimeTypes' => $mimeTypes, ]); - - $options['attr']['accept'] = implode(',', $mimeTypes); } $allConstraints[] = $fileConstraint; @@ -193,10 +194,12 @@ public function buildForm(FormBuilderInterface $builder, array $options) ]); // Max File Constraint - if ($translation->getOption('max')) { + if ($fileMax = (int) $translation->getOption('max')) { $options['constraints'][] = new Count([ - 'max' => (int) $translation->getOption('max'), + 'max' => $fileMax, ]); + + $options['attr']['max'] = $fileMax; } $options['multiple'] = true; From 80caf36041f44c788525dbc1b6145e5ad23c67e8 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 9 Nov 2016 18:53:48 +0100 Subject: [PATCH 17/39] add dropzone tutorial documentation --- README.md | 1 + Resources/doc/dropzone.md | 225 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 Resources/doc/dropzone.md diff --git a/README.md b/README.md index ca17928..1bdbf22 100644 --- a/README.md +++ b/README.md @@ -81,3 +81,4 @@ Make sure you've set the correct permissions in the Sulu backend for this bundle - [Mailchimp](Resources/doc/mailchimp.md "Mailchimp Form Field") - [Recaptcha](Resources/doc/recaptcha.md "Recaptcha Form Field") +- [Dropzone](Resources/doc/dropzone.md "Dropzone Form Field") diff --git a/Resources/doc/dropzone.md b/Resources/doc/dropzone.md new file mode 100644 index 0000000..57e216a --- /dev/null +++ b/Resources/doc/dropzone.md @@ -0,0 +1,225 @@ +# Dropzone + +## 1. The Form Theme + +To use a dropzone in forms you need edit your form theme + +```twig +{%- block form_start -%} + {# Form need an id to access the element over js #} + {% set attr = attr|merge({ id: 'dynamic-form' }) %} + + {{ parent() }} +{%- endblock form_start -%} + +{%- block file_widget -%} + {# Dropzone #} +
+
+ +
+
+{%- endblock -%} +``` + +## 2. Form submit handling with multiple dropzones + +The following JS will show you how you can submit a form +over multiple dropzones: + +```js +var component = function() { + return { + $el: $('#dynamic-form'), + dropzones: [], + + /** + * @method initialize + */ + initialize: function() { + this.initializeDropzones(); + this.$el.submit(this.submit.bind(this)); + + return true; + }, + + /** + * @method submit + */ + submit: function(event) { + if (!this.hasFiles()) { + // default form submit + return true; + } + + // submit over dropzone + event.preventDefault(); + this.dropzones[0].processQueue(); + + return false; + }, + + /** + * @method initializeDropzone + */ + initializeDropzones: function() { + var dropzones = []; + + Dropzone.autoDiscover = false; + + // create dropzones + this.$el.find('.upload-files').each(function(index, el) { + var $dropzone = $(el); + + // need to slice [] because its added by dropzone + var paramName = $dropzone.data('name'); + paramName = paramName.substr(0, paramName.length - 2); + + // add new dropzone + dropzones.push( + this.createDropzone( + $dropzone.attr('id'), + paramName, + $dropzone.data('max'), + $dropzone.data('accept') + ) + ); + }.bind(this)); + + this.dropzones = dropzones; + }, + + /** + * @method destroyDropzones + */ + destroyDropzones: function() { + for (var i = 0, length = this.dropzones.length; i < length; i++) { + this.dropzones[i].destroy(); + } + }, + + /** + * @method hasFiles + */ + hasFiles: function() { + // has dropzones + if (!this.dropzones.length) { + return false; + } + + // has files in dropzone + for (var i = 0, length = this.dropzones.length; i < length; i++) { + if (this.dropzones[i].getQueuedFiles().length) { + return true; + } + } + }, + + /** + * @method createDropzone + */ + createDropzone: function(id, paramName, maxFiles, accept) { + var self = this; + + // get form action url + var url = this.$el.attr('action'); + if (!url) { + url = window.location.href; + } + + // create new dropzone + return new Dropzone('#' + id, { + paramName: paramName, + url: url, + autoProcessQueue: false, + uploadMultiple: true, + parallelUploads: maxFiles, + maxFiles: maxFiles, + maxFilesize: 1, // max 1 MB + acceptedFiles: accept, + clickable: ['#' + id], + previewTemplate: [ + '
', + ' ', + ' ', + ' ', + ' ', + '
', + '
' + ].join(''), + init: function() { + this.on('sendingmultiple', self.sendingDropzone.bind(self)); + this.on('successmultiple', self.successDropzone.bind(self)); + this.on('errormultiple', self.errorDropzone.bind(self)); + } + }) + }, + + /** + * @method createDropzone + */ + sendingDropzone: function(data, xhr, formData) { + // disable all submit buttons in form + this.$el.find('[type=submit]').prop('disabled', true); + + // add fields to form data + $.each(this.$el.serializeArray(), function(index, item) { + formData.append(item.name, item.value); + }); + + // add other dropzone files + for (var i = 1, length = this.dropzones.length; i < length; i++) { + var files = this.dropzones[i].getQueuedFiles(); + + for (var x = 0, fileLength = files.length; x < fileLength; x++) { + formData.append( + this.dropzones[i]._getParamName(x), + files[x], + files[x].name + ); + } + } + }, + + /** + * @method successDropzone + */ + successDropzone: function(file, response) { + var $newForm = $(response).find('#' + this.id); + + // on success no form is displayed we can redirect to + if (!$newForm.length) { + window.location.href = '?send=true'; + + return; + } + + // on error destroy dropzones + this.destroyDropzones(); + + // replace form with + this.$el.html($newForm.html()); + + // reinitilize dropzones + this.initializeDropzones(); + + // scroll to first error here + // initialize other js libraries + }, + + /** + * @method errorDropzone + */ + errorDropzone: function() { + // enable submit buttons + this.$el.find('[type=submit]').prop('disabled', false); + } + }; +}(); + +component.initialize(); +``` From 827f78be02ad865ae61104d6249f0d04b28e12f0 Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 10 Nov 2016 13:04:59 +0100 Subject: [PATCH 18/39] added dropzone requirements in documentation --- Resources/doc/dropzone.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Resources/doc/dropzone.md b/Resources/doc/dropzone.md index 57e216a..0a72e5b 100644 --- a/Resources/doc/dropzone.md +++ b/Resources/doc/dropzone.md @@ -32,6 +32,9 @@ The following JS will show you how you can submit a form over multiple dropzones: ```js +var $ = require('jquery'); +var Dropzone = require('dropzone'); + var component = function() { return { $el: $('#dynamic-form'), From 11bda63ea3664c5571a9f1aee790c23853eca1cd Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 10 Nov 2016 14:36:35 +0100 Subject: [PATCH 19/39] fix limitation of content type select (#117) --- CHANGELOG.md | 1 + .../views/Template/content-types/form_select_simple.html.twig | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66f64c8..0cdea52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #117 Fixed limitation of content type select - FEATURE #115 Added options for attachment validation - BUGFIX #114 Fixed multiple choices to text type columns - BUGFIX #113 Fixed naming of mailchimp parameters diff --git a/Resources/views/Template/content-types/form_select_simple.html.twig b/Resources/views/Template/content-types/form_select_simple.html.twig index 14137e7..b28b417 100644 --- a/Resources/views/Template/content-types/form_select_simple.html.twig +++ b/Resources/views/Template/content-types/form_select_simple.html.twig @@ -2,7 +2,7 @@ class="preview-update trigger-save-button" data-form="true" data-property='{{ property|json_encode }}' - data-aura-url="/admin/api/l91/forms?flat=true&fields=id,title&sortBy=title&locale={{ languageCode }}" + data-aura-url="/admin/api/l91/forms?flat=true&fields=id,title&sortBy=title&limit=999&locale={{ languageCode }}" data-aura-result-key="forms" data-aura-component="select@husky" data-aura-instance-name="{{ id|raw }}" @@ -15,4 +15,4 @@ data-aura-pre-selected-elements="[]" data-mapper-property="{{ property.name }}" data-aura-height="200"> -
\ No newline at end of file +
From c16a04b15fe320c039064de05ddaef9d087dbc6f Mon Sep 17 00:00:00 2001 From: L91 Date: Fri, 18 Nov 2016 09:43:57 +0100 Subject: [PATCH 20/39] Fixed permission problem on false locale (#120) --- CHANGELOG.md | 1 + Resources/public/dist/main.js | 2 +- Resources/public/js/main.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cdea52..8e82ad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## dev-develop + - BUGFIX #120 Fixed permission problem on false locale - BUGFIX #117 Fixed limitation of content type select - FEATURE #115 Added options for attachment validation - BUGFIX #114 Fixed multiple choices to text type columns diff --git a/Resources/public/dist/main.js b/Resources/public/dist/main.js index 2269176..d725d5d 100644 --- a/Resources/public/dist/main.js +++ b/Resources/public/dist/main.js @@ -1 +1 @@ -require.config({paths:{l91suluform:"../../l91suluform/dist",l91suluformcss:"../../l91suluform/css","type/formSelect":"../../l91suluform/dist/validation/types/formSelect","type/select-type-custom":"../../l91suluform/dist/validation/types/select-type-custom"}}),define(["css!l91suluformcss/main"],function(){return{name:"L91SuluFormBundle",initialize:function(a){"use strict";function b(){return c.sulu.getUserSetting("contentLanguage")||c.sulu.user.locale}var c=a.sandbox;a.components.addSource("l91suluform","/bundles/l91suluform/dist/components"),c.mvc.routes.push({route:"l91/forms",callback:function(){var a=b();c.emit("sulu.router.navigate","l91/forms/"+a)}}),c.mvc.routes.push({route:"l91/forms/:language",callback:function(a){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/add/:content",callback:function(a,b){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/edit::id/:content",callback:function(a,b,c){return'
'}})}}}); \ No newline at end of file +require.config({paths:{l91suluform:"../../l91suluform/dist",l91suluformcss:"../../l91suluform/css","type/formSelect":"../../l91suluform/dist/validation/types/formSelect","type/select-type-custom":"../../l91suluform/dist/validation/types/select-type-custom"}}),define(["css!l91suluformcss/main"],function(){return{name:"L91SuluFormBundle",initialize:function(a){"use strict";function b(){return c.sulu.getUserSetting("contentLanguage")||c.sulu.getDefaultContentLocale()}var c=a.sandbox;a.components.addSource("l91suluform","/bundles/l91suluform/dist/components"),c.mvc.routes.push({route:"l91/forms",callback:function(){var a=b();c.emit("sulu.router.navigate","l91/forms/"+a)}}),c.mvc.routes.push({route:"l91/forms/:language",callback:function(a){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/add/:content",callback:function(a,b){return'
'}}),c.mvc.routes.push({route:"l91/forms/:language/edit::id/:content",callback:function(a,b,c){return'
'}})}}}); \ No newline at end of file diff --git a/Resources/public/js/main.js b/Resources/public/js/main.js index 0ea1b98..65d88b2 100644 --- a/Resources/public/js/main.js +++ b/Resources/public/js/main.js @@ -24,7 +24,7 @@ define(['css!l91suluformcss/main'], function() { function getContentLanguage() { // FIXME do not use user locale as default use default language of system instead - return sandbox.sulu.getUserSetting('contentLanguage') || sandbox.sulu.user.locale; + return sandbox.sulu.getUserSetting('contentLanguage') || sandbox.sulu.getDefaultContentLocale(); } // no language redirect: Generated by https://github.com/alexander-schranz/sulu-backend-bundle. From e2eb895fc2bcb736ddd6fda93bff090eef96a668 Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 24 Nov 2016 13:03:47 +0100 Subject: [PATCH 21/39] added dynamic form list and export (#121) --- Admin/DynamicListNavigationProvider.php | 58 +++++++ CHANGELOG.md | 2 + Controller/DynamicController.php | 121 +++++++++++++ .../DynamicListBuilderCompilerPass.php | 35 ++++ DependencyInjection/Configuration.php | 8 + DependencyInjection/L91SuluFormExtension.php | 13 ++ Entity/Dynamic.php | 112 ++++++++++-- Entity/Form.php | 56 +++++- L91SuluFormBundle.php | 2 + ListBuilder/DynamicListBuilder.php | 162 ++++++++++++++++++ ListBuilder/DynamicListBuilderInterface.php | 30 ++++ ListBuilder/DynamicListFactory.php | 120 +++++++++++++ ListBuilder/DynamicListFactoryInterface.php | 50 ++++++ Provider/DynamicProvider.php | 5 + Repository/DynamicRepository.php | 12 ++ Resources/config/doctrine/Dynamic.orm.xml | 3 +- Resources/config/routing_api.yml | 6 + Resources/config/services.xml | 91 ++++++---- Resources/doc/dynamic.md | 9 +- .../dist/components/dynamics/list/main.js | 1 + .../js/components/dynamics/list/main.js | 125 ++++++++++++++ 21 files changed, 971 insertions(+), 50 deletions(-) create mode 100644 Admin/DynamicListNavigationProvider.php create mode 100644 Controller/DynamicController.php create mode 100644 DependencyInjection/CompilerPass/DynamicListBuilderCompilerPass.php create mode 100644 ListBuilder/DynamicListBuilder.php create mode 100644 ListBuilder/DynamicListBuilderInterface.php create mode 100644 ListBuilder/DynamicListFactory.php create mode 100644 ListBuilder/DynamicListFactoryInterface.php create mode 100644 Repository/DynamicRepository.php create mode 100644 Resources/public/dist/components/dynamics/list/main.js create mode 100644 Resources/public/js/components/dynamics/list/main.js diff --git a/Admin/DynamicListNavigationProvider.php b/Admin/DynamicListNavigationProvider.php new file mode 100644 index 0000000..b2b621b --- /dev/null +++ b/Admin/DynamicListNavigationProvider.php @@ -0,0 +1,58 @@ +config = $config; + } + + /** + * {@inheritdoc} + */ + public function getNavigationItems(array $options = []) + { + $items = []; + + foreach ($this->config as $templateKey => $config) { + $item = new ContentNavigationItem('Formular'); + $item->setAction('form-list'); + $item->setDisplay(['edit']); + $item->setComponent('dynamics/list@l91suluform'); + $item->setComponentOptions([ + 'template' => $templateKey, + 'property' => $config['property'], + 'view' => isset($config['view']) ? $config['view'] : 'default', + ]); + + $item->setDisplayConditions( + [ + new DisplayCondition('template', DisplayCondition::OPERATOR_EQUAL, $templateKey), + ] + ); + + $items[] = $item; + } + + return $items; + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e82ad8..d003678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## dev-develop + + - FEATURE #121 Added dynamic form list and export - BUGFIX #120 Fixed permission problem on false locale - BUGFIX #117 Fixed limitation of content type select - FEATURE #115 Added options for attachment validation diff --git a/Controller/DynamicController.php b/Controller/DynamicController.php new file mode 100644 index 0000000..adbfd72 --- /dev/null +++ b/Controller/DynamicController.php @@ -0,0 +1,121 @@ +get('l91_sulu_form.repository.dynamic'); + + $filters = $this->getFilters($request); + $page = $request->get('page', 1); + $limit = $request->get('limit'); + $offset = (($page - 1) * $limit); + $view = $request->get('view', 'default'); + $sortOrder = $request->get('sortOrder', 'asc'); + $sortBy = $request->get('sortBy', 'created'); + + $entries = $repository->findBy( + $filters, + [$sortBy => $sortOrder], + $limit, + $offset + ); + + $entries = $this->get('l91_sulu_form.list_builder.dynamic_list_factory')->build($entries, $view); + + // avoid total request when entries < limit + if (count($entries) == $limit) { + $total = count($repository->findBy($filters)); + } else { + // calculate total + $total = count($entries) + $offset; + } + + // create list representation + $representation = new ListRepresentation( + $entries, + 'dynamics', + $request->get('_route'), + $request->query->all(), + $page, + $limit, + $total + ); + + return $this->handleView($this->view($representation)); + } + + /** + * Returns the fields for a dynamic form. + * + * @param Request $request + * + * @return Response + */ + public function cgetFieldsAction(Request $request) + { + $form = $this->loadForm($request); + $locale = $request->getLocale(); + + $fieldDescriptors = $this->get('l91_sulu_form.list_builder.dynamic_list_factory') + ->getFieldDescriptors($form, $locale); + + return $this->handleView($this->view(array_values($fieldDescriptors))); + } + + /** + * Get filters. + * + * @param Request $request + * + * @return array + */ + protected function getFilters(Request $request) + { + $filters = [ + 'uuid' => $request->get('uuid'), + 'webspaceKey' => $request->get('webspaceKey'), + 'form' => $request->get('form'), + ]; + + return $filters; + } + + /** + * Get form. + * + * @param Request $request + * + * @return Form + */ + protected function loadForm(Request $request) + { + $formId = (int) $request->get('form'); + + if (!$formId) { + throw new BadRequestHttpException('"form" is required parameter'); + } + + return $this->get('l91_sulu_form.repository.form')->findById($formId); + } +} diff --git a/DependencyInjection/CompilerPass/DynamicListBuilderCompilerPass.php b/DependencyInjection/CompilerPass/DynamicListBuilderCompilerPass.php new file mode 100644 index 0000000..e00e712 --- /dev/null +++ b/DependencyInjection/CompilerPass/DynamicListBuilderCompilerPass.php @@ -0,0 +1,35 @@ +hasDefinition('l91_sulu_form.list_builder.dynamic_list_factory')) { + return; + } + + $definition = $container->getDefinition('l91_sulu_form.list_builder.dynamic_list_factory'); + $taggedServices = $container->findTaggedServiceIds('l91_sulu_form.dynamic_list_builder'); + + foreach ($taggedServices as $id => $tags) { + foreach ($tags as $attributes) { + $definition->addMethodCall( + 'add', + [new Reference($id), $attributes['alias']] + ); + } + } + } +} diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index b4e110d..8d65d70 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -28,6 +28,14 @@ public function getConfigTreeBuilder() ->scalarNode('to')->end() ->end() ->end() + ->arrayNode('dynamic_list_builder') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('default')->defaultValue('simple')->end() + ->scalarNode('delimiter')->defaultValue(PHP_EOL)->end() + ->end() + ->end() + ->variableNode('content_dynamic_lists')->defaultValue([])->end() ->arrayNode('ajax_templates') ->prototype('scalar')->end()->defaultValue([]) ->end() diff --git a/DependencyInjection/L91SuluFormExtension.php b/DependencyInjection/L91SuluFormExtension.php index 793281d..5c164e7 100644 --- a/DependencyInjection/L91SuluFormExtension.php +++ b/DependencyInjection/L91SuluFormExtension.php @@ -51,7 +51,20 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('l91.sulu.form.mail.to', $config['mail_helper']['to']); $container->setParameter('l91.sulu.form.ajax_templates', $config['ajax_templates']); $container->setParameter('l91.sulu.form.mailchimp_api_key', $config['mailchimp_api_key']); + $container->setParameter('l91.sulu.form.content_dynamic_list_config', $config['content_dynamic_lists']); + // Dynamic List Builder + $container->setParameter( + 'l91.sulu.form.dynamic_list_builder.default', + $config['dynamic_list_builder']['default'] + ); + + $container->setParameter( + 'l91.sulu.form.dynamic_list_builder.delimiter', + $config['dynamic_list_builder']['delimiter'] + ); + + // Load services $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.xml'); diff --git a/Entity/Dynamic.php b/Entity/Dynamic.php index 832d171..0ab2274 100644 --- a/Entity/Dynamic.php +++ b/Entity/Dynamic.php @@ -223,6 +223,16 @@ class Dynamic implements TimestampableInterface self::TYPE_RADIO_BUTTONS, ]; + /** + * @var array + */ + public static $HIDDEN_TYPES = [ + self::TYPE_SPACER, + self::TYPE_FREE_TEXT, + self::TYPE_HEADLINE, + self::TYPE_RECAPTCHA, + ]; + /** * @param string $uuid * @param string $locale @@ -292,38 +302,112 @@ public function __isset($name) */ public function __get($name) { - if (property_exists($this, $name)) { - if (in_array($name, [self::TYPE_CHECKBOX_MULTIPLE, self::TYPE_DROPDOWN_MULTIPLE, self::TYPE_ATTACHMENT])) { - return json_decode($this->$name, true); + return $this->getField($name); + } + + /** + * {@inheritdoc} + */ + public function getCreated() + { + return $this->created; + } + + /** + * {@inheritdoc} + */ + public function getChanged() + { + return $this->changed; + } + + /** + * Get id. + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Get form. + * + * @return Form + */ + public function getForm() + { + return $this->form; + } + + /** + * Get field. + * + * @param string $key + * + * @return string|array + */ + public function getField($key) + { + if (property_exists($this, $key)) { + if (in_array($key, [self::TYPE_CHECKBOX_MULTIPLE, self::TYPE_DROPDOWN_MULTIPLE, self::TYPE_ATTACHMENT])) { + return json_decode($this->$key, true); } - return $this->$name; + return $this->$key; } $array = $this->getData(); - if (isset($array[$name])) { - if (strpos($name, 'date') === 0) { - return new \DateTime($array[$name]); + if (isset($array[$key])) { + if (strpos($key, 'date') === 0) { + return new \DateTime($array[$key]); } - return $array[$name]; + return $array[$key]; } } /** - * {@inheritdoc} + * Get fields. + * + * @param bool $hideHidden + * + * @return array */ - public function getCreated() + public function getFields($hideHidden = false) { - return $this->created; + $entry = []; + + if (!$this->form) { + return []; + } + + foreach ($this->form->getFields() as $field) { + if ($hideHidden && in_array($field->getType(), self::$HIDDEN_TYPES)) { + continue; + } + + $entry[$field->getKey()] = $this->getField($field->getKey()); + } + + return $entry; } /** - * {@inheritdoc} + * Get type. + * + * @param string $key + * + * @return string */ - public function getChanged() + public function getType($key) { - return $this->changed; + if (!$this->form) { + return; + } + + return $this->form->getFieldType($key); } } diff --git a/Entity/Form.php b/Entity/Form.php index 3186f04..4b5d5a5 100644 --- a/Entity/Form.php +++ b/Entity/Form.php @@ -36,6 +36,8 @@ public function __construct() } /** + * Get id. + * * @return int */ public function getId() @@ -44,6 +46,8 @@ public function getId() } /** + * Get default locale. + * * @return string */ public function getDefaultLocale() @@ -52,17 +56,25 @@ public function getDefaultLocale() } /** - * @param string $defaultLocale + * Set default locale. + * + * @param $defaultLocale + * + * @return $this */ public function setDefaultLocale($defaultLocale) { $this->defaultLocale = $defaultLocale; + + return $this; } /** + * Add translation. + * * @param FormTranslation $translation * - * @return Form + * @return $this */ public function addTranslation(FormTranslation $translation) { @@ -72,14 +84,22 @@ public function addTranslation(FormTranslation $translation) } /** + * Remove translation. + * * @param FormTranslation $translation + * + * @return $this */ public function removeTranslation(FormTranslation $translation) { $this->translations->removeElement($translation); + + return $this; } /** + * Get translations. + * * @return \Doctrine\Common\Collections\Collection|FormTranslation[] */ public function getTranslations() @@ -88,6 +108,8 @@ public function getTranslations() } /** + * Get translation. + * * @param string $locale * @param bool $create * @param bool $fallback @@ -117,6 +139,8 @@ public function getTranslation($locale, $create = false, $fallback = false) } /** + * Add field. + * * @param FormField $field * * @return Form @@ -129,11 +153,17 @@ public function addField(FormField $field) } /** + * Remove field. + * * @param FormField $field + * + * @return $this */ public function removeField(FormField $field) { $this->fields->removeElement($field); + + return $this; } /** @@ -145,6 +175,8 @@ public function getFields() } /** + * Get field by key. + * * @param string $key * * @return FormField|null @@ -159,6 +191,26 @@ public function getField($key) } /** + * Get field type by key. + * + * @param string $key + * + * @return string|void + */ + public function getFieldType($key) + { + $field = $this->getField($key); + + if (!$field) { + return; + } + + return $field->getType(); + } + + /** + * Get fields not in array. + * * @param $keys * * @return FormField[] diff --git a/L91SuluFormBundle.php b/L91SuluFormBundle.php index eaa18f1..ea4e603 100644 --- a/L91SuluFormBundle.php +++ b/L91SuluFormBundle.php @@ -2,6 +2,7 @@ namespace L91\Sulu\Bundle\FormBundle; +use L91\Sulu\Bundle\FormBundle\DependencyInjection\CompilerPass\DynamicListBuilderCompilerPass; use L91\Sulu\Bundle\FormBundle\DependencyInjection\CompilerPass\ListProviderCompilerPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -13,5 +14,6 @@ public function build(ContainerBuilder $container) parent::build($container); $container->addCompilerPass(new ListProviderCompilerPass()); + $container->addCompilerPass(new DynamicListBuilderCompilerPass()); } } diff --git a/ListBuilder/DynamicListBuilder.php b/ListBuilder/DynamicListBuilder.php new file mode 100644 index 0000000..24b0c22 --- /dev/null +++ b/ListBuilder/DynamicListBuilder.php @@ -0,0 +1,162 @@ +delimiter = $delimiter; + $this->router = $router; + } + + /** + * @param Dynamic $dynamic + * @param $locale + * + * @return array + */ + public function build(Dynamic $dynamic, $locale) + { + $entry = $dynamic->getFields(); + + $singleEntry = [ + 'id' => $dynamic->getId(), + ]; + + foreach ($entry as $key => $value) { + if ($dynamic->getType($key) === Dynamic::TYPE_ATTACHMENT) { + $singleEntry[$key] = $this->getMediaUrls($value); + } else { + $singleEntry[$key] = $this->toString($value); + } + } + + $singleEntry['created'] = $dynamic->getCreated()->format('c'); + + return [$singleEntry]; + } + + /** + * Convert value to string. + * + * @param string|array $value + * + * @return string + * + * @throws \Exception + */ + protected function toString($value) + { + if (!$value) { + return ''; + } + + if (is_string($value) || is_numeric($value)) { + return $value; + } + + if ($value instanceof \DateTime) { + return $value->format('c'); + } + + if (!is_array($value)) { + throw new \Exception('Invalid value for list builder.'); + } + + return implode($this->delimiter, $value); + } + + /** + * Get media urls. + * + * @param string $value + * + * @return string + */ + protected function getMediaUrls($value) + { + if (is_string($value)) { + return $this->getMediaUrl($value); + } + + if (is_array($value)) { + foreach ($value as $key => $mediaId) { + $value[$key] = $this->getMediaUrl($mediaId); + } + + return implode($this->delimiter, $value); + } + + return $this->toString($value); + } + + /** + * Get media url. + * + * @param string $value + * + * @return string + */ + protected function getMediaUrl($value) + { + return str_replace(urlencode('{id}'), $value, $this->getDownloadUrl()); + } + + /** + * For performance generate route only once. + * + * @return string + */ + protected function getDownloadUrl() + { + if ($this->downloadUrl === null) { + $this->downloadUrl = $this->router->generate( + 'sulu_media.website.media.download', + [ + 'slug' => 'file', + 'id' => '{id}', + ], + true + ); + } + + return $this->downloadUrl; + } +} diff --git a/ListBuilder/DynamicListBuilderInterface.php b/ListBuilder/DynamicListBuilderInterface.php new file mode 100644 index 0000000..ba4e2e4 --- /dev/null +++ b/ListBuilder/DynamicListBuilderInterface.php @@ -0,0 +1,30 @@ +defaultBuilder = $defaultBuilder; + } + + /** + * {@inheritdoc} + */ + public function getFieldDescriptors(Form $form, $locale) + { + $fieldDescriptors = []; + + foreach ($form->getFields() as $field) { + if (in_array($field->getType(), Dynamic::$HIDDEN_TYPES)) { + continue; + } + + $title = ''; + + $translation = $field->getTranslation($locale); + + if ($translation) { + $title = $translation->getTitle(); + } + + $fieldDescriptors[$field->getKey()] = new FieldDescriptor( + $field->getKey(), + $title, + false, + true, + $field->getType() == 'date' ? 'date' : '', + '', + '', + false // not sortable + ); + } + + $fieldDescriptors['created'] = new FieldDescriptor( + 'created', + 'l91_sulu_form.created', + false, + true, + 'date' + ); + + return $fieldDescriptors; + } + + /** + * {@inheritdoc} + */ + public function build($dynamics, $locale, $builder = 'default') + { + $entries = []; + + foreach ($dynamics as $dynamic) { + $entries = array_merge($entries, $this->getBuilder($builder)->build($dynamic, $locale)); + } + + return $entries; + } + + /** + * {@inheritdoc} + */ + public function add(DynamicListBuilderInterface $builder, $alias) + { + $this->builders[$alias] = $builder; + } + + /** + * Get builder. + * + * @param string $alias + * + * @return DynamicListBuilderInterface + * + * @throws \Exception + */ + protected function getBuilder($alias = null) + { + if (!$alias || $alias === 'default') { + $alias = $this->defaultBuilder; + } + + if (!$this->builders[$alias]) { + throw new \Exception(sprintf('Bilder with the name "%s" not found.', $alias)); + } + + return $this->builders[$alias]; + } +} diff --git a/ListBuilder/DynamicListFactoryInterface.php b/ListBuilder/DynamicListFactoryInterface.php new file mode 100644 index 0000000..be2d875 --- /dev/null +++ b/ListBuilder/DynamicListFactoryInterface.php @@ -0,0 +1,50 @@ + $this->createFieldDescriptor('id', '', 'public.id'), 'uuid' => $this->createFieldDescriptor('uuid', '', 'uuid', true), diff --git a/Repository/DynamicRepository.php b/Repository/DynamicRepository.php new file mode 100644 index 0000000..43c7a7f --- /dev/null +++ b/Repository/DynamicRepository.php @@ -0,0 +1,12 @@ + + table="l91_fo_dynamic" + repository-class="L91\Sulu\Bundle\FormBundle\Repository\DynamicRepository"> diff --git a/Resources/config/routing_api.yml b/Resources/config/routing_api.yml index cc5184e..cc7c6af 100644 --- a/Resources/config/routing_api.yml +++ b/Resources/config/routing_api.yml @@ -4,6 +4,12 @@ l91_sulu_form.tests: prefix: l91/form name_prefix: l91_sulu_form. +l91_sulu_form.dynamic: + type: rest + resource: L91\Sulu\Bundle\FormBundle\Controller\DynamicController + prefix: l91/form + name_prefix: l91_sulu_form. + l91.sulu.form.forms: type: rest resource: L91\Sulu\Bundle\FormBundle\Controller\FormController diff --git a/Resources/config/services.xml b/Resources/config/services.xml index cd057f3..3f81638 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -12,10 +12,11 @@ + - + @@ -24,15 +25,22 @@ - - - %l91.sulu.form.mail.from% - %l91.sulu.form.mail.to% - + + + + + + + + %sulu_admin.name% - - + + + - + + %l91.sulu.form.content_dynamic_list_config% - - - - L91SuluFormBundle:Form - - - - + - - - - - %sulu_admin.name% - - + - + - + + L91SuluFormBundle:Template:content-types/form_select_simple.html.twig @@ -82,5 +78,42 @@ + + + + %l91.sulu.form.dynamic_list_builder.default% + + + + %l91.sulu.form.dynamic_list_builder.delimiter% + + + + + + + + + L91SuluFormBundle:Form + + + + + L91SuluFormBundle:Dynamic + + + + + + %l91.sulu.form.mail.from% + %l91.sulu.form.mail.to% + + + + + + diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index 2734043..d2e2a45 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -150,12 +150,13 @@ form-notify.html.twig ## List Tab - Export -To visualise a tab in the Sulu template, simply add following lines to your Bundles `services.xml`: +To visualise a tab in the Sulu template, simply configured the following in your `app/config/config.yml`: ```xml - - - +l91_sulu_form: + content_dynamic_lists: + : + property: ``` **Now a tab should be visible with a list you can export** diff --git a/Resources/public/dist/components/dynamics/list/main.js b/Resources/public/dist/components/dynamics/list/main.js new file mode 100644 index 0000000..d8303a7 --- /dev/null +++ b/Resources/public/dist/components/dynamics/list/main.js @@ -0,0 +1 @@ +define(["jquery"],function(a){"use strict";var b={toolbarId:"dynamic-toolbar",toolbarKey:"dynamics",listId:"dynamic-list",endPointUrl:"/admin/api/l91/form/dynamics",fieldsAction:"/admin/api/l91/form/dynamics/fields"};return{layout:function(){return{extendExisting:!0,content:{width:"fixed",leftSpace:!0,rightSpace:!0}}},initialize:function(){this.render(),this.initPreview()},initPreview:function(){this.sandbox.emit("sulu.preview.initialize",null,!0)},getUrlParameters:function(){return{form:this.options.data()[this.options.property],webspaceKey:this.options.webspace,locale:this.options.language,view:this.options.view,uuid:this.options.id}},render:function(){this.sandbox.dom.html(this.$el,'
');var c=this.getUrlParameters(),d="?"+a.param(c);this.sandbox.sulu.initListToolbarAndList.call(this,b.toolbarKey,b.fieldsAction+d,{el:this.$find("#"+b.toolbarId),template:this.sandbox.sulu.buttons.get({settings:{options:{id:"settings",dropdownItems:{"export":{options:{title:"public.export",icon:"download",callback:function(){var d=a("
");a("body").append(d),App.start([{name:"csv-export@suluadmin",options:{el:d,urlParameter:c,url:b.endPointUrl+".csv"}}])}.bind(this)}},columnOptions:{options:{type:"columnOptions"}}}}}}),instanceName:this.instanceName},{el:this.$find("#"+b.listId),instanceName:this.instanceName,url:b.endPointUrl+d,resultKey:"dynamics",viewOptions:{table:{selectItem:!1,fullWidth:!0}}})}}}); \ No newline at end of file diff --git a/Resources/public/js/components/dynamics/list/main.js b/Resources/public/js/components/dynamics/list/main.js new file mode 100644 index 0000000..dc6ea03 --- /dev/null +++ b/Resources/public/js/components/dynamics/list/main.js @@ -0,0 +1,125 @@ +/** + * Generated by https://github.com/alexander-schranz/sulu-backend-bundle. + */ + +define(['jquery'], function ($) { + 'use strict'; + + var constants = { + toolbarId: 'dynamic-toolbar', + toolbarKey: 'dynamics', + listId: 'dynamic-list', + endPointUrl: '/admin/api/l91/form/dynamics', + fieldsAction: '/admin/api/l91/form/dynamics/fields' + }; + + return { + + layout: function() { + return { + extendExisting: true, + content: { + width: 'fixed', + leftSpace: true, + rightSpace: true + } + }; + }, + + initialize: function() { + this.render(); + this.initPreview(); + }, + + /** + * Initilize the sulu preview + */ + initPreview: function() { + this.sandbox.emit('sulu.preview.initialize', null, true); + }, + + /** + * Get filter parameters for dynamics. + */ + getUrlParameters: function() { + return { + 'form': this.options.data()[this.options.property], + 'webspaceKey': this.options.webspace, + 'locale': this.options.language, + 'view': this.options.view, + 'uuid': this.options.id + }; + }, + + /** + * Renders the component + */ + render: function () { + this.sandbox.dom.html(this.$el, + '
' + + '
' + ); + + var urlParameters = this.getUrlParameters(); + var queryString = '?' + $.param(urlParameters); + + // init list-toolbar and datagrid + this.sandbox.sulu.initListToolbarAndList.call( + this, + constants.toolbarKey, + constants.fieldsAction + queryString, + { + // options for the header (list-toolbar) + el: this.$find('#' + constants.toolbarId), + template: this.sandbox.sulu.buttons.get({ + settings: { + options: { + id: 'settings', + dropdownItems: { + export: { + options: { + title: 'public.export', + icon: 'download', + callback: function() { + var $container = $('
'); + $('body').append($container); + + App.start([{ + name: 'csv-export@suluadmin', + options: { + el: $container, + urlParameter: urlParameters, + url: constants.endPointUrl + '.csv' + } + }]); + }.bind(this) + } + }, + columnOptions: { + options: { + type: 'columnOptions' + } + } + } + } + } + }), + instanceName: this.instanceName + }, + { + // options for the content (datagrid) + el: this.$find('#' + constants.listId), + instanceName: this.instanceName, + url: constants.endPointUrl + queryString, + resultKey: 'dynamics', + viewOptions: { + table: { + selectItem: false, + fullWidth: true + } + } + } + ); + } + }; +}); From 5e1bb065ad8d6412b53b51ee405592b004c5c3ef Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 24 Nov 2016 13:23:58 +0100 Subject: [PATCH 22/39] fixed sort on dynamic list and removed search (#122) --- CHANGELOG.md | 3 ++- ListBuilder/DynamicListFactory.php | 2 +- Resources/public/dist/components/dynamics/list/main.js | 2 +- Resources/public/js/components/dynamics/list/main.js | 5 ++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d003678..590b980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog ## dev-develop - + + - ENHANCEMENT #122 Fixed sort on dynamic list and removed search - FEATURE #121 Added dynamic form list and export - BUGFIX #120 Fixed permission problem on false locale - BUGFIX #117 Fixed limitation of content type select diff --git a/ListBuilder/DynamicListFactory.php b/ListBuilder/DynamicListFactory.php index 704cd6b..ffca014 100644 --- a/ListBuilder/DynamicListFactory.php +++ b/ListBuilder/DynamicListFactory.php @@ -68,7 +68,7 @@ public function getFieldDescriptors(Form $form, $locale) 'l91_sulu_form.created', false, true, - 'date' + 'datetime' ); return $fieldDescriptors; diff --git a/Resources/public/dist/components/dynamics/list/main.js b/Resources/public/dist/components/dynamics/list/main.js index d8303a7..740d58c 100644 --- a/Resources/public/dist/components/dynamics/list/main.js +++ b/Resources/public/dist/components/dynamics/list/main.js @@ -1 +1 @@ -define(["jquery"],function(a){"use strict";var b={toolbarId:"dynamic-toolbar",toolbarKey:"dynamics",listId:"dynamic-list",endPointUrl:"/admin/api/l91/form/dynamics",fieldsAction:"/admin/api/l91/form/dynamics/fields"};return{layout:function(){return{extendExisting:!0,content:{width:"fixed",leftSpace:!0,rightSpace:!0}}},initialize:function(){this.render(),this.initPreview()},initPreview:function(){this.sandbox.emit("sulu.preview.initialize",null,!0)},getUrlParameters:function(){return{form:this.options.data()[this.options.property],webspaceKey:this.options.webspace,locale:this.options.language,view:this.options.view,uuid:this.options.id}},render:function(){this.sandbox.dom.html(this.$el,'
');var c=this.getUrlParameters(),d="?"+a.param(c);this.sandbox.sulu.initListToolbarAndList.call(this,b.toolbarKey,b.fieldsAction+d,{el:this.$find("#"+b.toolbarId),template:this.sandbox.sulu.buttons.get({settings:{options:{id:"settings",dropdownItems:{"export":{options:{title:"public.export",icon:"download",callback:function(){var d=a("
");a("body").append(d),App.start([{name:"csv-export@suluadmin",options:{el:d,urlParameter:c,url:b.endPointUrl+".csv"}}])}.bind(this)}},columnOptions:{options:{type:"columnOptions"}}}}}}),instanceName:this.instanceName},{el:this.$find("#"+b.listId),instanceName:this.instanceName,url:b.endPointUrl+d,resultKey:"dynamics",viewOptions:{table:{selectItem:!1,fullWidth:!0}}})}}}); \ No newline at end of file +define(["jquery"],function(a){"use strict";var b={toolbarId:"dynamic-toolbar",toolbarKey:"dynamics",listId:"dynamic-list",endPointUrl:"/admin/api/l91/form/dynamics",fieldsAction:"/admin/api/l91/form/dynamics/fields"};return{layout:function(){return{extendExisting:!0,content:{width:"fixed",leftSpace:!0,rightSpace:!0}}},initialize:function(){this.render(),this.initPreview()},initPreview:function(){this.sandbox.emit("sulu.preview.initialize",null,!0)},getUrlParameters:function(){return{form:this.options.data()[this.options.property],webspaceKey:this.options.webspace,locale:this.options.language,view:this.options.view,uuid:this.options.id,sortBy:"created",sortOrder:"desc"}},render:function(){this.sandbox.dom.html(this.$el,'
');var c=this.getUrlParameters(),d="?"+a.param(c);this.sandbox.sulu.initListToolbarAndList.call(this,b.toolbarKey,b.fieldsAction+d,{el:this.$find("#"+b.toolbarId),template:this.sandbox.sulu.buttons.get({settings:{options:{id:"settings",dropdownItems:{"export":{options:{title:"public.export",icon:"download",callback:function(){var d=a("
");a("body").append(d),App.start([{name:"csv-export@suluadmin",options:{el:d,urlParameter:c,url:b.endPointUrl+".csv"}}])}.bind(this)}},columnOptions:{options:{type:"columnOptions"}}}}}}),hasSearch:!1,instanceName:this.instanceName},{el:this.$find("#"+b.listId),instanceName:this.instanceName,url:b.endPointUrl+d,resultKey:"dynamics",viewOptions:{table:{selectItem:!1,fullWidth:!0}}})}}}); \ No newline at end of file diff --git a/Resources/public/js/components/dynamics/list/main.js b/Resources/public/js/components/dynamics/list/main.js index dc6ea03..10f4659 100644 --- a/Resources/public/js/components/dynamics/list/main.js +++ b/Resources/public/js/components/dynamics/list/main.js @@ -47,7 +47,9 @@ define(['jquery'], function ($) { 'webspaceKey': this.options.webspace, 'locale': this.options.language, 'view': this.options.view, - 'uuid': this.options.id + 'uuid': this.options.id, + 'sortBy': 'created', + 'sortOrder': 'desc' }; }, @@ -104,6 +106,7 @@ define(['jquery'], function ($) { } } }), + hasSearch: false, instanceName: this.instanceName }, { From 4fa908e76de6c0906dab30787843967e15c0a36f Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 24 Nov 2016 14:42:21 +0100 Subject: [PATCH 23/39] fixed csv export for bool values (#123) --- CHANGELOG.md | 1 + ListBuilder/DynamicListBuilder.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 590b980..726a7c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## dev-develop + - BUGFIX #123 Fixed csv export for bool values - ENHANCEMENT #122 Fixed sort on dynamic list and removed search - FEATURE #121 Added dynamic form list and export - BUGFIX #120 Fixed permission problem on false locale diff --git a/ListBuilder/DynamicListBuilder.php b/ListBuilder/DynamicListBuilder.php index 24b0c22..e0a1bd7 100644 --- a/ListBuilder/DynamicListBuilder.php +++ b/ListBuilder/DynamicListBuilder.php @@ -92,6 +92,10 @@ protected function toString($value) return $value; } + if (is_bool($value)) { + return $value ? 1 : 0; + } + if ($value instanceof \DateTime) { return $value->format('c'); } From 1cc17d6f73f3d614dfea4c4f90a240b7aa1fbba7 Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 24 Nov 2016 16:14:22 +0100 Subject: [PATCH 24/39] added support to add dynamic form list to other navigation tabs (#124) --- CHANGELOG.md | 1 + Content/Types/FormSelect.php | 10 +++++++++- Controller/DynamicController.php | 2 +- DependencyInjection/Configuration.php | 2 +- DependencyInjection/L91SuluFormExtension.php | 18 +++++++++++++++++- Resources/config/services.xml | 8 -------- Resources/doc/dynamic.md | 7 ++++--- 7 files changed, 33 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 726a7c1..5ad8203 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## dev-develop + - FEATURE #124 Added support to add dynamic list to article bundle - BUGFIX #123 Fixed csv export for bool values - ENHANCEMENT #122 Fixed sort on dynamic list and removed search - FEATURE #121 Added dynamic form list and export diff --git a/Content/Types/FormSelect.php b/Content/Types/FormSelect.php index 59d63e2..4689080 100644 --- a/Content/Types/FormSelect.php +++ b/Content/Types/FormSelect.php @@ -104,8 +104,16 @@ public function getContentData(PropertyInterface $property) try { // Create Dynamic Data $uuid = $property->getStructure()->getUuid(); - $webspaceKey = $property->getStructure()->getWebspaceKey(); $locale = $property->getStructure()->getLanguageCode(); + $webspaceKey = $property->getStructure()->getWebspaceKey(); + + if ($request->get('_sulu')) { + if ($request->get('_sulu')->getAttribute('webspace')) { + $webspaceKey = $request->get('_sulu')->getAttribute('webspace')->getKey(); + } + $locale = $request->getLocale(); + } + $formEntity = $this->formRepository->findById($id, $locale); // set Defaults diff --git a/Controller/DynamicController.php b/Controller/DynamicController.php index adbfd72..3843eb0 100644 --- a/Controller/DynamicController.php +++ b/Controller/DynamicController.php @@ -98,7 +98,7 @@ protected function getFilters(Request $request) 'form' => $request->get('form'), ]; - return $filters; + return array_filter($filters); } /** diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 8d65d70..c0e8b59 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -35,7 +35,7 @@ public function getConfigTreeBuilder() ->scalarNode('delimiter')->defaultValue(PHP_EOL)->end() ->end() ->end() - ->variableNode('content_dynamic_lists')->defaultValue([])->end() + ->variableNode('dynamic_lists')->defaultValue([])->end() ->arrayNode('ajax_templates') ->prototype('scalar')->end()->defaultValue([]) ->end() diff --git a/DependencyInjection/L91SuluFormExtension.php b/DependencyInjection/L91SuluFormExtension.php index 5c164e7..ca789b9 100644 --- a/DependencyInjection/L91SuluFormExtension.php +++ b/DependencyInjection/L91SuluFormExtension.php @@ -2,8 +2,10 @@ namespace L91\Sulu\Bundle\FormBundle\DependencyInjection; +use L91\Sulu\Bundle\FormBundle\Admin\DynamicListNavigationProvider; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -51,7 +53,21 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('l91.sulu.form.mail.to', $config['mail_helper']['to']); $container->setParameter('l91.sulu.form.ajax_templates', $config['ajax_templates']); $container->setParameter('l91.sulu.form.mailchimp_api_key', $config['mailchimp_api_key']); - $container->setParameter('l91.sulu.form.content_dynamic_list_config', $config['content_dynamic_lists']); + $container->setParameter('l91.sulu.form.dynamic_lists.config', $config['dynamic_lists']); + + // add dynamic lists + foreach ($config['dynamic_lists'] as $key => $value) { + $parameter = 'l91.sulu.form.dynamic_lists.' . $key . '.config'; + $container->setParameter($parameter, $value); + + $definition = new Definition(DynamicListNavigationProvider::class); + $definition->addArgument('%' . $parameter . '%'); + $definition->addArgument($key); + $definition->setClass(DynamicListNavigationProvider::class); + $definition->addTag('sulu_admin.content_navigation', ['alias' => $key]); + $definition->addTag('sulu.context', ['context' => 'admin']); + $container->setDefinition('l91_sulu_form.navigation_provider.' . $key . '.dynamic_list', $definition); + } // Dynamic List Builder $container->setParameter( diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 3f81638..fa990c4 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -50,14 +50,6 @@ - - %l91.sulu.form.content_dynamic_list_config% - - - - - diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index d2e2a45..a83ee27 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -154,9 +154,10 @@ To visualise a tab in the Sulu template, simply configured the following in your ```xml l91_sulu_form: - content_dynamic_lists: - : - property: + dynamic_lists: + content: + : + property: ``` **Now a tab should be visible with a list you can export** From d26932d2a113059045acb9eab068f8dd4e578981 Mon Sep 17 00:00:00 2001 From: L91 Date: Wed, 30 Nov 2016 08:00:13 +0100 Subject: [PATCH 25/39] added option to create media collection for every form and page (#118) --- CHANGELOG.md | 2 +- Content/Types/FormSelect.php | 34 +++-- DependencyInjection/Configuration.php | 7 + DependencyInjection/L91SuluFormExtension.php | 13 +- Media/CollectionStrategyInterface.php | 30 +++++ Media/CollectionStrategySingle.php | 44 +++++++ Media/CollectionStrategyTree.php | 129 +++++++++++++++++++ Resources/config/services.xml | 14 +- Resources/doc/dynamic.md | 9 ++ 9 files changed, 269 insertions(+), 13 deletions(-) create mode 100644 Media/CollectionStrategyInterface.php create mode 100644 Media/CollectionStrategySingle.php create mode 100644 Media/CollectionStrategyTree.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ad8203..716c197 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## dev-develop + - FEATURE #118 Added media collection strategy tree - FEATURE #124 Added support to add dynamic list to article bundle - BUGFIX #123 Fixed csv export for bool values - ENHANCEMENT #122 Fixed sort on dynamic list and removed search @@ -44,4 +45,3 @@ - FEATURE #67 Added sixths widths to fields - BUGFIX #66 Fixed that dynamic is related to a form - BUGFIX #65 Unlimited title column and changed string to text - diff --git a/Content/Types/FormSelect.php b/Content/Types/FormSelect.php index 4689080..879dc71 100644 --- a/Content/Types/FormSelect.php +++ b/Content/Types/FormSelect.php @@ -7,10 +7,10 @@ use L91\Sulu\Bundle\FormBundle\Event\DynFormSavedEvent; use L91\Sulu\Bundle\FormBundle\Form\HandlerInterface; use L91\Sulu\Bundle\FormBundle\Form\Type\DynamicFormType; +use L91\Sulu\Bundle\FormBundle\Media\CollectionStrategyInterface; use L91\Sulu\Bundle\FormBundle\Repository\FormRepository; use Sulu\Component\Content\Compat\PropertyInterface; use Sulu\Component\Content\SimpleContentType; -use Sulu\Component\Media\SystemCollections\SystemCollectionManagerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RequestStack; @@ -47,9 +47,9 @@ class FormSelect extends SimpleContentType private $formHandler; /** - * @var SystemCollectionManagerInterface + * @var CollectionStrategyInterface */ - private $systemCollectionManager; + private $collectionStrategy; /** * @var EventDispatcherInterface @@ -64,7 +64,7 @@ class FormSelect extends SimpleContentType * @param RequestStack $requestStack * @param FormFactoryInterface $formFactory * @param HandlerInterface $formHandler - * @param SystemCollectionManagerInterface $systemCollectionManager + * @param CollectionStrategyInterface $collectionStrategy * @param EventDispatcherInterface $eventDispatcher */ public function __construct( @@ -73,7 +73,7 @@ public function __construct( RequestStack $requestStack, FormFactoryInterface $formFactory, HandlerInterface $formHandler, - SystemCollectionManagerInterface $systemCollectionManager, + CollectionStrategyInterface $collectionStrategy, EventDispatcherInterface $eventDispatcher ) { parent::__construct('FormSelect', ''); @@ -82,7 +82,7 @@ public function __construct( $this->requestStack = $requestStack; $this->formFactory = $formFactory; $this->formHandler = $formHandler; - $this->systemCollectionManager = $systemCollectionManager; + $this->collectionStrategy = $collectionStrategy; $this->eventDispatcher = $eventDispatcher; } @@ -116,13 +116,20 @@ public function getContentData(PropertyInterface $property) $formEntity = $this->formRepository->findById($id, $locale); + $translation = $formEntity->getTranslation($locale); + + if (!$translation) { + // No translation for this locale exists + return; + } + // set Defaults $defaults = []; foreach ($formEntity->getFields() as $field) { - $translation = $field->getTranslation($locale); + $fieldTranslation = $field->getTranslation($locale); - if ($translation && $translation->getDefaultValue()) { - $value = $translation->getDefaultValue(); + if ($fieldTranslation && $fieldTranslation->getDefaultValue()) { + $value = $fieldTranslation->getDefaultValue(); // handle special types switch ($field->getType()) { @@ -145,7 +152,14 @@ public function getContentData(PropertyInterface $property) $locale, $property->getName(), $property->getStructure()->getView(), - $this->systemCollectionManager->getSystemCollection('l91_sulu_form.attachments') + $this->collectionStrategy->getCollectionId( + $formEntity->getId(), + $translation->getTitle(), + 'page', + $property->getStructure()->getUuid(), + $property->getStructure()->getProperty('title')->getValue(), + $locale + ) ); $form = $this->formFactory->create( diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index c0e8b59..d434319 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -22,6 +22,13 @@ public function getConfigTreeBuilder() $rootNode->children() ->scalarNode('mailchimp_api_key')->defaultValue(null)->end() + ->enumNode('media_collection_strategy') + ->values([ + L91SuluFormExtension::MEDIA_COLLECTION_STRATEGY_SINGLE, + L91SuluFormExtension::MEDIA_COLLECTION_STRATEGY_TREE, + ]) + ->defaultValue(L91SuluFormExtension::MEDIA_COLLECTION_STRATEGY_SINGLE) + ->end() ->arrayNode('mail_helper') ->children() ->scalarNode('from')->end() diff --git a/DependencyInjection/L91SuluFormExtension.php b/DependencyInjection/L91SuluFormExtension.php index ca789b9..5b6a056 100644 --- a/DependencyInjection/L91SuluFormExtension.php +++ b/DependencyInjection/L91SuluFormExtension.php @@ -17,6 +17,10 @@ */ class L91SuluFormExtension extends Extension implements PrependExtensionInterface { + const SYSTEM_COLLECTION_ROOT = 'l91_sulu_form'; + const MEDIA_COLLECTION_STRATEGY_SINGLE = 'single'; + const MEDIA_COLLECTION_STRATEGY_TREE = 'tree'; + /** * {@inheritdoc} */ @@ -27,7 +31,7 @@ public function prepend(ContainerBuilder $container) 'sulu_media', [ 'system_collections' => [ - 'l91_sulu_form' => [ + self::SYSTEM_COLLECTION_ROOT => [ 'meta_title' => ['en' => 'Sulu forms', 'de' => 'Sulu Formulare'], 'collections' => [ 'attachments' => [ @@ -54,6 +58,13 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('l91.sulu.form.ajax_templates', $config['ajax_templates']); $container->setParameter('l91.sulu.form.mailchimp_api_key', $config['mailchimp_api_key']); $container->setParameter('l91.sulu.form.dynamic_lists.config', $config['dynamic_lists']); + $container->setParameter('l91.sulu.form.media_collection_strategy', $config['media_collection_strategy']); + + // Default Media Collection Strategy + $container->setAlias( + 'l91_sulu_form.media_collection_strategy.default', + 'l91_sulu_form.media_collection_strategy.' . $config['media_collection_strategy'] + ); // add dynamic lists foreach ($config['dynamic_lists'] as $key => $value) { diff --git a/Media/CollectionStrategyInterface.php b/Media/CollectionStrategyInterface.php new file mode 100644 index 0000000..277ba0b --- /dev/null +++ b/Media/CollectionStrategyInterface.php @@ -0,0 +1,30 @@ +systemCollectionManager = $systemCollectionManager; + } + + /** + * {@inheritdoc} + */ + public function getCollectionId( + $formId, + $formTitle, + $type, + $typeId, + $title, + $locale + ) { + return $this->systemCollectionManager->getSystemCollection( + L91SuluFormExtension::SYSTEM_COLLECTION_ROOT . '.attachments' + ); + } +} diff --git a/Media/CollectionStrategyTree.php b/Media/CollectionStrategyTree.php new file mode 100644 index 0000000..7d7707a --- /dev/null +++ b/Media/CollectionStrategyTree.php @@ -0,0 +1,129 @@ +collectionManager = $collectionManager; + $this->systemCollectionManager = $systemCollectionManager; + } + + /** + * {@inheritdoc} + */ + public function getCollectionId( + $formId, + $formTitle, + $type, + $typeId, + $title, + $locale + ) { + $rootCollectionKey = L91SuluFormExtension::SYSTEM_COLLECTION_ROOT; + $parentCollectionKey = $rootCollectionKey . '.' . $formId; + $collectionKey = $parentCollectionKey . '.' . $type . '_' . $typeId; + + $collectionId = $this->loadCollectionId($collectionKey, $locale); + + // Return collection when exists + if ($collectionId) { + return $collectionId; + } + + // Get parent collection + $parentCollectionId = $this->loadCollectionId($parentCollectionKey, $locale); + + // Create Parent Collection when not exists + if (!$parentCollectionId) { + $parentCollectionId = $this->createCollection( + $formTitle, + $this->systemCollectionManager->getSystemCollection($rootCollectionKey), + $parentCollectionKey, + $locale + ); + } + + // Create Collection + return $this->createCollection( + $title, + $parentCollectionId, + $collectionKey, + $locale + ); + } + + /** + * Create collection. + * + * @param string $title + * @param int $parentId + * @param string $collectionKey + * @param string $locale + * + * @return int + */ + private function createCollection($title, $parentId, $collectionKey, $locale) + { + $parentCollection = $this->collectionManager->save([ + 'title' => $title, + 'type' => ['id' => 2], + 'parent' => $parentId, + 'key' => $collectionKey, + 'locale' => $locale, + ], null); + + return $parentCollection->getId(); + } + + /** + * Load collection id. + * + * @param string $collectionKey + * @param string $locale + * + * @return int + */ + private function loadCollectionId( + $collectionKey, + $locale + ) { + try { + $collection = $this->collectionManager->getByKey($collectionKey, $locale); + + if (!$collection) { + return; + } + + return $collection->getId(); + } catch (\Exception $e) { + // Catch all exception + } + } +} diff --git a/Resources/config/services.xml b/Resources/config/services.xml index fa990c4..9cb446e 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -65,7 +65,7 @@ - + @@ -107,5 +107,17 @@ + + + + + + + + + + diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index a83ee27..b292a8e 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -161,3 +161,12 @@ l91_sulu_form: ``` **Now a tab should be visible with a list you can export** + +## Media Collections + +To create for every form and page an own collection you need to configure the following in your `config.yml`: + +```yml +l91_sulu_form: + media_collection_strategy: "tree" +``` From 3f64bf3130291d8fa3a994e6d524c5d3b24430f3 Mon Sep 17 00:00:00 2001 From: L91 Date: Tue, 6 Dec 2016 13:53:45 +0100 Subject: [PATCH 26/39] fixed form select by using native select (#126) --- CHANGELOG.md | 1 + Controller/ListController.php | 1 - Manager/FormManager.php | 1 - .../views/Template/content-types/form_select_simple.html.twig | 1 + 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 716c197..2aac77a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## dev-develop + - BUGFIX #125 Fixed form select by using native select - FEATURE #118 Added media collection strategy tree - FEATURE #124 Added support to add dynamic list to article bundle - BUGFIX #123 Fixed csv export for bool values diff --git a/Controller/ListController.php b/Controller/ListController.php index 306f49f..d400c5b 100644 --- a/Controller/ListController.php +++ b/Controller/ListController.php @@ -83,7 +83,6 @@ public function cgetAction(Request $request) $page = $listBuilder->getCurrentPage(); $limit = $listBuilder->getLimit(); - // create list representation $representation = new ListRepresentation( $list, diff --git a/Manager/FormManager.php b/Manager/FormManager.php index 68e03aa..5b8a3fc 100644 --- a/Manager/FormManager.php +++ b/Manager/FormManager.php @@ -143,7 +143,6 @@ public function save($data, $locale = null, $id = null) $fieldTranslation->setPlaceholder(self::getValue($fieldData, 'placeholder')); $fieldTranslation->setDefaultValue(self::getValue($fieldData, 'defaultValue')); - // Field Options $prefix = 'options['; diff --git a/Resources/views/Template/content-types/form_select_simple.html.twig b/Resources/views/Template/content-types/form_select_simple.html.twig index b28b417..f7d3140 100644 --- a/Resources/views/Template/content-types/form_select_simple.html.twig +++ b/Resources/views/Template/content-types/form_select_simple.html.twig @@ -9,6 +9,7 @@ data-aura-editable="false" data-aura-direction="bottom" data-aura-value-name="title" + data-aura-is-native="true" data-aura-deselect-field="select.no-choice" data-type="select-type-custom" data-mapper-return-value="id" From 04d0601ae0bd41531cdeff34121ce8d3ec78c566 Mon Sep 17 00:00:00 2001 From: L91 Date: Thu, 15 Dec 2016 10:57:42 +0100 Subject: [PATCH 27/39] Fixed httpexception add dynamic form builder (#111) * fixed exception controller redirect --- CHANGELOG.md | 1 + Content/Types/FormSelect.php | 164 +-------- DependencyInjection/Configuration.php | 1 + DependencyInjection/L91SuluFormExtension.php | 1 + Entity/Dynamic.php | 10 + EventListener/RequestListener.php | 81 +++- Form/Builder.php | 365 +++++++++++++++++++ Form/BuilderInterface.php | 36 ++ Resources/config/services.xml | 22 +- Resources/doc/dynamic.md | 6 - 10 files changed, 532 insertions(+), 155 deletions(-) create mode 100644 Form/Builder.php create mode 100644 Form/BuilderInterface.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aac77a..8228db9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## dev-develop + - BUGFIX #111 Fixed exception controller redirect - BUGFIX #125 Fixed form select by using native select - FEATURE #118 Added media collection strategy tree - FEATURE #124 Added support to add dynamic list to article bundle diff --git a/Content/Types/FormSelect.php b/Content/Types/FormSelect.php index 879dc71..4486f3f 100644 --- a/Content/Types/FormSelect.php +++ b/Content/Types/FormSelect.php @@ -2,19 +2,11 @@ namespace L91\Sulu\Bundle\FormBundle\Content\Types; -use Doctrine\ORM\NoResultException; -use L91\Sulu\Bundle\FormBundle\Entity\Dynamic; -use L91\Sulu\Bundle\FormBundle\Event\DynFormSavedEvent; -use L91\Sulu\Bundle\FormBundle\Form\HandlerInterface; -use L91\Sulu\Bundle\FormBundle\Form\Type\DynamicFormType; -use L91\Sulu\Bundle\FormBundle\Media\CollectionStrategyInterface; +use L91\Sulu\Bundle\FormBundle\Form\BuilderInterface; use L91\Sulu\Bundle\FormBundle\Repository\FormRepository; use Sulu\Component\Content\Compat\PropertyInterface; use Sulu\Component\Content\SimpleContentType; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\Form\FormInterface; /** * ContentType for selecting a form. @@ -32,58 +24,26 @@ class FormSelect extends SimpleContentType private $formRepository; /** - * @var RequestStack + * @var BuilderInterface */ - private $requestStack; - - /** - * @var FormFactoryInterface - */ - private $formFactory; - - /** - * @var HandlerInterface - */ - private $formHandler; - - /** - * @var CollectionStrategyInterface - */ - private $collectionStrategy; - - /** - * @var EventDispatcherInterface - */ - private $eventDispatcher; + private $formBuilder; /** * FormSelect constructor. * * @param string $template * @param FormRepository $formRepository - * @param RequestStack $requestStack - * @param FormFactoryInterface $formFactory - * @param HandlerInterface $formHandler - * @param CollectionStrategyInterface $collectionStrategy - * @param EventDispatcherInterface $eventDispatcher + * @param BuilderInterface $formBuilder */ public function __construct( $template, FormRepository $formRepository, - RequestStack $requestStack, - FormFactoryInterface $formFactory, - HandlerInterface $formHandler, - CollectionStrategyInterface $collectionStrategy, - EventDispatcherInterface $eventDispatcher + BuilderInterface $formBuilder ) { parent::__construct('FormSelect', ''); $this->template = $template; $this->formRepository = $formRepository; - $this->requestStack = $requestStack; - $this->formFactory = $formFactory; - $this->formHandler = $formHandler; - $this->collectionStrategy = $collectionStrategy; - $this->eventDispatcher = $eventDispatcher; + $this->formBuilder = $formBuilder; } /** @@ -97,105 +57,21 @@ public function getContentData(PropertyInterface $property) return; } - $request = $this->requestStack->getCurrentRequest(); - - $form = null; - - try { - // Create Dynamic Data - $uuid = $property->getStructure()->getUuid(); - $locale = $property->getStructure()->getLanguageCode(); - $webspaceKey = $property->getStructure()->getWebspaceKey(); - - if ($request->get('_sulu')) { - if ($request->get('_sulu')->getAttribute('webspace')) { - $webspaceKey = $request->get('_sulu')->getAttribute('webspace')->getKey(); - } - $locale = $request->getLocale(); - } - - $formEntity = $this->formRepository->findById($id, $locale); - - $translation = $formEntity->getTranslation($locale); - - if (!$translation) { - // No translation for this locale exists - return; - } - - // set Defaults - $defaults = []; - foreach ($formEntity->getFields() as $field) { - $fieldTranslation = $field->getTranslation($locale); - - if ($fieldTranslation && $fieldTranslation->getDefaultValue()) { - $value = $fieldTranslation->getDefaultValue(); - - // handle special types - switch ($field->getType()) { - case Dynamic::TYPE_DATE: - $value = new \DateTime($value); - break; - case Dynamic::TYPE_DROPDOWN_MULTIPLE: - case Dynamic::TYPE_CHECKBOX_MULTIPLE: - $value = preg_split('/\r\n|\r|\n/', $value, -1, PREG_SPLIT_NO_EMPTY); - break; - } - - $defaults[$field->getKey()] = $value; - } - } - - // Create Form Type - $formType = new DynamicFormType( - $formEntity, - $locale, - $property->getName(), - $property->getStructure()->getView(), - $this->collectionStrategy->getCollectionId( - $formEntity->getId(), - $translation->getTitle(), - 'page', - $property->getStructure()->getUuid(), - $property->getStructure()->getProperty('title')->getValue(), - $locale - ) - ); - - $form = $this->formFactory->create( - $formType, - new Dynamic($uuid, $locale, $formEntity, $webspaceKey, $defaults) - ); - - // handle request - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $dynamic = $form->getData(); - $serializedObject = $formEntity->serializeForLocale($locale, $dynamic); - - // save - $this->formHandler->handle( - $form, - [ - '_form_type' => $formType, - 'formEntity' => $serializedObject, - ] - ); - - $event = new DynFormSavedEvent($serializedObject, $dynamic); - $this->eventDispatcher->dispatch(DynFormSavedEvent::NAME, $event); - - // Do redirect after success - throw new HttpException(302, null, null, ['Location' => '?send=true']); - } - - return $form->createView(); - } catch (NoResultException $e) { - // do nothing + /** @var FormInterface $form */ + list($formType, $form) = $this->formBuilder->build( + $id, + 'page', + $property->getStructure()->getUuid(), + $property->getStructure()->getProperty('title')->getValue(), + $property->getStructure()->getLanguageCode(), + $property->getName() + ); + + if (!$form) { + return; } - return; + return $form->createView(); } /** diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index d434319..7ff6e96 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -42,6 +42,7 @@ public function getConfigTreeBuilder() ->scalarNode('delimiter')->defaultValue(PHP_EOL)->end() ->end() ->end() + ->scalarNode('dynamic_default_view')->defaultValue('AppBundle:templates:dynamic')->end() ->variableNode('dynamic_lists')->defaultValue([])->end() ->arrayNode('ajax_templates') ->prototype('scalar')->end()->defaultValue([]) diff --git a/DependencyInjection/L91SuluFormExtension.php b/DependencyInjection/L91SuluFormExtension.php index 5b6a056..f91a32c 100644 --- a/DependencyInjection/L91SuluFormExtension.php +++ b/DependencyInjection/L91SuluFormExtension.php @@ -57,6 +57,7 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('l91.sulu.form.mail.to', $config['mail_helper']['to']); $container->setParameter('l91.sulu.form.ajax_templates', $config['ajax_templates']); $container->setParameter('l91.sulu.form.mailchimp_api_key', $config['mailchimp_api_key']); + $container->setParameter('l91.sulu.form.dynamic_default_view', $config['dynamic_default_view']); $container->setParameter('l91.sulu.form.dynamic_lists.config', $config['dynamic_lists']); $container->setParameter('l91.sulu.form.media_collection_strategy', $config['media_collection_strategy']); diff --git a/Entity/Dynamic.php b/Entity/Dynamic.php index 0ab2274..2246d9a 100644 --- a/Entity/Dynamic.php +++ b/Entity/Dynamic.php @@ -341,6 +341,16 @@ public function getForm() return $this->form; } + /** + * Get locale. + * + * @return string + */ + public function getLocale() + { + return $this->locale; + } + /** * Get field. * diff --git a/EventListener/RequestListener.php b/EventListener/RequestListener.php index cd308b8..693d7cb 100644 --- a/EventListener/RequestListener.php +++ b/EventListener/RequestListener.php @@ -2,10 +2,54 @@ namespace L91\Sulu\Bundle\FormBundle\EventListener; +use L91\Sulu\Bundle\FormBundle\Entity\Dynamic; +use L91\Sulu\Bundle\FormBundle\Event\DynFormSavedEvent; +use L91\Sulu\Bundle\FormBundle\Form\BuilderInterface; +use L91\Sulu\Bundle\FormBundle\Form\HandlerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Event\GetResponseEvent; class RequestListener { + /** + * @var BuilderInterface + */ + protected $formBuilder; + + /** + * @var HandlerInterface + */ + protected $formHander; + + /** + * @var EventDispatcherInterface + */ + protected $eventDispatcher; + + /** + * RequestListener constructor. + * + * @param BuilderInterface $formBuilder + * @param HandlerInterface $formHandler + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct( + BuilderInterface $formBuilder, + HandlerInterface $formHandler, + EventDispatcherInterface $eventDispatcher + ) { + $this->formBuilder = $formBuilder; + $this->formHandler = $formHandler; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * On Kernel request. + * + * @param GetResponseEvent $event + */ public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { @@ -15,9 +59,44 @@ public function onKernelRequest(GetResponseEvent $event) $request = $event->getRequest(); - if ($request->isMethod('post')) { + if (!$request->isMethod('post')) { // don't do anything iif it's not a post request return; } + + try { + /** @var FormInterface $form */ + list($formType, $form) = $this->formBuilder->buildByRequest($request); + + if (!$form || !$formType) { + // do nothing when no form was found + return; + } + } catch (\Exception $e) { + // Catch all exception on build form by request + + return; + } + + if ($form->isSubmitted() && $form->isValid()) { + /** @var Dynamic $dynamic */ + $dynamic = $form->getData(); + $serializedObject = $dynamic->getForm()->serializeForLocale($dynamic->getLocale(), $dynamic); + + // save + $this->formHandler->handle( + $form, + [ + '_form_type' => $formType, + 'formEntity' => $serializedObject, + ] + ); + + $dynFormSavedEvent = new DynFormSavedEvent($serializedObject, $dynamic); + $this->eventDispatcher->dispatch(DynFormSavedEvent::NAME, $dynFormSavedEvent); + + $response = new RedirectResponse('?send=true'); + $event->setResponse($response); + } } } diff --git a/Form/Builder.php b/Form/Builder.php new file mode 100644 index 0000000..8bcdc21 --- /dev/null +++ b/Form/Builder.php @@ -0,0 +1,365 @@ +requestStack = $requestStack; + $this->formRepository = $formRepository; + $this->collectionStrategy = $collectionStrategy; + $this->formFactory = $formFactory; + $this->defaultStructureView = $defaultStructureView; + } + + /** + * @param Request $request + * + * @return array + */ + public function buildByRequest(Request $request) + { + foreach ($request->request->all() as $key => $parameters) { + if (strpos($key, 'dynamic_') === 0) { + $formNameParts = explode('dynamic_', $key, 2); + + if (!isset($formNameParts[1])) { + continue; + } + + $name = $formNameParts[1]; + $locale = $request->getLocale(); + + $structure = $request->attributes->get('structure'); + + if ( + !$structure instanceof StructureInterface + || !$structure->hasProperty('title') + || !$structure->hasProperty($name) + ) { + continue; + } + + $typeId = $structure->getUuid(); + $typeName = $structure->getProperty('title')->getValue(); + $id = (int) $structure->getProperty($name)->getValue(); + + if (!$typeId || !$id || !$typeName) { + continue; + } + + return $this->build($id, 'page', $typeId, $typeName, $locale, $name); + } + } + + return [null, null]; + } + + /** + * Returns formType and the builded form. + * + * @param int $id + * @param string $type + * @param string $typeId + * @param string $typeName + * @param string $locale + * @param string $name + * + * @return array + */ + public function build($id, $type, $typeId, $typeName, $locale = null, $name = 'form') + { + $request = $this->requestStack->getCurrentRequest(); + + if (!$locale) { + $locale = $request->getLocale(); + } + + // Check if form was builded before and return the cached form. + $key = $this->getKey($id, $type, $typeId, $typeName, $locale, $name); + + if (!isset($this->cache[$key])) { + $this->cache[$key] = $this->buildForm($id, $type, $typeId, $typeName, $locale, $name); + } + + return $this->cache[$key]; + } + + /** + * Returns formType and the built form. + * + * @param int $id + * @param string $type + * @param string $typeId + * @param string $typeName + * @param string $locale + * @param string $name + * + * @return array + */ + protected function buildForm($id, $type, $typeId, $typeName, $locale, $name) + { + $request = $this->requestStack->getCurrentRequest(); + + // Load Form entity + $formEntity = $this->loadFormEntity($id, $locale); + + if (!$formEntity) { + return [null, null]; + } + + $webspaceKey = $this->getWebspaceKey(); + $defaults = $this->getDefaults($formEntity, $locale); + + // Create Form Type + $formType = $this->createFormType( + $formEntity, + $locale, + $name, + $type, + $typeId, + $typeName + ); + + // Create Form + $form = $this->createForm( + $formType, + $typeId, + $locale, + $formEntity, + $webspaceKey, + $defaults + ); + + // Handle request + $form->handleRequest($request); + + return [$formType, $form]; + } + + /** + * Get key. + * + * @param int $id + * @param string $type + * @param string $typeId + * @param string $typeName + * @param string $locale + * @param string $name + * + * @return string + */ + protected function getKey($id, $type, $typeId, $typeName, $locale, $name) + { + return implode('__', func_get_args()); + } + + /** + * Create form. + * + * @param $formType + * @param $typeId + * @param $locale + * @param $formEntity + * @param $webspaceKey + * @param $defaults + * + * @return FormInterface + */ + protected function createForm($formType, $typeId, $locale, $formEntity, $webspaceKey, $defaults) + { + return $this->formFactory->create( + $formType, + new Dynamic($typeId, $locale, $formEntity, $webspaceKey, $defaults) + ); + } + + /** + * Load Form entity. + * + * @param $id + * @param $locale + * + * @return Form + */ + protected function loadFormEntity($id, $locale) + { + try { + // Load Form entity + $formEntity = $this->formRepository->findById($id, $locale); + } catch (NoResultException $e) { + return; + } + + $translation = $formEntity->getTranslation($locale); + + if (!$translation) { + // No translation for this locale exists + return; + } + + return $formEntity; + } + + /** + * Create form type. + * + * @param Form $formEntity + * @param string $locale + * @param string $name + * @param string $type + * @param string $typeId + * @param string $typeName + * + * @return DynamicFormType + */ + protected function createFormType( + Form $formEntity, + $locale, + $name, + $type, + $typeId, + $typeName + ) { + /** @var PageBridge $structure */ + $structure = $this->requestStack->getCurrentRequest()->attributes->get('structure'); + + $structureView = $this->defaultStructureView; + + if ($structure) { + $structureView = $structure->getView(); + } + + return new DynamicFormType( + $formEntity, + $locale, + $name, + $structureView, + $this->collectionStrategy->getCollectionId( + $formEntity->getId(), + $formEntity->getTranslation($locale)->getTitle(), + $type, + $typeId, + $typeName, + $locale + ) + ); + } + + /** + * Get defaults. + * + * @param Form $formEntity + * @param string $locale + * + * @return array + */ + protected function getDefaults(Form $formEntity, $locale) + { + // set Defaults + $defaults = []; + + foreach ($formEntity->getFields() as $field) { + $fieldTranslation = $field->getTranslation($locale); + + if ($fieldTranslation && $fieldTranslation->getDefaultValue()) { + $value = $fieldTranslation->getDefaultValue(); + + // handle special types + switch ($field->getType()) { + case Dynamic::TYPE_DATE: + $value = new \DateTime($value); + break; + case Dynamic::TYPE_DROPDOWN_MULTIPLE: + case Dynamic::TYPE_CHECKBOX_MULTIPLE: + $value = preg_split('/\r\n|\r|\n/', $value, -1, PREG_SPLIT_NO_EMPTY); + break; + } + + $defaults[$field->getKey()] = $value; + } + } + + return $defaults; + } + + /** + * Get webspace key. + * + * @return string + */ + protected function getWebspaceKey() + { + $request = $this->requestStack->getCurrentRequest(); + $webspaceKey = null; + + if ($request->get('_sulu')) { + if ($request->get('_sulu')->getAttribute('webspace')) { + $webspaceKey = $request->get('_sulu')->getAttribute('webspace')->getKey(); + } + } + + return $webspaceKey; + } +} diff --git a/Form/BuilderInterface.php b/Form/BuilderInterface.php new file mode 100644 index 0000000..53d2c9c --- /dev/null +++ b/Form/BuilderInterface.php @@ -0,0 +1,36 @@ + L91SuluFormBundle:Template:content-types/form_select_simple.html.twig + + + + + + + - - + - + + %l91.sulu.form.dynamic_default_view% + - + + + + + + + diff --git a/Resources/doc/dynamic.md b/Resources/doc/dynamic.md index b292a8e..1bd3a03 100644 --- a/Resources/doc/dynamic.md +++ b/Resources/doc/dynamic.md @@ -108,12 +108,6 @@ https://github.com/symfony/symfony/blob/v2.7.0/src/Symfony/Bridge/Twig/Resources {%- endblock form_label -%} ``` -## Issues - -Please check to following issue before using it in production: - -[https://github.com/alexander-schranz/sulu-form-bundle/issues/69](https://github.com/alexander-schranz/sulu-form-bundle/issues/69) - ## Create Form To create a dynamic form (which is selectable in the property type `form_select`) simply From 83949c4a3f3f264e7c0ea380a310f4956e61a649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Kh=C3=BCny?= Date: Wed, 21 Dec 2016 10:18:12 +0100 Subject: [PATCH 28/39] Added toggler to set email as replyTo (#130) * Add toggler to set replyTo and german translation * save replyTo status and use email as replyTo when it exists * added field translations * fixed english translation * Fixed translations * Fixed notfiyReplyTo return and template structure --- CHANGELOG.md | 1 + Controller/FormController.php | 1 + Entity/FormTranslation.php | 29 +++++++++++++++++++ Form/Type/DynamicFormType.php | 14 +++++++++ Manager/FormManager.php | 1 + .../config/doctrine/FormTranslation.orm.xml | 5 ++++ Resources/translations/sulu/backend.de.xlf | 4 +++ Resources/translations/sulu/backend.en.xlf | 4 +++ Resources/translations/sulu/backend.fr.xlf | 4 +++ Resources/views/forms/template.html.twig | 29 ++++++++++++++++--- 10 files changed, 88 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8228db9..beaf36b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## dev-develop + - FEATURE #130 Added toggler to set email as replyTo - BUGFIX #111 Fixed exception controller redirect - BUGFIX #125 Fixed form select by using native select - FEATURE #118 Added media collection strategy tree diff --git a/Controller/FormController.php b/Controller/FormController.php index 6323f04..65d3609 100644 --- a/Controller/FormController.php +++ b/Controller/FormController.php @@ -547,6 +547,7 @@ private function getApiEntity(Form $entity, $locale) 'sendAttachments' => $translation->getSendAttachments(), 'deactivateNotifyMails' => $translation->getDeactivateNotifyMails(), 'deactivateCustomerMails' => $translation->getDeactivateCustomerMails(), + 'replyTo' => $translation->getReplyTo(), ]; } diff --git a/Entity/FormTranslation.php b/Entity/FormTranslation.php index 90e5baf..f9f0909 100644 --- a/Entity/FormTranslation.php +++ b/Entity/FormTranslation.php @@ -62,6 +62,11 @@ class FormTranslation implements AuditableInterface */ private $deactivateCustomerMails; + /** + * @var bool + */ + private $replyTo; + /** * @var string */ @@ -325,6 +330,30 @@ public function getDeactivateCustomerMails() return $this->deactivateCustomerMails; } + /** + * Set replyTo. + * + * @param bool $replyTo + * + * @return FormTranslation + */ + public function setReplyTo($replyTo) + { + $this->replyTo = $replyTo; + + return $this; + } + + /** + * Get replyTo. + * + * @return bool + */ + public function getReplyTo() + { + return $this->replyTo; + } + /** * @param string $locale * diff --git a/Form/Type/DynamicFormType.php b/Form/Type/DynamicFormType.php index 4be85ab..3b17a4b 100644 --- a/Form/Type/DynamicFormType.php +++ b/Form/Type/DynamicFormType.php @@ -336,6 +336,20 @@ public function getNotifyToMailAddress($formData = []) return [$toMail => $toName]; } + /** + * {@inheritdoc} + */ + public function getNotifyReplyToMailAddress($formData = []) + { + if ($this->getTranslation()->getReplyTo()) { + if ($formData->__isset('email')) { + return $formData->__get('email'); + } + } + + return parent::getNotifyReplyToMailAddress($formData); + } + /** * {@inheritdoc} */ diff --git a/Manager/FormManager.php b/Manager/FormManager.php index 5b8a3fc..52a967b 100644 --- a/Manager/FormManager.php +++ b/Manager/FormManager.php @@ -98,6 +98,7 @@ public function save($data, $locale = null, $id = null) $translation->setSendAttachments(self::getValue($data, 'sendAttachments')); $translation->setDeactivateNotifyMails(self::getValue($data, 'deactivateNotifyMails')); $translation->setDeactivateCustomerMails(self::getValue($data, 'deactivateCustomerMails')); + $translation->setReplyTo(self::getValue($data, 'replyTo')); $translation->setChanged(new \DateTime()); // Add Translation to Form diff --git a/Resources/config/doctrine/FormTranslation.orm.xml b/Resources/config/doctrine/FormTranslation.orm.xml index 90e8865..ff34d62 100644 --- a/Resources/config/doctrine/FormTranslation.orm.xml +++ b/Resources/config/doctrine/FormTranslation.orm.xml @@ -32,6 +32,11 @@ + + + + + diff --git a/Resources/translations/sulu/backend.de.xlf b/Resources/translations/sulu/backend.de.xlf index ffe315b..1f90ae9 100644 --- a/Resources/translations/sulu/backend.de.xlf +++ b/Resources/translations/sulu/backend.de.xlf @@ -35,6 +35,10 @@ l91_sulu_form.deactivate_customer Bestätigungsemails deaktivieren + + l91_sulu_form.user_as_reply_to + "Reply-to" Adresse automatisch ausfüllen + diff --git a/Resources/translations/sulu/backend.en.xlf b/Resources/translations/sulu/backend.en.xlf index 5609796..3555981 100644 --- a/Resources/translations/sulu/backend.en.xlf +++ b/Resources/translations/sulu/backend.en.xlf @@ -35,6 +35,10 @@ l91_sulu_form.deactivate_customer deactivate Successmails + + l91_sulu_form.user_as_reply_to + Autofill "reply-to" address + diff --git a/Resources/translations/sulu/backend.fr.xlf b/Resources/translations/sulu/backend.fr.xlf index 2d40353..6d0c4c7 100644 --- a/Resources/translations/sulu/backend.fr.xlf +++ b/Resources/translations/sulu/backend.fr.xlf @@ -34,6 +34,10 @@ l91_sulu_form.deactivate_customer déactiver les mails de confirmation + + l91_sulu_form.user_as_reply_to + "répondre" compléter l'adresse automatiquement + diff --git a/Resources/views/forms/template.html.twig b/Resources/views/forms/template.html.twig index 7ce6ab3..371077e 100644 --- a/Resources/views/forms/template.html.twig +++ b/Resources/views/forms/template.html.twig @@ -171,9 +171,28 @@
+ -
-
+
+
+
+ + +
+
+
+
+
+
-
+
+
+
-
+