├── .gitignore ├── Resources ├── translations │ ├── .gitkeep │ ├── routes.en.po │ └── zikulaformiculamodule.en.po ├── views │ ├── Form │ │ ├── 0 │ │ │ ├── userFooter.html.twig │ │ │ ├── userHeader.html.twig │ │ │ ├── adminMail.html.twig │ │ │ ├── userMail.html.twig │ │ │ ├── userError.html.twig │ │ │ ├── userMail.txt.twig │ │ │ ├── adminMail.txt.twig │ │ │ ├── userForm.html.twig │ │ │ └── userConfirm.html.twig │ │ ├── 1 │ │ │ ├── userFooter.html.twig │ │ │ ├── userHeader.html.twig │ │ │ ├── userMail.html.twig │ │ │ ├── adminMail.html.twig │ │ │ ├── userError.html.twig │ │ │ ├── adminMail.txt.twig │ │ │ ├── userMail.txt.twig │ │ │ ├── userConfirm.html.twig │ │ │ └── userForm.html.twig │ │ ├── 2 │ │ │ ├── userFooter.html.twig │ │ │ ├── userHeader.html.twig │ │ │ ├── adminMail.html.twig │ │ │ ├── userMail.html.twig │ │ │ ├── userError.html.twig │ │ │ ├── userMail.txt.twig │ │ │ ├── adminMail.txt.twig │ │ │ ├── userForm.html.twig │ │ │ └── userConfirm.html.twig │ │ └── 3 │ │ │ ├── userFooter.html.twig │ │ │ ├── userHeader.html.twig │ │ │ ├── adminMail.html.twig │ │ │ ├── userMail.html.twig │ │ │ ├── userError.html.twig │ │ │ ├── adminMail.txt.twig │ │ │ ├── userMail.txt.twig │ │ │ ├── userConfirm.html.twig │ │ │ └── userForm.html.twig │ ├── ContentType │ │ └── formEdit.html.twig │ ├── Include │ │ └── spamCheck.html.twig │ ├── Contact │ │ ├── delete.html.twig │ │ ├── edit.html.twig │ │ └── view.html.twig │ ├── Submission │ │ ├── delete.html.twig │ │ ├── view.html.twig │ │ └── display.html.twig │ └── Config │ │ └── config.html.twig ├── public │ ├── fonts │ │ ├── vera.ttf │ │ ├── arial.ttf │ │ ├── freesans.ttf │ │ ├── quickhand.ttf │ │ └── quickhand_readme.txt │ └── js │ │ └── ZikulaFormiculaModule.Config.js ├── config │ ├── routing.yaml │ └── services.yaml └── docs │ └── credits.txt ├── .github └── dependabot.yml ├── ZikulaFormiculaModule.php ├── composer.lock ├── Entity ├── Repository │ ├── ContactRepository.php │ └── SubmissionRepository.php ├── ContactEntity.php └── SubmissionEntity.php ├── zikula.manifest.json ├── DependencyInjection └── ZikulaFormiculaExtension.php ├── .styleci.yml ├── composer.json ├── Form └── Type │ ├── DeleteContactType.php │ ├── DeleteSubmissionType.php │ ├── EditContactType.php │ ├── UserSubmissionType.php │ └── ConfigType.php ├── Menu └── ExtensionMenu.php ├── Twig └── Extension │ └── FormiculaCaptchaExtension.php ├── ContentType ├── Form │ └── Type │ │ └── FormType.php └── FormType.php ├── HookSubscriber └── FormUiHooksSubscriber.php ├── Traits └── StandardFieldsTrait.php ├── Helper ├── EnvironmentHelper.php └── CaptchaHelper.php ├── Controller ├── ConfigController.php ├── SubmissionController.php └── ContactController.php ├── FormiculaModuleInstaller.php └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /Resources/translations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Resources/views/Form/0/userFooter.html.twig: -------------------------------------------------------------------------------- 1 | {# empty footer #} 2 | -------------------------------------------------------------------------------- /Resources/views/Form/1/userFooter.html.twig: -------------------------------------------------------------------------------- 1 | {# empty footer #} 2 | -------------------------------------------------------------------------------- /Resources/views/Form/2/userFooter.html.twig: -------------------------------------------------------------------------------- 1 | {# empty footer #} 2 | -------------------------------------------------------------------------------- /Resources/views/Form/3/userFooter.html.twig: -------------------------------------------------------------------------------- 1 | {# empty footer #} 2 | -------------------------------------------------------------------------------- /Resources/views/ContentType/formEdit.html.twig: -------------------------------------------------------------------------------- 1 | {{ form_row(form) }} 2 | -------------------------------------------------------------------------------- /Resources/public/fonts/vera.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zikula-modules/Formicula/HEAD/Resources/public/fonts/vera.ttf -------------------------------------------------------------------------------- /Resources/public/fonts/arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zikula-modules/Formicula/HEAD/Resources/public/fonts/arial.ttf -------------------------------------------------------------------------------- /Resources/public/fonts/freesans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zikula-modules/Formicula/HEAD/Resources/public/fonts/freesans.ttf -------------------------------------------------------------------------------- /Resources/public/fonts/quickhand.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zikula-modules/Formicula/HEAD/Resources/public/fonts/quickhand.ttf -------------------------------------------------------------------------------- /Resources/config/routing.yaml: -------------------------------------------------------------------------------- 1 | zikulaformiculamodule: 2 | resource: "@ZikulaFormiculaModule/Controller" 3 | type: annotation 4 | -------------------------------------------------------------------------------- /Resources/views/Form/1/userHeader.html.twig: -------------------------------------------------------------------------------- 1 | {{ pageSetVar('title', 'Apply online'|trans) }} 2 |

{% trans %}Apply online{% endtrans %}

3 | {{ showflashes() }} 4 | -------------------------------------------------------------------------------- /Resources/views/Form/0/userHeader.html.twig: -------------------------------------------------------------------------------- 1 | {{ pageSetVar('title', 'Contact our team'|trans) }} 2 |

{% trans %}Contact our team{% endtrans %}

3 | {{ showflashes() }} 4 | -------------------------------------------------------------------------------- /Resources/views/Form/2/userHeader.html.twig: -------------------------------------------------------------------------------- 1 | {{ pageSetVar('title', 'Contact our team'|trans) }} 2 |

{% trans %}Contact our team{% endtrans %}

3 | {{ showflashes() }} 4 | -------------------------------------------------------------------------------- /Resources/views/Form/3/userHeader.html.twig: -------------------------------------------------------------------------------- 1 | {{ pageSetVar('title', 'Make a reservation'|trans) }} 2 |

{% trans %}Make a reservation{% endtrans %}

3 | {{ showflashes() }} 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | 2 | version: 2 3 | updates: 4 | - package-ecosystem: "composer" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | -------------------------------------------------------------------------------- /Resources/views/Form/0/adminMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}New contact{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/0/adminMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/0/userMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}Contact our team{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/0/userMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/1/userMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}Apply online!{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/1/userMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/2/adminMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}New contact{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/2/adminMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/2/userMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}Contact our team{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/2/userMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/1/adminMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}New application{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/1/adminMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/3/adminMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}New rental request{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/3/adminMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/3/userMail.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% trans %}Make a reservation{% endtrans %} 5 | 6 | 7 | 8 | 9 | {{ include('@ZikulaFormiculaModule/Form/3/userMail.txt.twig')|nl2br }} 10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/views/Form/0/userError.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/0/userHeader.html.twig') }} 2 | 3 |

4 | {% trans %}There is an error in your input.{% endtrans %} 5 |

6 | {% trans %}Go back to the form{% endtrans %} 7 |

8 |

9 | 10 | {{ include('@ZikulaFormiculaModule/Form/0/userFooter.html.twig') }} 11 | -------------------------------------------------------------------------------- /Resources/views/Form/1/userError.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/1/userHeader.html.twig') }} 2 | 3 |

4 | {% trans %}There is an error in your input.{% endtrans %} 5 |

6 | {% trans %}Go back to the form{% endtrans %} 7 |

8 |

9 | 10 | {{ include('@ZikulaFormiculaModule/Form/1/userFooter.html.twig') }} 11 | -------------------------------------------------------------------------------- /Resources/views/Form/2/userError.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/2/userHeader.html.twig') }} 2 | 3 |

4 | {% trans %}There is an error in your input.{% endtrans %} 5 |

6 | {% trans %}Go back to the form{% endtrans %} 7 |

8 |

9 | 10 | {{ include('@ZikulaFormiculaModule/Form/2/userFooter.html.twig') }} 11 | -------------------------------------------------------------------------------- /Resources/views/Form/3/userError.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/3/userHeader.html.twig') }} 2 | 3 |

4 | {% trans %}There is an error in your input.{% endtrans %} 5 |

6 | {% trans %}Go back to the form{% endtrans %} 7 |

8 |

9 | 10 | {{ include('@ZikulaFormiculaModule/Form/3/userFooter.html.twig') }} 11 | -------------------------------------------------------------------------------- /ZikulaFormiculaModule.php: -------------------------------------------------------------------------------- 1 | =7.2.5", 17 | "ext-gd": "*" 18 | }, 19 | "platform-dev": [], 20 | "plugin-api-version": "2.0.0" 21 | } 22 | -------------------------------------------------------------------------------- /Resources/views/Include/spamCheck.html.twig: -------------------------------------------------------------------------------- 1 | {% if enableSpamCheck %} 2 |
3 | 4 |
5 | {{ zikulaformiculamodule_simpleCaptcha() }} 6 | {# example for custom arguments: 7 | zikulaformiculamodule_simpleCaptcha(font='arial', size=20, bgColour='ffffff', fgColour='0000ff') 8 | #} 9 | 10 | {% trans %}(to prevent spam){% endtrans %} 11 |
12 |
13 | {% endif %} 14 | -------------------------------------------------------------------------------- /Entity/Repository/ContactRepository.php: -------------------------------------------------------------------------------- 1 | =3.0.0 <4.0.0", 15 | "composerpath": "composer.json", 16 | "description": "Template-driven form mailer.", 17 | "keywords": [ 18 | ] 19 | }, 20 | "urls": { 21 | "version": "", 22 | "docs": "", 23 | "demo": "", 24 | "download": "https://github.com/zikula-modules/Formicula/releases", 25 | "issues": "https://github.com/zikula-modules/Formicula/issues" 26 | }, 27 | "dependencies": [ 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /Resources/public/js/ZikulaFormiculaModule.Config.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $(document).ready(function() { 3 | if (!$('#zikulaformiculamodule_config_enableSpamCheck').prop('checked')) { 4 | $('#formiculaSpamCheckDetails').addClass('d-none'); 5 | } 6 | $('#zikulaformiculamodule_config_enableSpamCheck').change(function() { 7 | $('#formiculaSpamCheckDetails').toggleClass('d-none', !$('#zikulaformiculamodule_config_enableSpamCheck').prop('checked')); 8 | }); 9 | 10 | if (!$('#zikulaformiculamodule_config_storeSubmissionData').prop('checked')) { 11 | $('#formiculaDataStorageDetails').addClass('d-none'); 12 | } 13 | $('#zikulaformiculamodule_config_storeSubmissionData').change(function(){ 14 | $('#formiculaDataStorageDetails').toggleClass('d-none', !$('#zikulaformiculamodule_config_storeSubmissionData').prop('checked')); 15 | }); 16 | }); 17 | })(jQuery) 18 | -------------------------------------------------------------------------------- /DependencyInjection/ZikulaFormiculaExtension.php: -------------------------------------------------------------------------------- 1 | load('services.yaml'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: symfony 2 | risky: true 3 | 4 | enabled: 5 | - alpha_ordered_imports 6 | - cast_spaces 7 | - combine_consecutive_issets 8 | - combine_consecutive_unsets 9 | - concat_with_spaces 10 | - declare_strict_types 11 | - escape_implicit_backslashes 12 | - explicit_indirect_variable 13 | - explicit_string_variable 14 | - mb_str_functions 15 | - multiline_comment_opening_closing 16 | - no_null_property_initialization 17 | - no_php4_constructor 18 | - no_useless_else 19 | - php_unit_mock 20 | - php_unit_namespaced 21 | - php_unit_set_up_tear_down_visibility 22 | - random_api_migration 23 | - strict_comparison 24 | - ternary_to_null_coalescing 25 | 26 | disabled: 27 | - cast_spaces 28 | - concat_without_spaces 29 | - function_declaration 30 | - native_constant_invocation_symfony 31 | - native_function_invocation_symfony 32 | - no_blank_lines_after_phpdoc 33 | - no_blank_lines_after_throw 34 | - php_unit_fqcn_annotation 35 | - phpdoc_align 36 | - phpdoc_scalar 37 | - phpdoc_separation 38 | - phpdoc_summary 39 | - phpdoc_to_comment 40 | - pre_increment 41 | - single_quote 42 | - trailing_comma_in_multiline_array 43 | - unalign_double_arrow 44 | - unalign_equals 45 | -------------------------------------------------------------------------------- /Resources/docs/credits.txt: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | // vpContact module for Rogue 0.711 3 | // Copyright (c) 2002 by 4 | // http://www.beginner-ag.de/postnuke 5 | // ---------------------------------------------------------------------- 6 | // 7 | // Formicula 0.1 - 0.3 8 | // Smartyfied version for use with pnRender by Frank Schummertz, Jim Hadfield 9 | // (in fact this an 80% rewrite of the older vpContact code) 10 | // frank.schummertz@landseer-stuttgart.de 11 | // jim@snowbankih.com 12 | // http://snowbankih.tzo.com 13 | // ---------------------------------------------------------------------- 14 | // 15 | // Formicula 0.5 16 | // store contacts in seperate contacts table (like vpContact) 17 | // reiner.maiwald@freenet.de 18 | // 19 | // Formicula 0.6 - 1.0 20 | // frank.schummertz@landseer-stuttgart.de 21 | // 22 | // Thanks to Carsten Volmer for extensive testing. 23 | // French translation by Christophe Beaujean (yokav) 24 | // 25 | // Formicula 2.0 26 | // frank.schummertz@landseer-stuttgart.de 27 | // Stylesheet adjustments by Carsten Volmer 28 | // 29 | // Formicula 3.0 30 | // updated for Zikula 1.3 31 | // Carsten Volmer, Axel Guckelberger, Erik Spaan 32 | // 33 | // Formicula 4.0 34 | // updated for Zikula 1.4 35 | // Axel Guckelberger 36 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zikula/formicula-module", 3 | "version": "6.0.1", 4 | "description": "Template-driven form mailer.", 5 | "type": "zikula-module", 6 | "license": "LGPL-3.0+", 7 | "authors": [ 8 | { 9 | "name": "Zikula", 10 | "homepage": "https://ziku.la/" 11 | } 12 | ], 13 | "autoload": { 14 | "psr-4": { "Zikula\\FormiculaModule\\": "" } 15 | }, 16 | "require": { 17 | "php": ">=7.2.5", 18 | "ext-gd": "*" 19 | }, 20 | "extra": { 21 | "zikula": { 22 | "class": "Zikula\\FormiculaModule\\ZikulaFormiculaModule", 23 | "core-compatibility": ">=3.0.0 <4.0.0", 24 | "displayname": "Formicula", 25 | "url": "formicula", 26 | "oldnames": ["Formicula"], 27 | "icon": "far fa-check-square", 28 | "capabilities": { 29 | "admin": { 30 | "route": "zikulaformiculamodule_contact_view" 31 | }, 32 | "user": { 33 | "route": "zikulaformiculamodule_user_index" 34 | } 35 | }, 36 | "securityschema": { 37 | "ZikulaFormiculaModule::": "Form ID:Contact ID:" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Resources/views/Form/0/userMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans with {'%s%': userData.uname} %}Hello %s%!{% endtrans %} 2 | 3 | {% trans %}Thank you for the comments posted from our website. The sent data is:{% endtrans %} 4 | 5 | {% trans %}Your Name{% endtrans %}: {{ userData.name }} 6 | {% if modVars.showCompany and userData.company %} 7 | {% trans %}Company{% endtrans %}: {{ userData.company }} 8 | {% endif %} 9 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 10 | {% if modVars.showPhone and userData.phone %} 11 | {% trans %}Phone number{% endtrans %}: {{ userData.phone }} 12 | {% endif %} 13 | {% if modVars.showUrl and userData.url %} 14 | {% trans %}Website{% endtrans %}: {{ userData.url }} 15 | {% endif %} 16 | {% if modVars.showLocation and userData.location %} 17 | {% trans %}Location{% endtrans %}: {{ userData.location }} 18 | {% endif %} 19 | 20 | {% for field in customFields %} 21 | {{ field.name }}: {{ field.data }} 22 | {% endfor %} 23 | {% if modVars.showComment and userData.comment %} 24 | 25 | {% trans %}Comment{% endtrans %}: 26 | {{ userData.comment }} 27 | {% endif %} 28 | {% if modVars.showFileAttachment and userData.fileUpload %} 29 | 30 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 31 | {% endif %} 32 | 33 | {% trans %}We will respond to your email address as soon as possible.{% endtrans %} 34 | 35 | {% trans with {'%s%': siteName} %}The %s% team{% endtrans %} 36 | -------------------------------------------------------------------------------- /Resources/views/Form/2/userMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans with {'%s%': userData.uname} %}Hello %s%!{% endtrans %} 2 | 3 | {% trans %}Thank you for the comments posted from our website. The sent data is:{% endtrans %} 4 | 5 | {% trans %}Your name{% endtrans %}: {{ userData.name }} 6 | {% if modVars.showCompany and userData.company %} 7 | {% trans %}Company{% endtrans %}: {{ userData.company }} 8 | {% endif %} 9 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 10 | {% if modVars.showPhone and userData.phone %} 11 | {% trans %}Phone number{% endtrans %}: {{ userData.phone }} 12 | {% endif %} 13 | {% if modVars.showUrl and userData.url %} 14 | {% trans %}Website{% endtrans %}: {{ userData.url }} 15 | {% endif %} 16 | {% if modVars.showLocation and userData.location %} 17 | {% trans %}Location{% endtrans %}: {{ userData.location }} 18 | {% endif %} 19 | 20 | {% for field in customFields %} 21 | {{ field.name }}: {{ field.data }} 22 | {% endfor %} 23 | {% if modVars.showComment and userData.comment %} 24 | 25 | {% trans %}Comment{% endtrans %}: 26 | {{ userData.comment }} 27 | {% endif %} 28 | {% if modVars.showFileAttachment and userData.fileUpload %} 29 | 30 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 31 | {% endif %} 32 | 33 | {% trans %}We will respond to your email address as soon as possible.{% endtrans %} 34 | 35 | {% trans with {'%s%': siteName} %}The %s% team{% endtrans %} 36 | -------------------------------------------------------------------------------- /Resources/views/Contact/delete.html.twig: -------------------------------------------------------------------------------- 1 |

2 | 3 | {% trans %}Delete contact{% endtrans %} 4 | {{ pageSetVar('title', 'Delete contact'|trans) }} 5 |

6 | 7 | {{ form_start(form) }} 8 | {{ form_errors(form) }} 9 | 10 |
11 | {% trans %}Confirmation prompt{% endtrans %} 12 |

{% trans with { '%s%': contact.name } %}Do you really want to delete contact '%s%'?{% endtrans %}

13 | 14 | {{ form_row(form.cid) }} 15 |
16 |
17 | {% trans %}Contact information{% endtrans %} 18 |
19 | 20 |
21 |

{{ contact.name }}

22 |
23 |
24 |
25 | 26 |
27 |

{{ contact.email }}

28 |
29 |
30 |
31 | 32 |
33 |
34 | {{ form_widget(form.delete) }} 35 | {{ form_widget(form.cancel) }} 36 |
37 |
38 | 39 | {{ form_end(form) }} 40 | -------------------------------------------------------------------------------- /Resources/views/Form/0/adminMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans %}Hello!{% endtrans %} 2 | 3 | {% trans %}A visitor of to your web site used the form for contact and sent the following:{% endtrans %} 4 | 5 | {% trans %}Form #{% endtrans %}: {{ form }} 6 | {% trans %}Contact{% endtrans %}: {{ contact.name }} 7 | {% trans %}Name{% endtrans %}: {{ userData.name }} 8 | {% if modVars.showCompany and userData.company %} 9 | {% trans %}Company{% endtrans %}: {{ userData.company }} 10 | {% endif %} 11 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 12 | {% if modVars.showPhone and userData.phone %} 13 | {% trans %}Phone number{% endtrans %}: {{ userData.phone }} 14 | {% endif %} 15 | {% if modVars.showUrl and userData.url %} 16 | {% trans %}Website{% endtrans %}: {{ userData.url }} 17 | {% endif %} 18 | {% if modVars.showLocation and userData.location %} 19 | {% trans %}Location{% endtrans %}: {{ userData.location }} 20 | {% endif %} 21 | 22 | {% for field in customFields %} 23 | {{ field.name }}: {{ field.data }} 24 | {% endfor %} 25 | {% if modVars.showComment and userData.comment %} 26 | 27 | {% trans %}Comment{% endtrans %}: 28 | {{ userData.comment }} 29 | {% endif %} 30 | {% if modVars.showFileAttachment and userData.fileUpload %} 31 | 32 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 33 | {% endif %} 34 | 35 | {% trans %}The user has the following IP address/hostname:{% endtrans %} {{ ipAddress }} / {{ hostName }} 36 | -------------------------------------------------------------------------------- /Resources/views/Form/2/adminMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans %}Hello!{% endtrans %} 2 | 3 | {% trans %}A visitor of to your web site used the form for contact and sent the following:{% endtrans %} 4 | 5 | {% trans %}Form #{% endtrans %}: {{ form }} 6 | {% trans %}Contact{% endtrans %}: {{ contact.name }} 7 | {% trans %}Name{% endtrans %}: {{ userData.name }} 8 | {% if modVars.showCompany and userData.company %} 9 | {% trans %}Company{% endtrans %}: {{ userData.company }} 10 | {% endif %} 11 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 12 | {% if modVars.showPhone and userData.phone %} 13 | {% trans %}Phone number{% endtrans %}: {{ userData.phone }} 14 | {% endif %} 15 | {% if modVars.showUrl and userData.url %} 16 | {% trans %}Website{% endtrans %}: {{ userData.url }} 17 | {% endif %} 18 | {% if modVars.showLocation and userData.location %} 19 | {% trans %}Location{% endtrans %}: {{ userData.location }} 20 | {% endif %} 21 | 22 | {% for field in customFields %} 23 | {{ field.name }}: {{ field.data }} 24 | {% endfor %} 25 | {% if modVars.showComment and userData.comment %} 26 | 27 | {% trans %}Comment{% endtrans %}: 28 | {{ userData.comment }} 29 | {% endif %} 30 | {% if modVars.showFileAttachment and userData.fileUpload %} 31 | 32 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 33 | {% endif %} 34 | 35 | {% trans %}The user has the following IP address/hostname:{% endtrans %} {{ ipAddress }} / {{ hostName }} 36 | -------------------------------------------------------------------------------- /Resources/views/Form/3/adminMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans %}Hello!{% endtrans %} 2 | 3 | {% trans %}A visitor to your website made a new rental request and sent the following:{% endtrans %} 4 | 5 | {% trans %}Form #{% endtrans %}: {{ form }} 6 | {% trans %}Contact{% endtrans %}: {{ contact.name }} 7 | {% trans %}Name{% endtrans %}: {{ userData.name }} 8 | {% if modVars.showCompany and userData.company %} 9 | {% trans %}Company{% endtrans %}: {{ userData.company }} 10 | {% endif %} 11 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 12 | {% if modVars.showPhone and userData.phone %} 13 | {% trans %}Phone number{% endtrans %}: {{ userData.phone }} 14 | {% endif %} 15 | {% if modVars.showUrl and userData.url %} 16 | {% trans %}Website{% endtrans %}: {{ userData.url }} 17 | {% endif %} 18 | {% if modVars.showLocation and userData.location %} 19 | {% trans %}Location{% endtrans %}: {{ userData.location }} 20 | {% endif %} 21 | 22 | {% for field in customFields %} 23 | {{ field.name }}: {{ field.data }} 24 | {% endfor %} 25 | {% if modVars.showComment and userData.comment %} 26 | 27 | {% trans %}Comment{% endtrans %}: 28 | {{ userData.comment }} 29 | {% endif %} 30 | {% if modVars.showFileAttachment and userData.fileUpload %} 31 | 32 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 33 | {% endif %} 34 | 35 | {% trans %}The user has the following IP address/hostname:{% endtrans %} {{ ipAddress }} / {{ hostName }} 36 | -------------------------------------------------------------------------------- /Resources/views/Form/1/adminMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans %}Hello!{% endtrans %} 2 | 3 | {% trans %}A visitor of to your web site used the form for contact and sent the following:{% endtrans %} 4 | 5 | {% trans %}Form #{% endtrans %}: {{ form }} 6 | {% trans %}Contact{% endtrans %}: {{ contact.name }} 7 | {% trans %}Name{% endtrans %}: {{ userData.name }} 8 | {% if modVars.showCompany and userData.company %} 9 | {% trans %}Company{% endtrans %}: {{ userData.company }} 10 | {% endif %} 11 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 12 | {% if modVars.showPhone and userData.phone %} 13 | {% trans %}Phone number'{% endtrans %}: {{ userData.phone }} 14 | {% endif %} 15 | {% if modVars.showUrl and userData.url %} 16 | {% trans %}Website{% endtrans %}: {{ userData.url }} 17 | {% endif %} 18 | {% if modVars.showLocation and userData.location %} 19 | {% trans %}Location{% endtrans %}: {{ userData.location }} 20 | {% endif %} 21 | 22 | {% for field in customFields %} 23 | {{ field.name }}: {{ field.data }} 24 | {% endfor %} 25 | {% if modVars.showComment and userData.comment %} 26 | 27 | {% trans %}Comment{% endtrans %}: 28 | {{ userData.comment }} 29 | {% endif %} 30 | {% if modVars.showFileAttachment and userData.fileUpload %} 31 | 32 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 33 | {% endif %} 34 | 35 | {% trans %}The user has the following IP address/hostname:{% endtrans %} {{ ipAddress }} / {{ hostName }} 36 | -------------------------------------------------------------------------------- /Resources/views/Form/1/userMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans with {'%s%': userData.uname} %}Hello %s%!{% endtrans %} 2 | 3 | {% trans %}This data was sent to us:{% endtrans %} 4 | 5 | {% trans %}Your name{% endtrans %}: {{ userData.name }} 6 | {% if modVars.showCompany and userData.company %} 7 | {% trans %}Company{% endtrans %}: {{ userData.company }} 8 | {% endif %} 9 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 10 | {% if modVars.showPhone and userData.phone %} 11 | {% trans %}Phone number{% endtrans %}: {{ userData.phone }} 12 | {% endif %} 13 | {% if modVars.showUrl and userData.url %} 14 | {% trans %}Website{% endtrans %}: {{ userData.url }} 15 | {% endif %} 16 | {% if modVars.showLocation and userData.location %} 17 | {% trans %}Location{% endtrans %}: {{ userData.location }} 18 | {% endif %} 19 | 20 | {% for field in customFields %} 21 | {{ field.name }}: {{ field.data }} 22 | {% endfor %} 23 | {% if modVars.showComment and userData.comment %} 24 | 25 | {% trans %}Comment{% endtrans %}: 26 | {{ userData.comment }} 27 | {% endif %} 28 | {% if modVars.showFileAttachment and userData.fileUpload %} 29 | 30 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 31 | {% endif %} 32 | 33 | {% trans %}Thanks for applying, we will keep your data strictly confidential.{% endtrans %} 34 | 35 | {% trans %}We will respond to your email address as soon as possible.{% endtrans %} 36 | 37 | {% trans with {'%s%': siteName} %}The %s% team{% endtrans %} 38 | -------------------------------------------------------------------------------- /Form/Type/DeleteContactType.php: -------------------------------------------------------------------------------- 1 | add('cid', HiddenType::class) 30 | ->add('delete', SubmitType::class, [ 31 | 'label' => 'Delete', 32 | 'icon' => 'fa-trash-alt', 33 | 'attr' => [ 34 | 'class' => 'btn-danger' 35 | ] 36 | ]) 37 | ->add('cancel', SubmitType::class, [ 38 | 'label' => 'Cancel', 39 | 'icon' => 'fa-times' 40 | ]) 41 | ; 42 | } 43 | 44 | public function getBlockPrefix() 45 | { 46 | return 'zikulaformiculamodule_deletecontact'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Form/Type/DeleteSubmissionType.php: -------------------------------------------------------------------------------- 1 | add('sid', HiddenType::class) 30 | ->add('delete', SubmitType::class, [ 31 | 'label' => 'Delete', 32 | 'icon' => 'fa-trash-alt', 33 | 'attr' => [ 34 | 'class' => 'btn-danger' 35 | ] 36 | ]) 37 | ->add('cancel', SubmitType::class, [ 38 | 'label' => 'Cancel', 39 | 'icon' => 'fa-times' 40 | ]) 41 | ; 42 | } 43 | 44 | public function getBlockPrefix() 45 | { 46 | return 'zikulaformiculamodule_deletesubmission'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Resources/views/Form/3/userMail.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans with {'%s%': userData.uname} %}Hello %s%!{% endtrans %} 2 | 3 | {% trans %}Thank you for your reservation.{% endtrans %} 4 | 5 | {% trans %}Kind regards{% endtrans %} 6 | {{ siteName }} 7 | 8 | {% trans %}This data was sent to us:{% endtrans %} 9 | 10 | {% trans %}Your name{% endtrans %}: {{ userData.name }} 11 | {% if modVars.showCompany and userData.company %} 12 | {% trans %}Company{% endtrans %}: {{ userData.company }} 13 | {% endif %} 14 | {% trans %}Email{% endtrans %}: {{ userData.emailAddress }} 15 | {% if modVars.showPhone and userData.phone %} 16 | {% trans %}Phone number{% endtrans %}: {{ userData.phone }} 17 | {% endif %} 18 | {% if modVars.showUrl and userData.url %} 19 | {% trans %}Website{% endtrans %}: {{ userData.url }} 20 | {% endif %} 21 | {% if modVars.showLocation and userData.location %} 22 | {% trans %}Location{% endtrans %}: {{ userData.location }} 23 | {% endif %} 24 | 25 | {% for field in customFields %} 26 | {{ field.name }}: {{ field.data }} 27 | {% endfor %} 28 | {% if modVars.showComment and userData.comment %} 29 | 30 | {% trans %}Comment{% endtrans %}: 31 | {{ userData.comment }} 32 | {% endif %} 33 | {% if modVars.showFileAttachment and userData.fileUpload %} 34 | 35 | {% trans %}Attached file{% endtrans %}: {{ userData.fileUpload }} 36 | {% endif %} 37 | 38 | {% trans %}We will respond to your email address as soon as possible.{% endtrans %} 39 | 40 | {% trans with {'%s%': siteName} %}The %s% team{% endtrans %} 41 | -------------------------------------------------------------------------------- /Resources/translations/routes.en.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Content-Type: text/plain; charset=UTF-8\n" 4 | "Content-Transfer-Encoding: 8bit\n" 5 | "Language: en\n" 6 | 7 | msgid "doc" 8 | msgstr "/installdoc/{name}" 9 | msgid "fos_js_routing_js" 10 | msgstr "/js/routing.{_format}" 11 | msgid "guiteebmainztheme_ajax_getsearchsuggestions" 12 | msgstr "/ajax/getSearchSuggestions" 13 | msgid "home" 14 | msgstr "/" 15 | msgid "install" 16 | msgstr "/install/{stage}" 17 | msgid "liip_imagine_filter" 18 | msgstr "/media/cache/resolve/{filter}/{path}" 19 | msgid "liip_imagine_filter_runtime" 20 | msgstr "/media/cache/resolve/{filter}/rc/{hash}/{path}" 21 | msgid "upgrade" 22 | msgstr "/upgrade/{stage}" 23 | msgid "zikula_hook_hook_changeproviderareaorder" 24 | msgstr "/hooks/changeorder" 25 | msgid "zikula_hook_hook_edit" 26 | msgstr "/hooks/{moduleName}" 27 | msgid "zikula_hook_hook_togglesubscribeareastatus" 28 | msgstr "/hooks/togglestatus" 29 | msgid "zikula_workflow_editor_index" 30 | msgstr "/editor/index" 31 | msgid "zikulaformiculamodule_config_clearcache" 32 | msgstr "/config/clearcache" 33 | msgid "zikulaformiculamodule_config_config" 34 | msgstr "/config/config" 35 | msgid "zikulaformiculamodule_contact_delete" 36 | msgstr "/contact/delete" 37 | msgid "zikulaformiculamodule_contact_edit" 38 | msgstr "/contact/edit" 39 | msgid "zikulaformiculamodule_contact_view" 40 | msgstr "/contact/view" 41 | msgid "zikulaformiculamodule_submission_delete" 42 | msgstr "/submission/delete" 43 | msgid "zikulaformiculamodule_submission_display" 44 | msgstr "/submission/display" 45 | msgid "zikulaformiculamodule_submission_view" 46 | msgstr "/submission/view" 47 | msgid "zikulaformiculamodule_user_index" 48 | msgstr "/" -------------------------------------------------------------------------------- /Resources/views/Contact/edit.html.twig: -------------------------------------------------------------------------------- 1 |

2 | 3 | {{ mode == 'create' ? 'Add contact'|trans : 'Edit contact'|trans }} 4 | {{ pageSetVar('title', mode == 'create' ? 'Add contact'|trans : 'Edit contact'|trans) }} 5 |

6 | 7 | {{ form_start(form) }} 8 | {{ form_errors(form) }} 9 | 10 |
11 | {% trans %}Basic contact information{% endtrans %} 12 | {{ form_row(form.name) }} 13 | {{ form_row(form.email) }} 14 | {{ form_row(form.public) }} 15 |
16 |
17 | {% trans %}User confirmation email data{% endtrans %} 18 | {{ form_row(form.senderName) }} 19 | {{ form_row(form.senderEmail) }} 20 | {{ form_row(form.sendingSubject) }} 21 |
22 |

{% trans %}You can use the following placeholders within the subject:{% endtrans %}

23 | 31 |
32 |
33 | 34 |
35 |
36 | {{ form_widget(form.save) }} 37 | {{ form_widget(form.cancel) }} 38 |
39 |
40 | 41 | {{ form_end(form) }} 42 | -------------------------------------------------------------------------------- /Menu/ExtensionMenu.php: -------------------------------------------------------------------------------- 1 | factory->createItem('formiculaAdminMenu'); 24 | if ($this->permissionApi->hasPermission($this->getBundleName() . '::', '::', ACCESS_ADMIN)) { 25 | $menu->addChild('View contacts', [ 26 | 'route' => 'zikulaformiculamodule_contact_view', 27 | ])->setAttribute('icon', 'fas fa-users'); 28 | $menu->addChild('Add contact', [ 29 | 'route' => 'zikulaformiculamodule_contact_edit', 30 | ])->setAttribute('icon', 'fas fa-user-plus'); 31 | $menu->addChild('View submissions', [ 32 | 'route' => 'zikulaformiculamodule_submission_view', 33 | ])->setAttribute('icon', 'fas fa-envelope'); 34 | $menu->addChild('Settings', [ 35 | 'route' => 'zikulaformiculamodule_config_config', 36 | ])->setAttribute('icon', 'fas fa-wrench'); 37 | $menu->addChild('Clear captcha image cache', [ 38 | 'route' => 'zikulaformiculamodule_config_clearcache', 39 | ])->setAttribute('icon', 'fas fa-eraser'); 40 | } 41 | 42 | return 0 === $menu->count() ? null : $menu; 43 | } 44 | 45 | public function getBundleName(): string 46 | { 47 | return 'ZikulaFormiculaModule'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Twig/Extension/FormiculaCaptchaExtension.php: -------------------------------------------------------------------------------- 1 | captchaHelper = $captchaHelper; 30 | } 31 | 32 | public function getFunctions() 33 | { 34 | return [ 35 | new TwigFunction('zikulaformiculamodule_simpleCaptcha', [$this, 'simpleCaptcha'], ['is_safe' => ['html']]) 36 | ]; 37 | } 38 | 39 | /** 40 | * The zikulaformiculamodule_simpleCaptcha function adds a simplecaptcha image to a form. 41 | * 42 | * Example: 43 | * {{ zikulaformiculamodule_simpleCaptcha(font='quikhand', size=14, bgColour='ffffff', fgColour='000000') }} 44 | * 45 | * @param string $font Name of font to use (arial, freesans, quickhand, vera) 46 | * @param int $size Font size 47 | * @param string $bgColour Background colour (hex code without the # char) 48 | * @param string $fgColour Foreground colour (hex code without the # char) 49 | * 50 | * @return string The image markup 51 | */ 52 | public function simpleCaptcha($font = 'quickhand', $size = 14, $bgColour = 'ffffff', $fgColour = '000000'): string 53 | { 54 | return $this->captchaHelper->createCaptcha($font, $size, $bgColour, $fgColour); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Resources/views/Form/0/userForm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/0/userHeader.html.twig') }} 2 | {{ form_start(form) }} 3 | {{ form_errors(form) }} 4 | 5 |

{% trans %}Mandatory fields are indicated with an asterisk.{% endtrans %}

6 | 7 |
8 | {% trans %}Contact our team{% endtrans %} 9 | {{ form_row(form.form) }} 10 | {{ form_row(form.adminFormat) }} 11 | {% if modVars.sendConfirmationToUser and not modVars.showUserFormat %} 12 | {{ form_row(form.userFormat) }} 13 | {% endif %} 14 | {{ form_row(form.cid) }} 15 | {{ form_row(form.name) }} 16 | {% if modVars.showCompany %} 17 | {{ form_row(form.company) }} 18 | {% endif %} 19 | {{ form_row(form.emailAddress) }} 20 | {% if modVars.showPhone %} 21 | {{ form_row(form.phone) }} 22 | {% endif %} 23 | {% if modVars.showUrl %} 24 | {{ form_row(form.url) }} 25 | {% endif %} 26 | {% if modVars.showLocation %} 27 | {{ form_row(form.location) }} 28 | {% endif %} 29 | {% if modVars.showComment %} 30 | {{ form_row(form.comment) }} 31 | {% endif %} 32 | {% if modVars.sendConfirmationToUser and modVars.showUserFormat %} 33 | {{ form_row(form.userFormat) }} 34 | {% endif %} 35 | {% if modVars.showFileAttachment %} 36 | {{ form_row(form.fileUpload) }} 37 | {% endif %} 38 | 39 | {% if enableSpamCheck %} 40 | {{ include('@ZikulaFormiculaModule/Include/spamCheck.html.twig') }} 41 | {% endif %} 42 |
43 | 44 | {% set hooks = notifyDisplayHooks(eventName='zikulaformiculamodule.ui_hooks.forms.form_edit') %} 45 | {% if hooks is iterable and hooks|length > 0 %} 46 | {% for area, hook in hooks %} 47 |
{{ hook|raw }}
48 | {% endfor %} 49 | {% endif %} 50 | 51 |
52 |
53 | {{ form_widget(form.submit) }} 54 |
55 |
56 | 57 | {{ form_end(form) }} 58 | 59 | {{ include('@ZikulaFormiculaModule/Form/0/userFooter.html.twig') }} 60 | -------------------------------------------------------------------------------- /Resources/views/Form/2/userForm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/2/userHeader.html.twig') }} 2 | {{ form_start(form) }} 3 | {{ form_errors(form) }} 4 | 5 |

{% trans %}Mandatory fields are indicated with an asterisk.{% endtrans %}

6 | 7 |
8 | {% trans %}Contact our team{% endtrans %} 9 | {{ form_row(form.form) }} 10 | {{ form_row(form.adminFormat) }} 11 | {% if modVars.sendConfirmationToUser and not modVars.showUserFormat %} 12 | {{ form_row(form.userFormat) }} 13 | {% endif %} 14 | {{ form_row(form.cid) }} 15 | {{ form_row(form.name) }} 16 | {% if modVars.showCompany %} 17 | {{ form_row(form.company) }} 18 | {% endif %} 19 | {{ form_row(form.emailAddress) }} 20 | {% if modVars.showPhone %} 21 | {{ form_row(form.phone) }} 22 | {% endif %} 23 | {% if modVars.showUrl %} 24 | {{ form_row(form.url) }} 25 | {% endif %} 26 | {% if modVars.showLocation %} 27 | {{ form_row(form.location) }} 28 | {% endif %} 29 | {% if modVars.showComment %} 30 | {{ form_row(form.comment) }} 31 | {% endif %} 32 | {% if modVars.sendConfirmationToUser and modVars.showUserFormat %} 33 | {{ form_row(form.userFormat) }} 34 | {% endif %} 35 | {% if modVars.showFileAttachment %} 36 | {{ form_row(form.fileUpload) }} 37 | {% endif %} 38 | 39 | {% if enableSpamCheck %} 40 | {{ include('@ZikulaFormiculaModule/Include/spamCheck.html.twig') }} 41 | {% endif %} 42 |
43 | 44 | {% set hooks = notifyDisplayHooks(eventName='zikulaformiculamodule.ui_hooks.forms.form_edit') %} 45 | {% if hooks is iterable and hooks|length > 0 %} 46 | {% for area, hook in hooks %} 47 |
{{ hook|raw }}
48 | {% endfor %} 49 | {% endif %} 50 | 51 |
52 |
53 | {{ form_widget(form.submit) }} 54 |
55 |
56 | 57 | {{ form_end(form) }} 58 | 59 | {{ include('@ZikulaFormiculaModule/Form/2/userFooter.html.twig') }} 60 | -------------------------------------------------------------------------------- /Resources/views/Submission/delete.html.twig: -------------------------------------------------------------------------------- 1 |

2 | 3 | {% trans %}Delete form submission{% endtrans %} 4 | {{ pageSetVar('title', 'Delete form submission'|trans) }} 5 |

6 | 7 | {{ form_start(form) }} 8 | {{ form_errors(form) }} 9 | 10 |
11 | {% trans %}Confirmation prompt{% endtrans %} 12 |

{% trans with { '%s%': submission.name } %}Do you really want to delete form submission '%s%'?{% endtrans %}

13 | 14 | {{ form_row(form.sid) }} 15 |
16 |
17 | {% trans %}Submission information{% endtrans %} 18 |
19 | 20 |
21 |

{{ submission.form }}

22 |
23 |
24 |
25 | 26 |
27 |

{{ submission.cid }}

28 |
29 |
30 |
31 | 32 |
33 |

{{ submission.createdDate|format_date('short', 'short') }}

34 |
35 |
36 |
37 | 38 | 41 |
42 |
43 | 44 |
45 |
46 | {{ form_widget(form.delete) }} 47 | {{ form_widget(form.cancel) }} 48 |
49 |
50 | 51 | {{ form_end(form) }} 52 | -------------------------------------------------------------------------------- /Resources/views/Contact/view.html.twig: -------------------------------------------------------------------------------- 1 |

2 | 3 | {% trans %}View contacts{% endtrans %} 4 | {{ pageSetVar('title', 'View contacts'|trans) }} 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {% for contact in contacts %} 25 | 26 | 27 | 28 | 29 | 30 | 38 | 39 | {% else %} 40 | 41 | 42 | 43 | {% endfor %} 44 | 45 |
{% trans %}ID{% endtrans %}{% trans %}Name{% endtrans %}{% trans %}Email{% endtrans %}{% trans %}Public{% endtrans %}{% trans %}Actions{% endtrans %}
{{ contact.cid }}{{ contact.name }}{{ contact.email }}{{ contact.public|yesNo }} 31 | {% if contact.allowEdit %} 32 | 33 | {% endif %} 34 | {% if contact.allowDelete %} 35 | 36 | {% endif %} 37 |
{% trans %}No contacts found.{% endtrans %}
46 | -------------------------------------------------------------------------------- /Resources/views/Submission/view.html.twig: -------------------------------------------------------------------------------- 1 |

2 | 3 | {% trans %}View form submissions{% endtrans %} 4 | {{ pageSetVar('title', 'View form submissions'|trans) }} 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% for submission in submissions %} 27 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 38 | {% else %} 39 | 40 | 41 | 42 | {% endfor %} 43 | 44 |
{% trans %}ID{% endtrans %}{% trans %}Form #{% endtrans %}{% trans %}Contact ID{% endtrans %}{% trans %}Date{% endtrans %}{% trans %}Name{% endtrans %}{% trans %}Actions{% endtrans %}
{{ submission.sid }}{{ submission.form }}{{ submission.cid }}{{ submission.createdDate|format_date('short', 'short') }}{{ submission.name }} 34 | 35 | 36 |
{% trans %}No submissions found.{% endtrans %}
45 | {{ adminFooter() }} 46 | -------------------------------------------------------------------------------- /ContentType/Form/Type/FormType.php: -------------------------------------------------------------------------------- 1 | setTranslator($translator); 41 | $this->contactRepository = $contactRepository; 42 | } 43 | 44 | public function buildForm(FormBuilderInterface $builder, array $options) 45 | { 46 | $allContacts = $this->contactRepository->findBy([], ['name' => 'ASC']); 47 | $contactChoices = []; 48 | $contactChoices[$this->trans('All public contacts or form default')] = -1; 49 | 50 | // only use public contacts 51 | foreach ($allContacts as $contact) { 52 | if (!$contact->isPublic()) { 53 | continue; 54 | } 55 | 56 | $contactChoices[$contact->getName()] = $contact->getCid(); 57 | } 58 | 59 | $builder 60 | ->add('form', IntegerType::class, [ 61 | 'label' => $this->trans('Form #') 62 | ]) 63 | ->add('contact', ChoiceType::class, [ 64 | 'label' => $this->trans('Show contact'), 65 | 'choices' => $contactChoices 66 | ]) 67 | ; 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | public function getBlockPrefix() 74 | { 75 | return 'zikulaformiculamodule_contenttype_form'; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Resources/views/Config/config.html.twig: -------------------------------------------------------------------------------- 1 | {{ pageAddAsset('javascript', zasset('@ZikulaFormiculaModule:js/ZikulaFormiculaModule.Config.js')) }} 2 |

3 | 4 | {% trans %}Settings{% endtrans %} 5 | {{ pageSetVar('title', 'Formicula settings'|trans) }} 6 |

7 | 8 | {{ form_start(form) }} 9 | {{ form_errors(form) }} 10 | 11 |
12 | {% trans %}General settings{% endtrans %} 13 | {{ form_row(form.defaultForm) }} 14 | {{ form_row(form.showCompany) }} 15 | {{ form_row(form.showPhone) }} 16 | {{ form_row(form.showUrl) }} 17 | {{ form_row(form.showLocation) }} 18 | {{ form_row(form.showComment) }} 19 |
20 |
21 | {% trans %}File upload settings{% endtrans %} 22 | {{ form_row(form.showFileAttachment) }} 23 | {{ form_row(form.uploadDirectory) }} 24 | {{ form_row(form.deleteUploadedFiles) }} 25 |
26 |
27 | {% trans %}Email and confirmation settings{% endtrans %} 28 | {{ form_row(form.sendConfirmationToUser) }} 29 | {{ form_row(form.defaultAdminFormat) }} 30 | {{ form_row(form.defaultUserFormat) }} 31 | {{ form_row(form.showUserFormat) }} 32 | {{ form_row(form.useContactsAsSender) }} 33 |
34 |
35 | {% trans %}Spam check settings{% endtrans %} 36 |

{% trans %}For your information: There are better spam check modules out there. For example the Zikula Captcha module which can be hooked to Formicula. If you want to use this module, then please do not forget to add the required permissions for the Captcha module, too.{% endtrans %}

37 | {{ form_row(form.enableSpamCheck) }} 38 |
39 |
40 | 41 |
42 | {{ cacheDirectory }} 43 |
44 |
45 |
46 | {{ form_row(form.excludeSpamCheck) }} 47 |
48 |
49 | {% trans %}Form submission storage{% endtrans %} 50 | {{ form_row(form.storeSubmissionData) }} 51 |
52 | {{ form_row(form.storeSubmissionDataForms) }} 53 |
54 |
55 | 56 |
57 |
58 | {{ form_widget(form.save) }} 59 | {{ form_widget(form.cancel) }} 60 |
61 |
62 | 63 | {{ form_end(form) }} 64 | -------------------------------------------------------------------------------- /HookSubscriber/FormUiHooksSubscriber.php: -------------------------------------------------------------------------------- 1 | translator = $translator; 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function getOwner(): string 42 | { 43 | return 'ZikulaFormiculaModule'; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getCategory(): string 50 | { 51 | return UiHooksCategory::NAME; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function getTitle(): string 58 | { 59 | return $this->translator->trans('Form ui hooks subscriber'); 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | */ 65 | public function getEvents(): array 66 | { 67 | return [ 68 | // Display hook for view/display templates. 69 | //UiHooksCategory::TYPE_DISPLAY_VIEW => 'zikulaformiculamodule.ui_hooks.forms.display_view', 70 | // Display hook for create/edit forms. 71 | UiHooksCategory::TYPE_FORM_EDIT => 'zikulaformiculamodule.ui_hooks.forms.form_edit', 72 | // Validate input from an item to be edited. 73 | UiHooksCategory::TYPE_VALIDATE_EDIT => 'zikulaformiculamodule.ui_hooks.forms.validate_edit', 74 | // Perform the final update actions for an edited item. 75 | //UiHooksCategory::TYPE_PROCESS_EDIT => 'zikulaformiculamodule.ui_hooks.forms.process_edit', 76 | // Validate input from an item to be deleted. 77 | //UiHooksCategory::TYPE_VALIDATE_DELETE => 'zikulaformiculamodule.ui_hooks.forms.validate_delete', 78 | // Perform the final delete actions for a deleted item. 79 | //UiHooksCategory::TYPE_PROCESS_DELETE => 'zikulaformiculamodule.ui_hooks.forms.process_delete' 80 | ]; 81 | } 82 | 83 | public function getAreaName(): string 84 | { 85 | return 'subscriber.zikulaformiculamodule.ui_hooks.forms'; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Traits/StandardFieldsTrait.php: -------------------------------------------------------------------------------- 1 | createdBy; 62 | } 63 | 64 | public function setCreatedBy(UserEntity $createdBy = null): void 65 | { 66 | if ($this->createdBy !== $createdBy) { 67 | $this->createdBy = $createdBy; 68 | } 69 | } 70 | 71 | public function getCreatedDate(): ?DateTimeInterface 72 | { 73 | return $this->createdDate; 74 | } 75 | 76 | public function setCreatedDate(DateTimeInterface $createdDate = null): void 77 | { 78 | if ($this->createdDate !== $createdDate) { 79 | $this->createdDate = $createdDate; 80 | } 81 | } 82 | 83 | public function getUpdatedBy(): ?UserEntity 84 | { 85 | return $this->updatedBy; 86 | } 87 | 88 | public function setUpdatedBy(UserEntity $updatedBy = null): void 89 | { 90 | if ($this->updatedBy !== $updatedBy) { 91 | $this->updatedBy = $updatedBy; 92 | } 93 | } 94 | 95 | public function getUpdatedDate(): ?DateTimeInterface 96 | { 97 | return $this->updatedDate; 98 | } 99 | 100 | public function setUpdatedDate(DateTimeInterface $updatedDate = null): void 101 | { 102 | if ($this->updatedDate !== $updatedDate) { 103 | $this->updatedDate = $updatedDate; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Form/Type/EditContactType.php: -------------------------------------------------------------------------------- 1 | add('name', TextType::class, [ 34 | 'label' => 'Contact name', 35 | 'attr' => [ 36 | 'maxlength' => 100 37 | ] 38 | ]) 39 | ->add('email', TextType::class, [ 40 | 'label' => 'Email address(es)', 41 | 'attr' => [ 42 | 'maxlength' => 200 43 | ], 44 | 'help' => 'You may enter a single address or a comma separated list of addresses.' 45 | ]) 46 | ->add('public', CheckboxType::class, [ 47 | 'label' => 'Public', 48 | 'required' => false 49 | ]) 50 | ->add('senderName', TextType::class, [ 51 | 'label' => 'Sender name', 52 | 'required' => false, 53 | 'attr' => [ 54 | 'maxlength' => 100 55 | ] 56 | ]) 57 | ->add('senderEmail', EmailType::class, [ 58 | 'label' => 'Sender email address', 59 | 'required' => false, 60 | 'attr' => [ 61 | 'maxlength' => 100 62 | ] 63 | ]) 64 | ->add('sendingSubject', TextType::class, [ 65 | 'label' => 'Subject', 66 | 'required' => false, 67 | 'attr' => [ 68 | 'maxlength' => 150 69 | ] 70 | ]) 71 | ->add('save', SubmitType::class, [ 72 | 'label' => 'Save', 73 | 'icon' => 'fa-check', 74 | 'attr' => [ 75 | 'class' => 'btn-success' 76 | ] 77 | ]) 78 | ->add('cancel', SubmitType::class, [ 79 | 'label' => 'Cancel', 80 | 'icon' => 'fa-times' 81 | ]) 82 | ; 83 | } 84 | 85 | public function getBlockPrefix() 86 | { 87 | return 'zikulaformiculamodule_editcontact'; 88 | } 89 | 90 | public function configureOptions(OptionsResolver $resolver) 91 | { 92 | $resolver->setDefaults([ 93 | 'data_class' => ContactEntity::class, 94 | ]); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Resources/views/Form/0/userConfirm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/0/userHeader.html.twig') }} 2 | 3 |

4 | {% trans %}Thank you for your questions/comments to our website!{% endtrans %}
5 | {% trans %}We will reply as soon as possible.{% endtrans %} 6 |

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% if modVars.showCompany and userData.company %} 26 | 27 | 28 | 29 | 30 | {% endif %} 31 | 32 | 33 | 34 | 35 | {% if modVars.showPhone and userData.phone %} 36 | 37 | 38 | 39 | 40 | {% endif %} 41 | {% if modVars.showUrl and userData.url %} 42 | 43 | 44 | 45 | 46 | {% endif %} 47 | {% if modVars.showLocation and userData.location %} 48 | 49 | 50 | 51 | 52 | {% endif %} 53 | {% for field in customFields %} 54 | 55 | 56 | 57 | 58 | {% endfor %} 59 | {% if modVars.showComment and userData.comment %} 60 | 61 | 62 | 63 | 64 | {% endif %} 65 | {% if modVars.showFileAttachment and userData.fileUpload %} 66 | 67 | 68 | 69 | 70 | {% endif %} 71 | 72 |
{% trans %}This data was sent to us:{% endtrans %}
{% trans %}Field{% endtrans %}{% trans %}Value{% endtrans %}
{% trans %}Your name{% endtrans %}{{ userData.name }}
{% trans %}Company{% endtrans %}{{ userData.company }}
{% trans %}Email{% endtrans %}{{ userData.emailAddress }}
{% trans %}Phone number{% endtrans %}{{ userData.phone }}
{% trans %}Website{% endtrans %}{{ userData.url }}
{% trans %}Location{% endtrans %}{{ userData.location }}
{{ field.name }}{{ field.data }}
{% trans %}Comment{% endtrans %}{{ userFormat == 'html' ? userData.comment : userData.comment|nl2br }}
{% trans %}Attached file{% endtrans %}{{ userData.fileUpload }}
73 | 74 | {% if modVars.sendConfirmationToUser %} 75 |

76 | {% if sentToUser %} 77 | {% trans %}Confirmation of your submission will be emailed to you in a few minutes.{% endtrans %} 78 | {% else %} 79 | {% trans %}There was an internal error when sending confirmation mail to you.{% endtrans %} 80 | {% endif %} 81 |

82 | {% endif %} 83 | 84 | {{ include('@ZikulaFormiculaModule/Form/0/userFooter.html.twig') }} 85 | -------------------------------------------------------------------------------- /Resources/views/Form/1/userConfirm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/1/userHeader.html.twig') }} 2 | 3 |

4 | {% trans %}Thanks for applying, we will keep your data strictly confidential.{% endtrans %} 5 |

6 |

{% trans %}This data was sent to us:{% endtrans %}

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% if modVars.showCompany and userData.company %} 26 | 27 | 28 | 29 | 30 | {% endif %} 31 | 32 | 33 | 34 | 35 | {% if modVars.showPhone and userData.phone %} 36 | 37 | 38 | 39 | 40 | {% endif %} 41 | {% if modVars.showUrl and userData.url %} 42 | 43 | 44 | 45 | 46 | {% endif %} 47 | {% if modVars.showLocation and userData.location %} 48 | 49 | 50 | 51 | 52 | {% endif %} 53 | {% for field in customFields %} 54 | 55 | 56 | 57 | 58 | {% endfor %} 59 | {% if modVars.showComment and userData.comment %} 60 | 61 | 62 | 63 | 64 | {% endif %} 65 | {% if modVars.showFileAttachment and userData.fileUpload %} 66 | 67 | 68 | 69 | 70 | {% endif %} 71 | 72 |
{% trans %}This data was sent to us:{% endtrans %}
{% trans %}Field{% endtrans %}{% trans %}Value{% endtrans %}
{% trans %}Your name{% endtrans %}{{ userData.name }}
{% trans %}Company{% endtrans %}{{ userData.company }}
{% trans %}Email{% endtrans %}{{ userData.emailAddress }}
{% trans %}Phone number{% endtrans %}{{ userData.phone }}
{% trans %}Website{% endtrans %}{{ userData.url }}
{% trans %}Location{% endtrans %}{{ userData.location }}
{{ field.name }}{{ field.data }}
{% trans %}Comment{% endtrans %}{{ userFormat == 'html' ? userData.comment : userData.comment|nl2br }}
{% trans %}Attached file{% endtrans %}{{ userData.fileUpload }}
73 | 74 | {% if modVars.sendConfirmationToUser %} 75 |

76 | {% if sentToUser %} 77 | {% trans %}Confirmation of your submission will be emailed to you in a few minutes.{% endtrans %} 78 | {% else %} 79 | {% trans %}There was an internal error when sending confirmation mail to you.{% endtrans %} 80 | {% endif %} 81 |

82 | {% endif %} 83 | 84 | {{ include('@ZikulaFormiculaModule/Form/1/userFooter.html.twig') }} 85 | -------------------------------------------------------------------------------- /Resources/views/Form/2/userConfirm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/2/userHeader.html.twig') }} 2 | 3 |

4 | {% trans %}Thank you for your questions/comments to our website!{% endtrans %}
5 | {% trans %}We will reply as soon as possible.{% endtrans %} 6 |

7 |

{% trans %}This data was sent to us:{% endtrans %}

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% if modVars.showCompany and userData.company %} 27 | 28 | 29 | 30 | 31 | {% endif %} 32 | 33 | 34 | 35 | 36 | {% if modVars.showPhone and userData.phone %} 37 | 38 | 39 | 40 | 41 | {% endif %} 42 | {% if modVars.showUrl and userData.url %} 43 | 44 | 45 | 46 | 47 | {% endif %} 48 | {% if modVars.showLocation and userData.location %} 49 | 50 | 51 | 52 | 53 | {% endif %} 54 | {% for field in customFields %} 55 | 56 | 57 | 58 | 59 | {% endfor %} 60 | {% if modVars.showComment and userData.comment %} 61 | 62 | 63 | 64 | 65 | {% endif %} 66 | {% if modVars.showFileAttachment and userData.fileUpload %} 67 | 68 | 69 | 70 | 71 | {% endif %} 72 | 73 |
{% trans %}This data was sent to us:{% endtrans %}
{% trans %}Field{% endtrans %}{% trans %}Value{% endtrans %}
{% trans %}Your name{% endtrans %}{{ userData.name }}
{% trans %}Company{% endtrans %}{{ userData.company }}
{% trans %}Email{% endtrans %}{{ userData.emailAddress }}
{% trans %}Phone number{% endtrans %}{{ userData.phone }}
{% trans %}Website{% endtrans %}{{ userData.url }}
{% trans %}Location{% endtrans %}{{ userData.location }}
{{ field.name }}{{ field.data }}
{% trans %}Comment{% endtrans %}{{ userFormat == 'html' ? userData.comment : userData.comment|nl2br }}
{% trans %}Attached file{% endtrans %}{{ userData.fileUpload }}
74 | 75 | {% if modVars.sendConfirmationToUser %} 76 |

77 | {% if sentToUser %} 78 | {% trans %}Confirmation of your submission will be emailed to you in a few minutes.{% endtrans %} 79 | {% else %} 80 | {% trans %}There was an internal error when sending confirmation mail to you.{% endtrans %} 81 | {% endif %} 82 |

83 | {% endif %} 84 | 85 | {{ include('@ZikulaFormiculaModule/Form/2/userFooter.html.twig') }} 86 | -------------------------------------------------------------------------------- /Resources/views/Form/3/userConfirm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/3/userHeader.html.twig') }} 2 | 3 |
4 |

{% trans with { '%s%': userData.uname } %}Thank you %s% for your reservation.{% endtrans %}

5 |

{% trans with { '%s%': userData.uemail } %}An email with the filled in data will be sent to our and your email address (%s%). We will reply as soon as possible.{% endtrans %}

6 |
7 |

{% trans %}This data was sent to us:{% endtrans %}

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% if modVars.showCompany and userData.company %} 27 | 28 | 29 | 30 | 31 | {% endif %} 32 | 33 | 34 | 35 | 36 | {% if modVars.showPhone and userData.phone %} 37 | 38 | 39 | 40 | 41 | {% endif %} 42 | {% if modVars.showUrl and userData.url %} 43 | 44 | 45 | 46 | 47 | {% endif %} 48 | {% if modVars.showLocation and userData.location %} 49 | 50 | 51 | 52 | 53 | {% endif %} 54 | {% for field in customFields %} 55 | 56 | 57 | 58 | 59 | {% endfor %} 60 | {% if modVars.showComment and userData.comment %} 61 | 62 | 63 | 64 | 65 | {% endif %} 66 | {% if modVars.showFileAttachment and userData.fileUpload %} 67 | 68 | 69 | 70 | 71 | {% endif %} 72 | 73 |
{% trans %}This data was sent to us:{% endtrans %}
{% trans %}Field{% endtrans %}{% trans %}Value{% endtrans %}
{% trans %}Your name{% endtrans %}{{ userData.name }}
{% trans %}Company{% endtrans %}{{ userData.company }}
{% trans %}Email{% endtrans %}{{ userData.emailAddress }}
{% trans %}Phone number{% endtrans %}{{ userData.phone }}
{% trans %}Website{% endtrans %}{{ userData.url }}
{% trans %}Location{% endtrans %}{{ userData.location }}
{{ field.name }}{{ field.data }}
{% trans %}Comment{% endtrans %}{{ userFormat == 'html' ? userData.comment : userData.comment|nl2br }}
{% trans %}Attached file{% endtrans %}{{ userData.fileUpload }}
74 | 75 | {% if modVars.sendConfirmationToUser %} 76 |

77 | {% if sentToUser %} 78 | {% trans %}Confirmation of your submission will be emailed to you in a few minutes.{% endtrans %} 79 | {% else %} 80 | {% trans %}There was an internal error when sending confirmation mail to you.{% endtrans %} 81 | {% endif %} 82 |

83 | {% endif %} 84 | 85 | {{ include('@ZikulaFormiculaModule/Form/3/userFooter.html.twig') }} 86 | -------------------------------------------------------------------------------- /ContentType/FormType.php: -------------------------------------------------------------------------------- 1 | translator->trans('Formicula form'); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getDescription(): string 56 | { 57 | return $this->translator->trans('Display a specific Formicula form.'); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function getDefaultData(): array 64 | { 65 | return [ 66 | 'form' => 0, 67 | 'contact' => -1 68 | ]; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function displayView(): string 75 | { 76 | $this->data = $this->getData(); 77 | if (null === $this->data['form'] || (int) ($this->data['form']) < 0) { 78 | return ''; 79 | } 80 | 81 | $attributes = [ 82 | '_controller' => 'Zikula\FormiculaModule\Controller\UserController::index', 83 | '_route' => 'zikulaformiculamodule_user_index' 84 | ]; 85 | 86 | $subRequest = $this->requestStack->getCurrentRequest()->duplicate([ 87 | 'form' => (int) $this->data['form'], 88 | 'cid' => $this->data['contact'] 89 | ], null, $attributes); 90 | 91 | $response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); 92 | 93 | return $response->getContent(); 94 | } 95 | 96 | /** 97 | * {@inheritdoc} 98 | */ 99 | public function displayEditing(): string 100 | { 101 | $this->data = $this->getData(); 102 | if (null === $this->data['form'] || (int) ($this->data['form']) < 0) { 103 | return $this->translator->trans('No form selected.'); 104 | } 105 | 106 | if ($this->data['contact'] > 0) { 107 | $output = '

' . $this->translator->trans('The Formicula form #%num% is shown here with only contact %con%', ['%num%' => $this->data['form'], '%con%' => $this->data['contact']]) . '

'; 108 | } else { 109 | $output = '

' . $this->translator->trans('The Formicula form #%num% is shown here with all contacts', ['%num%' => $this->data['form']]) . '

'; 110 | } 111 | 112 | return $output; 113 | } 114 | 115 | /** 116 | * {@inheritdoc} 117 | */ 118 | public function getEditFormClass(): string 119 | { 120 | return EditFormType::class; 121 | } 122 | 123 | /** 124 | * @required 125 | */ 126 | public function setRequestStack(RequestStack $requestStack) 127 | { 128 | $this->requestStack = $requestStack; 129 | } 130 | 131 | /** 132 | * @required 133 | */ 134 | public function setHttpKernel(HttpKernelInterface $httpKernel) 135 | { 136 | $this->httpKernel = $httpKernel; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Helper/EnvironmentHelper.php: -------------------------------------------------------------------------------- 1 | kernel = $kernel; 57 | $this->translator = $translator; 58 | $this->variableApi = $variableApi; 59 | $this->requestStack = $requestStack; 60 | $this->cacheDirectory = $cacheDir; 61 | } 62 | 63 | /** 64 | * Checks some environment aspects and sets error messages. 65 | */ 66 | public function check(): void 67 | { 68 | $request = $this->requestStack->getCurrentRequest(); 69 | $flashBag = null !== $request ? $request->getSession()->getFlashBag() : null; 70 | if (null === $flashBag) { 71 | return; 72 | } 73 | 74 | if (null === $this->kernel->getModule('ZikulaMailerModule')) { 75 | $flashBag->add('error', $this->translator->trans('Mailer module is not available - unable to send emails!')); 76 | } 77 | 78 | if (false === $this->variableApi->get('ZikulaFormiculaModule', 'enableSpamCheck', true)) { 79 | return; 80 | } 81 | 82 | if (!function_exists('imagettfbbox') 83 | || (!(imagetypes() && IMG_PNG) && !(imagetypes() && IMG_JPG) && !(imagetypes() && IMG_GIF)) 84 | ) { 85 | $flashBag->add('status', $this->translator->trans('There are no image function available - Captchas have been disabled.')); 86 | $this->variableApi->set('ZikulaFormiculaModule', 'enableSpamCheck', false); 87 | } 88 | 89 | if (!file_exists($this->cacheDirectory) || !is_writable($this->cacheDirectory)) { 90 | $flashBag->add('status', $this->translator->trans('Formicula cache directory does not exist or is not writable - Captchas have been disabled.')); 91 | $this->variableApi->set('ZikulaFormiculaModule', 'enableSpamCheck', false); 92 | } elseif (!file_exists($this->cacheDirectory . '/.htaccess')) { 93 | $flashBag->add('status', $this->translator->trans('Formicula cache directory does not contain the required .htaccess file - Captchas have been disabled.')); 94 | $this->variableApi->set('ZikulaFormiculaModule', 'enableSpamCheck', false); 95 | } 96 | } 97 | 98 | public function clearCache(): void 99 | { 100 | if (!file_exists($this->cacheDirectory) || !is_writable($this->cacheDirectory)) { 101 | return; 102 | } 103 | 104 | $files = (new Finder())->files()->in($this->cacheDirectory) 105 | ->notName(['.htaccess', 'index.htm', 'index.html']) 106 | ; 107 | foreach ($files as $file) { 108 | unlink($file->getRealPath()); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Resources/views/Submission/display.html.twig: -------------------------------------------------------------------------------- 1 |

2 | 3 | {% trans %}View submitted form data{% endtrans %} 4 | {{ pageSetVar('title', 'View submitted form data'|trans) }} 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
{% trans %}Date{% endtrans %}{% trans %}Name{% endtrans %}{% trans %}IP address{% endtrans %}{% trans %}Hostname{% endtrans %}{% trans %}Contact ID{% endtrans %}
{{ submission.createdDate|format_date('short', 'short') }}{{ submission.name }}{{ submission.ipAddress }}{{ submission.hostName }}{{ submission.cid }}
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
{% trans %}Website{% endtrans %}{% trans %}Company{% endtrans %}{% trans %}Phone number{% endtrans %}{% trans %}Location{% endtrans %}
{% if submission.url != '' %}{{ submission.url }}{% else %}{% trans %}None{% endtrans %}{% endif %}{{ submission.company|default('None'|trans) }}{{ submission.phoneNumber|default('None'|trans) }}{{ submission.location|default('None'|trans) }}
57 | {% if submission.customData|length > 0 %} 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | {% for key, value in submission.customData %} 71 | 72 | 73 | 74 | 75 | {% endfor %} 76 | 77 |
{% trans %}Custom fields{% endtrans %}
{% trans %}Name{% endtrans %}{% trans %}Value{% endtrans %}
{{ key }}{{ value }}
78 | {% endif %} 79 | {% if submission.comment != '' %} 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 |
{% trans %}Comment{% endtrans %}
{{ submission.comment|safeHtml|nl2br }}
95 | {% endif %} 96 | -------------------------------------------------------------------------------- /Controller/ConfigController.php: -------------------------------------------------------------------------------- 1 | environmentHelper = $environmentHelper; 51 | } 52 | 53 | /** 54 | * @Route("/config") 55 | * @Template("@ZikulaFormiculaModule/Config/config.html.twig") 56 | * @Theme("admin") 57 | */ 58 | public function config(Request $request, string $cacheDir): array 59 | { 60 | // check necessary environment 61 | $this->environmentHelper->check(); 62 | 63 | $modVars = $this->getVars(); 64 | 65 | // scan the templates folder for installed forms 66 | $templateDirectory = __DIR__ . '/../Resources/views/Form/'; 67 | $formChoices = []; 68 | $finder = new Finder(); 69 | 70 | foreach ($finder->directories()->in($templateDirectory)->sortByName() as $directory) { 71 | $finder2 = new Finder(); 72 | $finder2->files()->in($directory->getRealPath()); 73 | $formNumber = $directory->getFilename(); 74 | $label = $this->trans( 75 | 'Form #%num% containing %count% templates', 76 | [ 77 | '%num%' => $formNumber, 78 | '%count%' => count($finder2) 79 | ] 80 | ); 81 | $formChoices[$label] = $formNumber; 82 | } 83 | 84 | $form = $this->createForm( 85 | ConfigType::class, 86 | $modVars, 87 | [ 88 | 'formChoices' => $formChoices 89 | ] 90 | ); 91 | $form->handleRequest($request); 92 | if ($form->isSubmitted() && $form->isValid()) { 93 | if ($form->get('save')->isClicked()) { 94 | $formData = $form->getData(); 95 | 96 | if (!empty($formData['uploadDirectory']) && !is_writable($formData['uploadDirectory'])) { 97 | $this->addFlash('error', 'The webserver cannot write into the upload directory!'); 98 | } else { 99 | // remove spaces in the comma separated forms lists 100 | $formData['excludeSpamCheck'] = preg_replace('/\s*/m', '', $formData['excludeSpamCheck']); 101 | $formData['storeSubmissionDataForms'] = preg_replace('/\s*/m', '', $formData['storeSubmissionDataForms']); 102 | 103 | $this->setVars($formData); 104 | 105 | $this->addFlash('status', 'Done! Configuration updated.'); 106 | } 107 | } elseif ($form->get('cancel')->isClicked()) { 108 | $this->addFlash('status', 'Operation cancelled.'); 109 | } 110 | } 111 | 112 | $templateParameters = array_merge($modVars, [ 113 | 'form' => $form->createView(), 114 | 'cacheDirectory' => $cacheDir 115 | ]); 116 | 117 | return $templateParameters; 118 | } 119 | 120 | /** 121 | * Clear image cache. 122 | * 123 | * @Route("/clearcache") 124 | * @Theme("admin") 125 | */ 126 | public function clearCache(): RedirectResponse 127 | { 128 | $this->environmentHelper->clearCache(); 129 | $this->addFlash('status', 'The captcha image cache has been cleared.'); 130 | 131 | return $this->redirectToRoute('zikulaformiculamodule_contact_view'); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /Controller/SubmissionController.php: -------------------------------------------------------------------------------- 1 | submissionRepository = $submissionRepository; 55 | $this->environmentHelper = $environmentHelper; 56 | } 57 | 58 | /** 59 | * Shows a list of submissions. 60 | * 61 | * @Route("/view") 62 | * @PermissionCheck("admin") 63 | * @Template("@ZikulaFormiculaModule/Submission/view.html.twig") 64 | * @Theme("admin") 65 | */ 66 | public function view(Request $request) 67 | { 68 | // check necessary environment 69 | $this->environmentHelper->check(); 70 | 71 | $submissions = $this->submissionRepository->findBy([], ['sid' => 'DESC']); 72 | 73 | return [ 74 | 'submissions' => $submissions 75 | ]; 76 | } 77 | 78 | /** 79 | * Shows a specific form submission. 80 | * 81 | * @Route("/display") 82 | * @PermissionCheck("admin") 83 | * @Template("@ZikulaFormiculaModule/Submission/display.html.twig") 84 | * @Theme("admin") 85 | */ 86 | public function display(Request $request) 87 | { 88 | // check necessary environment 89 | $this->environmentHelper->check(); 90 | 91 | $submissionId = $request->query->getInt('sid', -1); 92 | $submission = $this->submissionRepository->find($submissionId); 93 | if (false === $submission) { 94 | $this->addFlash('error', 'Form submission could not be found.'); 95 | 96 | return $this->redirectToRoute('zikulaformiculamodule_submission_view'); 97 | } 98 | 99 | return [ 100 | 'submission' => $submission 101 | ]; 102 | } 103 | 104 | /** 105 | * Deletes an existing submit from the database. 106 | * 107 | * @Route("/delete") 108 | * @PermissionCheck("delete") 109 | * @Template("@ZikulaFormiculaModule/Submission/delete.html.twig") 110 | * @Theme("admin") 111 | */ 112 | public function delete(Request $request) 113 | { 114 | // check necessary environment 115 | $this->environmentHelper->check(); 116 | 117 | $entityManager = $this->getDoctrine()->getManager(); 118 | $submissionId = $request->query->getInt('sid', -1); 119 | 120 | $submission = $this->submissionRepository->find($submissionId); 121 | if (false === $submission) { 122 | $this->addFlash('error', 'Form submission could not be found.'); 123 | 124 | return $this->redirectToRoute('zikulaformiculamodule_submission_view'); 125 | } 126 | 127 | $form = $this->createForm(DeleteSubmissionType::class, $submission); 128 | $form->handleRequest($request); 129 | if ($form->isSubmitted() && $form->isValid()) { 130 | if ($form->get('delete')->isClicked()) { 131 | $submission = $form->getData(); 132 | $entityManager->remove($submission); 133 | $entityManager->flush(); 134 | $this->addFlash('status', 'Done! Submission deleted.'); 135 | } elseif ($form->get('cancel')->isClicked()) { 136 | $this->addFlash('status', 'Operation cancelled.'); 137 | } 138 | 139 | return $this->redirectToRoute('zikulaformiculamodule_submission_view'); 140 | } 141 | 142 | return [ 143 | 'form' => $form->createView(), 144 | 'submission' => $submission 145 | ]; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /Form/Type/UserSubmissionType.php: -------------------------------------------------------------------------------- 1 | add('form', HiddenType::class) 39 | ->add('adminFormat', HiddenType::class) 40 | ; 41 | if ($modVars['sendConfirmationToUser'] && !$modVars['showUserFormat']) { 42 | $builder->add('userFormat', HiddenType::class); 43 | } 44 | $builder 45 | ->add('cid', ChoiceType::class, [ 46 | 'label' => 'Contact', 47 | 'choices' => $options['contactChoices'], 48 | 'expanded' => false, 49 | 'multiple' => false 50 | ]) 51 | ->add('name', TextType::class, [ 52 | 'label' => 'Your name', 53 | 'attr' => [ 54 | 'maxlength' => 150 55 | ] 56 | ]) 57 | ; 58 | if ($modVars['showCompany']) { 59 | $builder->add('company', TextType::class, [ 60 | 'label' => 'Company', 61 | 'required' => false, 62 | 'attr' => [ 63 | 'maxlength' => 150 64 | ] 65 | ]); 66 | } 67 | $builder->add('emailAddress', EmailType::class, [ 68 | 'label' => 'Email address', 69 | 'attr' => [ 70 | 'maxlength' => 150, 71 | 'placeholder' => 'Enter a valid email address' 72 | ] 73 | ]); 74 | if ($modVars['showPhone']) { 75 | $builder->add('phone', TextType::class, [ 76 | 'label' => 'Phone number', 77 | 'required' => false, 78 | 'attr' => [ 79 | 'maxlength' => 50 80 | ] 81 | ]); 82 | } 83 | if ($modVars['showUrl']) { 84 | $builder->add('url', UrlType::class, [ 85 | 'label' => 'Website', 86 | 'attr' => [ 87 | 'maxlength' => 150, 88 | 'placeholder' => 'Enter a valid url' 89 | ], 90 | 'required' => false 91 | ]); 92 | } 93 | if ($modVars['showLocation']) { 94 | $builder->add('location', TextType::class, [ 95 | 'label' => 'Location', 96 | 'required' => false, 97 | 'attr' => [ 98 | 'maxlength' => 150 99 | ] 100 | ]); 101 | } 102 | if ($modVars['sendConfirmationToUser'] && $modVars['showUserFormat']) { 103 | $builder->add('userFormat', ChoiceType::class, [ 104 | 'label' => 'Email confirmation format', 105 | 'choices' => [ 106 | 'HTML' => 'html', 107 | 'Text' => 'plain', 108 | 'None' => 'none' 109 | ], 110 | 'expanded' => false, 111 | 'multiple' => false 112 | ]); 113 | } 114 | if ($modVars['showComment']) { 115 | $builder->add('comment', TextareaType::class, [ 116 | 'label' => 'Comment', 117 | 'attr' => [ 118 | 'placeholder' => 'Enter your comments here' 119 | ] 120 | ]); 121 | } 122 | if ($modVars['showFileAttachment']) { 123 | $builder->add('fileUpload', FileType::class, [ 124 | 'label' => 'Attach a file', 125 | 'required' => false 126 | ]); 127 | } 128 | $builder->add('submit', SubmitType::class, [ 129 | 'label' => 'Send', 130 | 'icon' => 'fa-check', 131 | 'attr' => [ 132 | 'class' => 'btn-success' 133 | ] 134 | ]); 135 | } 136 | 137 | public function getBlockPrefix() 138 | { 139 | return 'zikulaformiculamodule_usersubmission'; 140 | } 141 | 142 | public function configureOptions(OptionsResolver $resolver) 143 | { 144 | $resolver->setDefaults([ 145 | 'modVars' => [], 146 | 'contactChoices' => [] 147 | ]); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Entity/ContactEntity.php: -------------------------------------------------------------------------------- 1 | name = ''; 102 | $this->email = ''; 103 | $this->public = false; 104 | $this->senderName = ''; 105 | $this->senderEmail = ''; 106 | $this->sendingSubject = ''; 107 | } 108 | 109 | /** 110 | * Gets the id of the contact. 111 | */ 112 | public function getCid(): ?int 113 | { 114 | return $this->cid; 115 | } 116 | 117 | /** 118 | * Sets the id for the contact. 119 | */ 120 | public function setCid(int $cid): void 121 | { 122 | $this->cid = $cid; 123 | } 124 | 125 | /** 126 | * Gets the name of the contact. 127 | */ 128 | public function getName(): string 129 | { 130 | return $this->name; 131 | } 132 | 133 | /** 134 | * Sets the name for the contact. 135 | */ 136 | public function setName(string $name): void 137 | { 138 | $this->name = $name; 139 | } 140 | 141 | /** 142 | * Gets the email address of the contact. 143 | */ 144 | public function getEmail(): string 145 | { 146 | return $this->email; 147 | } 148 | 149 | /** 150 | * Sets the email address for the contact. 151 | */ 152 | public function setEmail(string $email): void 153 | { 154 | $this->email = $email; 155 | } 156 | 157 | /** 158 | * Gets the public flag of the contact. 159 | */ 160 | public function isPublic(): bool 161 | { 162 | return $this->public; 163 | } 164 | 165 | /** 166 | * Sets the public flag for the contact. 167 | */ 168 | public function setPublic(bool $public): void 169 | { 170 | if (is_bool($public)) { 171 | $this->public = $public; 172 | } 173 | } 174 | 175 | /** 176 | * Gets the sender name of the contact. 177 | */ 178 | public function getSenderName(): string 179 | { 180 | return $this->senderName; 181 | } 182 | 183 | /** 184 | * Sets the sender name for the contact. 185 | */ 186 | public function setSenderName(string $senderName): void 187 | { 188 | $this->senderName = $senderName; 189 | } 190 | 191 | /** 192 | * Gets the sender email address of the contact. 193 | */ 194 | public function getSenderEmail(): string 195 | { 196 | return $this->senderEmail; 197 | } 198 | 199 | /** 200 | * Sets the sender email address for the contact. 201 | */ 202 | public function setSenderEmail(string $senderEmail): void 203 | { 204 | $this->senderEmail = $senderEmail; 205 | } 206 | 207 | /** 208 | * Gets the sending subject of the contact. 209 | */ 210 | public function getSendingSubject(): string 211 | { 212 | return $this->sendingSubject; 213 | } 214 | 215 | /** 216 | * Sets the sending subject for the contact. 217 | */ 218 | public function setSendingSubject(string $subject): void 219 | { 220 | $this->sendingSubject = $subject; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /Resources/views/Form/1/userForm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/1/userHeader.html.twig') }} 2 | {{ form_start(form) }} 3 | {{ form_errors(form) }} 4 | 5 |

{% trans %}Mandatory fields are indicated with an asterisk.{% endtrans %}

6 | 7 |
8 | {% trans %}Apply online{% endtrans %} 9 | {{ form_row(form.form) }} 10 | {{ form_row(form.adminFormat) }} 11 | {% if modVars.sendConfirmationToUser and not modVars.showUserFormat %} 12 | {{ form_row(form.userFormat) }} 13 | {% endif %} 14 |
15 | {{ form_row(form.cid) }} 16 |
17 |
18 | 19 |
20 | 21 | 22 | 23 |
24 |
25 | {{ form_row(form.name) }} 26 |
27 | 28 |
29 | 30 | 31 | 32 |
33 |
34 | {% if modVars.showCompany %} 35 | {{ form_row(form.company) }} 36 | {% endif %} 37 | {{ form_row(form.emailAddress) }} 38 | {% if modVars.showLocation %} 39 |
40 | 41 |
42 | 43 | 44 | 45 |
46 |
47 | {{ form_row(form.location, {label: 'Zip City'|trans}) }} 48 | {% endif %} 49 |
50 | 51 |
52 | 53 | 54 | 55 |
56 |
57 |
58 | 59 |
60 | 61 | 62 | 63 |
64 |
65 | {% if modVars.showPhone %} 66 | {{ form_row(form.phone) }} 67 | {% endif %} 68 | {% if modVars.showUrl %} 69 | {{ form_row(form.url) }} 70 | {% endif %} 71 | {% if modVars.showComment %} 72 | {{ form_row(form.comment) }} 73 | {% endif %} 74 | {% if modVars.sendConfirmationToUser and modVars.showUserFormat %} 75 | {{ form_row(form.userFormat) }} 76 | {% endif %} 77 | {% if modVars.showFileAttachment %} 78 | {{ form_row(form.fileUpload) }} 79 | {% endif %} 80 | 81 | {% if enableSpamCheck %} 82 | {{ include('@ZikulaFormiculaModule/Include/spamCheck.html.twig') }} 83 | {% endif %} 84 |
85 | 86 | {% set hooks = notifyDisplayHooks(eventName='zikulaformiculamodule.ui_hooks.forms.form_edit') %} 87 | {% if hooks is iterable and hooks|length > 0 %} 88 | {% for area, hook in hooks %} 89 |
{{ hook|raw }}
90 | {% endfor %} 91 | {% endif %} 92 | 93 |
94 |
95 | {{ form_widget(form.submit) }} 96 |
97 |
98 | 99 | {{ form_end(form) }} 100 | 101 | {{ include('@ZikulaFormiculaModule/Form/1/userFooter.html.twig') }} 102 | 103 | {% set customScript %} 104 | 111 | {% endset %} 112 | {{ pageAddAsset('footer', customScript) }} 113 | -------------------------------------------------------------------------------- /Form/Type/ConfigType.php: -------------------------------------------------------------------------------- 1 | add('defaultForm', ChoiceType::class, [ 33 | 'label' => 'Default form', 34 | 'choices' => $options['formChoices'], 35 | 'expanded' => false, 36 | 'multiple' => false, 37 | 'help' => 'This form is used when no form is specified.' 38 | ]) 39 | ->add('showCompany', CheckboxType::class, [ 40 | 'label' => 'Show company', 41 | 'required' => false 42 | ]) 43 | ->add('showPhone', CheckboxType::class, [ 44 | 'label' => 'Show phone number', 45 | 'required' => false 46 | ]) 47 | ->add('showUrl', CheckboxType::class, [ 48 | 'label' => 'Show url', 49 | 'required' => false 50 | ]) 51 | ->add('showLocation', CheckboxType::class, [ 52 | 'label' => 'Show location', 53 | 'required' => false 54 | ]) 55 | ->add('showComment', CheckboxType::class, [ 56 | 'label' => 'Show comments textarea', 57 | 'required' => false 58 | ]) 59 | ->add('showFileAttachment', CheckboxType::class, [ 60 | 'label' => 'Show file attachment', 61 | 'required' => false 62 | ]) 63 | ->add('uploadDirectory', TextType::class, [ 64 | 'label' => 'Directory for uploaded files', 65 | 'attr' => [ 66 | 'maxlength' => 150 67 | ] 68 | ]) 69 | ->add('deleteUploadedFiles', CheckboxType::class, [ 70 | 'label' => 'Delete uploaded file(s) after sending', 71 | 'required' => false 72 | ]) 73 | ->add('sendConfirmationToUser', CheckboxType::class, [ 74 | 'label' => 'Send confirmation email to user', 75 | 'required' => false 76 | ]) 77 | ->add('defaultAdminFormat', ChoiceType::class, [ 78 | 'label' => 'Default email format for admin emails', 79 | 'choices' => [ 80 | 'HTML' => 'html', 81 | 'Plain text' => 'plain' 82 | ], 83 | 'expanded' => false, 84 | 'multiple' => false 85 | ]) 86 | ->add('defaultUserFormat', ChoiceType::class, [ 87 | 'label' => 'Default email format for user emails', 88 | 'choices' => [ 89 | 'HTML' => 'html', 90 | 'Plain text' => 'plain', 91 | 'None' => 'none' 92 | ], 93 | 'expanded' => false, 94 | 'multiple' => false 95 | ]) 96 | ->add('showUserFormat', CheckboxType::class, [ 97 | 'label' => 'Show user email format selector', 98 | 'required' => false 99 | ]) 100 | ->add('useContactsAsSender', CheckboxType::class, [ 101 | 'label' => 'Use contact mail addresses as sender', 102 | 'required' => false, 103 | 'help' => 'Disable this if you experience problems with your SMTP server' 104 | ]) 105 | ->add('enableSpamCheck', CheckboxType::class, [ 106 | 'label' => 'Activate simple spam check', 107 | 'required' => false, 108 | 'alert' => ['Make sure you the necessary form fields are available, see the docs for more information. This option will be turned off by Formicula automatically if no PHP functions for creating images are available.' => 'info'] 109 | ]) 110 | ->add('excludeSpamCheck', TextType::class, [ 111 | 'label' => 'Do not use spam check in these forms', 112 | 'required' => false, 113 | 'attr' => [ 114 | 'maxlength' => 40 115 | ], 116 | 'help' => 'Enter comma separated list of form ids or leave empty for using the spam check in all forms.' 117 | ]) 118 | ->add('storeSubmissionData', CheckboxType::class, [ 119 | 'label' => 'Store submitted data in database', 120 | 'required' => false 121 | ]) 122 | ->add('storeSubmissionDataForms', TextType::class, [ 123 | 'label' => 'Only store submissions from these forms', 124 | 'required' => false, 125 | 'attr' => [ 126 | 'maxlength' => 40 127 | ], 128 | 'help' => 'Enter comma separated list of form ids or leave empty for storing all forms.' 129 | ]) 130 | ->add('save', SubmitType::class, [ 131 | 'label' => 'Save', 132 | 'icon' => 'fa-check', 133 | 'attr' => [ 134 | 'class' => 'btn-success' 135 | ] 136 | ]) 137 | ->add('cancel', SubmitType::class, [ 138 | 'label' => 'Cancel', 139 | 'icon' => 'fa-times' 140 | ]) 141 | ; 142 | } 143 | 144 | public function getBlockPrefix() 145 | { 146 | return 'zikulaformiculamodule_config'; 147 | } 148 | 149 | public function configureOptions(OptionsResolver $resolver) 150 | { 151 | $resolver->setDefaults([ 152 | 'formChoices' => [] 153 | ]); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /Controller/ContactController.php: -------------------------------------------------------------------------------- 1 | contactRepository = $contactRepository; 57 | $this->environmentHelper = $environmentHelper; 58 | } 59 | 60 | /** 61 | * Show a list of contacts. 62 | * 63 | * @Route("/view") 64 | * @PermissionCheck("admin") 65 | * @Template("@ZikulaFormiculaModule/Contact/view.html.twig") 66 | * @Theme("admin") 67 | */ 68 | public function view(): array 69 | { 70 | // check necessary environment 71 | $this->environmentHelper->check(); 72 | 73 | $allContacts = $this->contactRepository->findBy([], ['cid' => 'ASC']); 74 | 75 | // only use those contacts where we have the necessary rights for 76 | $visibleContacts = []; 77 | foreach ($allContacts as $contact) { 78 | $contactId = $contact->getCid(); 79 | if (!$this->hasPermission('ZikulaFormiculaModule::', ":${contactId}:", ACCESS_EDIT)) { 80 | continue; 81 | } 82 | 83 | $contactArray = $contact->toArray(); 84 | $contactArray['allowEdit'] = true; 85 | $contactArray['allowDelete'] = $this->hasPermission('ZikulaFormiculaModule::', ":${contactId}:", ACCESS_DELETE); 86 | $visibleContacts[] = $contactArray; 87 | } 88 | 89 | return [ 90 | 'contacts' => $visibleContacts 91 | ]; 92 | } 93 | 94 | /** 95 | * Allows adding and editing contacts. 96 | * 97 | * @Route("/edit") 98 | * @PermissionCheck("admin") 99 | * @Template("@ZikulaFormiculaModule/Contact/edit.html.twig") 100 | * @Theme("admin") 101 | */ 102 | public function edit(Request $request) 103 | { 104 | // check necessary environment 105 | $this->environmentHelper->check(); 106 | 107 | $entityManager = $this->getDoctrine()->getManager(); 108 | $contactId = $request->query->getInt('cid', 0); 109 | 110 | if ($contactId < 1) { 111 | $mode = 'create'; 112 | $contact = new ContactEntity(); 113 | $contact->setPublic(true); 114 | } else { 115 | $mode = 'edit'; 116 | $contact = $this->contactRepository->find($contactId); 117 | if (false === $contact) { 118 | $this->addFlash('error', 'Contact could not be found.'); 119 | 120 | return $this->redirectToRoute('zikulaformiculamodule_contact_view'); 121 | } 122 | } 123 | 124 | $form = $this->createForm(EditContactType::class, $contact); 125 | $form->handleRequest($request); 126 | if ($form->isSubmitted() && $form->isValid()) { 127 | $valid = true; 128 | if ($form->get('save')->isClicked()) { 129 | $contact = $form->getData(); 130 | 131 | // email addresses can be a comma separated string, split and check separately 132 | $mailAddress = $contact->getEmail(); 133 | $mailAddress = preg_replace('/\s*/m', '', $mailAddress); // remove spaces 134 | $addresses = explode(',', $mailAddress); 135 | foreach ($addresses as $address) { 136 | if (false === filter_var($address, FILTER_VALIDATE_EMAIL)) { 137 | $this->addFlash('error', $this->trans('Error! Incorrect email address [%s%] supplied.', ['%s%' => $address])); 138 | $valid = false; 139 | break; 140 | } 141 | } 142 | if ($valid) { 143 | $contact->setEmail($mailAddress); 144 | 145 | $entityManager->persist($contact); 146 | $entityManager->flush(); 147 | if ('create' === $mode) { 148 | $this->addFlash('status', 'Done! Contact created.'); 149 | } else { 150 | $this->addFlash('status', 'Done! Contact updated.'); 151 | } 152 | } 153 | } elseif ($form->get('cancel')->isClicked()) { 154 | $this->addFlash('status', 'Operation cancelled.'); 155 | } 156 | 157 | if ($valid) { 158 | return $this->redirectToRoute('zikulaformiculamodule_contact_view'); 159 | } 160 | } 161 | 162 | return [ 163 | 'form' => $form->createView(), 164 | 'mode' => $mode, 165 | 'contact' => $contact 166 | ]; 167 | } 168 | 169 | /** 170 | * Deletes an existing contact from the database. 171 | * 172 | * @Route("/delete") 173 | * @PermissionCheck("delete") 174 | * @Template("@ZikulaFormiculaModule/Contact/delete.html.twig") 175 | * @Theme("admin") 176 | */ 177 | public function delete(Request $request) 178 | { 179 | // check necessary environment 180 | $this->environmentHelper->check(); 181 | 182 | $entityManager = $this->getDoctrine()->getManager(); 183 | $contactId = $request->query->getInt('cid', 0); 184 | 185 | $contact = $this->contactRepository->find($contactId); 186 | if (false === $contact) { 187 | $this->addFlash('error', 'Contact could not be found.'); 188 | 189 | return $this->redirectToRoute('zikulaformiculamodule_contact_view'); 190 | } 191 | 192 | $form = $this->createForm(DeleteContactType::class, $contact); 193 | $form->handleRequest($request); 194 | if ($form->isSubmitted() && $form->isValid()) { 195 | if ($form->get('delete')->isClicked()) { 196 | $contact = $form->getData(); 197 | $entityManager->remove($contact); 198 | $entityManager->flush(); 199 | $this->addFlash('status', 'Done! Contact deleted.'); 200 | } elseif ($form->get('cancel')->isClicked()) { 201 | $this->addFlash('status', 'Operation cancelled.'); 202 | } 203 | 204 | return $this->redirectToRoute('zikulaformiculamodule_contact_view'); 205 | } 206 | 207 | return [ 208 | 'form' => $form->createView(), 209 | 'contact' => $contact 210 | ]; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /FormiculaModuleInstaller.php: -------------------------------------------------------------------------------- 1 | cacheDirectory = $cacheDir; 59 | $this->uploadDirectory = str_replace('cache', 'uploads', $cacheDir); 60 | } 61 | 62 | public function install(): bool 63 | { 64 | $this->schemaTool->create($this->entities); 65 | 66 | $variableApi = $this->getVariableApi(); 67 | 68 | // create a contact for the webmaster 69 | $contact = new ContactEntity(); 70 | $contact->setName($this->trans('Webmaster')); 71 | $contact->setEmail($variableApi->get('ZConfig', 'adminmail')); 72 | $contact->setPublic(true); 73 | $contact->setSenderName($contact->getName()); 74 | $contact->setSenderEmail($contact->getEmail()); 75 | $contact->setSendingSubject($this->trans('Your mail to %s')); 76 | $this->entityManager->persist($contact); 77 | $this->entityManager->flush(); 78 | 79 | // try to create required directories 80 | $this->createCacheDirectory(); 81 | $this->createUploadDirectory(); 82 | 83 | $this->setVars($this->getDefaultSettings()); 84 | 85 | // initialisation successful 86 | return true; 87 | } 88 | 89 | public function upgrade($oldVersion): bool 90 | { 91 | switch ($oldVersion) { 92 | case '4.0.0': 93 | case '4.0.1': 94 | // nothing to do 95 | case '4.0.2': 96 | // fields have changed: createdUserId becomes createdBy, updatedUserId becomes updatedBy 97 | $connection = $this->entityManager->getConnection(); 98 | $tableName = 'submission'; 99 | $sql = ' 100 | ALTER TABLE `formicula_' . $tableName . '` 101 | CHANGE `createdUserId` `createdBy` INT(11) DEFAULT NULL 102 | '; 103 | $stmt = $connection->prepare($sql); 104 | $stmt->execute(); 105 | 106 | $sql = ' 107 | ALTER TABLE `formicula_' . $tableName . '` 108 | CHANGE `updatedUserId` `updatedBy` INT(11) DEFAULT NULL 109 | '; 110 | $stmt = $connection->prepare($sql); 111 | $stmt->execute(); 112 | // no break 113 | case '5.0.0': 114 | // added forgotten company field 115 | try { 116 | $this->schemaTool->update([ 117 | SubmissionEntity::class 118 | ]); 119 | } catch (\Exception $exception) { 120 | $this->addFlash('error', $this->trans('Doctrine Exception') . ': ' . $exception->getMessage()); 121 | 122 | return false; 123 | } 124 | case '5.0.1': 125 | $this->setVar('uploadDirectory', $this->uploadDirectory); 126 | // no break 127 | case '5.0.2': 128 | // nothing yet 129 | } 130 | 131 | // Update successful 132 | return true; 133 | } 134 | 135 | public function uninstall(): bool 136 | { 137 | $this->schemaTool->drop($this->entities); 138 | 139 | $this->delVars(); 140 | 141 | if (is_dir($this->cacheDirectory)) { 142 | $fs = new Filesystem(); 143 | try { 144 | $fs->remove($this->cacheDirectory); 145 | } catch (IOExceptionInterface $exception) { 146 | $this->addFlash( 147 | 'error', 148 | $this->trans( 149 | 'An error occurred while removing the cache directory at %s%.', 150 | ['%s%' => $this->cacheDirectory] 151 | ) 152 | ); 153 | } 154 | } 155 | 156 | // upload directory is currently not deleted, since the files may still be of interest 157 | 158 | return true; 159 | } 160 | 161 | private function createCacheDirectory(): void 162 | { 163 | $fs = new Filesystem(); 164 | try { 165 | if (!$fs->exists($this->cacheDirectory)) { 166 | $fs->mkdir($this->cacheDirectory); 167 | $fs->chmod($this->cacheDirectory, 0777); 168 | } 169 | } catch (IOExceptionInterface $exception) { 170 | $this->addFlash( 171 | 'error', 172 | $this->trans( 173 | 'An error occurred while creating the cache directory at %s%.', 174 | ['%s%' => $this->cacheDirectory] 175 | ) 176 | ); 177 | } 178 | 179 | try { 180 | if ($fs->exists($this->cacheDirectory . '/.htaccess')) { 181 | return; 182 | } 183 | $fs->dumpFile($this->cacheDirectory . '/.htaccess', 'SetEnvIf Request_URI "\.gif$" object_is_gif=gif 184 | SetEnvIf Request_URI "\.png$" object_is_png=png 185 | SetEnvIf Request_URI "\.jpg$" object_is_jpg=jpg 186 | SetEnvIf Request_URI "\.jpeg$" object_is_jpeg=jpeg 187 | Order deny,allow 188 | Deny from all 189 | Allow from env=object_is_gif 190 | Allow from env=object_is_png 191 | Allow from env=object_is_jpg 192 | Allow from env=object_is_jpeg 193 | '); 194 | $this->addFlash( 195 | 'status', 196 | $this->trans('Successfully created the cache directory with a .htaccess file in it.') 197 | ); 198 | } catch (IOExceptionInterface $exception) { 199 | $this->addFlash( 200 | 'error', 201 | $this->trans( 202 | 'Could not create .htaccess file in %s%, please refer to the manual before using the module!', 203 | ['%s%' => $this->cacheDirectory] 204 | ) 205 | ); 206 | } 207 | } 208 | 209 | private function createUploadDirectory(): void 210 | { 211 | $fs = new Filesystem(); 212 | try { 213 | if (!$fs->exists($this->uploadDirectory)) { 214 | $fs->mkdir($this->uploadDirectory); 215 | $fs->chmod($this->uploadDirectory, 0777); 216 | } 217 | } catch (IOExceptionInterface $exception) { 218 | $this->addFlash( 219 | 'error', 220 | $this->trans( 221 | 'An error occurred while creating the upload directory at %s%.', 222 | ['%s%' => $this->uploadDirectory] 223 | ) 224 | ); 225 | } 226 | } 227 | 228 | private function getDefaultSettings(): array 229 | { 230 | return [ 231 | 'defaultForm' => 0, 232 | 'showCompany' => true, 233 | 'showPhone' => true, 234 | 'showUrl' => true, 235 | 'showLocation' => true, 236 | 'showComment' => true, 237 | 238 | 'showFileAttachment' => false, 239 | 'uploadDirectory' => $this->uploadDirectory, 240 | 'deleteUploadedFiles' => true, 241 | 242 | 'sendConfirmationToUser' => true, 243 | 'defaultAdminFormat' => 'html', 244 | 'defaultUserFormat' => 'html', 245 | 'showUserFormat' => true, 246 | 'useContactsAsSender' => true, 247 | 248 | 'enableSpamCheck' => true, 249 | 'excludeSpamCheck' => '', 250 | 'storeSubmissionData' => false, 251 | 'storeSubmissionDataForms' => '' 252 | ]; 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /Entity/SubmissionEntity.php: -------------------------------------------------------------------------------- 1 | form = 0; 147 | $this->cid = 0; 148 | $this->ipAddress = ''; 149 | $this->hostName = ''; 150 | $this->name = ''; 151 | $this->email = ''; 152 | $this->phoneNumber = ''; 153 | $this->company = ''; 154 | $this->url = ''; 155 | $this->location = ''; 156 | $this->comment = ''; 157 | $this->customData = []; 158 | } 159 | 160 | /** 161 | * Gets the id of the submission. 162 | */ 163 | public function getSid(): ?int 164 | { 165 | return $this->sid; 166 | } 167 | 168 | /** 169 | * Sets the id for the submission. 170 | */ 171 | public function setSid(int $sid): void 172 | { 173 | $this->sid = $sid; 174 | } 175 | 176 | /** 177 | * Gets the id of the form. 178 | */ 179 | public function getForm(): int 180 | { 181 | return $this->form; 182 | } 183 | 184 | /** 185 | * Sets the form id for the submission. 186 | */ 187 | public function setForm(int $form): void 188 | { 189 | $this->form = $form; 190 | } 191 | 192 | /** 193 | * Gets the contact id of the submission. 194 | */ 195 | public function getCid(): int 196 | { 197 | return $this->cid; 198 | } 199 | 200 | /** 201 | * Sets the contact id for the submission. 202 | */ 203 | public function setCid(int $cid): void 204 | { 205 | $this->cid = $cid; 206 | } 207 | 208 | /** 209 | * Gets the ip address of the submission. 210 | */ 211 | public function getIpAddress(): string 212 | { 213 | return $this->ipAddress; 214 | } 215 | 216 | /** 217 | * Sets the ip address for the submission. 218 | */ 219 | public function setIpAddress(string $ipAddress): void 220 | { 221 | $this->ipAddress = $ipAddress; 222 | } 223 | 224 | /** 225 | * Gets the host name of the submission. 226 | */ 227 | public function getHostName(): string 228 | { 229 | return $this->hostName; 230 | } 231 | 232 | /** 233 | * Sets the host name for the submission. 234 | */ 235 | public function setHostName(string $hostName): void 236 | { 237 | $this->hostName = $hostName; 238 | } 239 | 240 | /** 241 | * Gets the name of the submission. 242 | */ 243 | public function getName(): string 244 | { 245 | return $this->name; 246 | } 247 | 248 | /** 249 | * Sets the name for the submission. 250 | */ 251 | public function setName(string $name): void 252 | { 253 | $this->name = $name; 254 | } 255 | 256 | /** 257 | * Gets the email address of the submission. 258 | */ 259 | public function getEmail(): string 260 | { 261 | return $this->email; 262 | } 263 | 264 | /** 265 | * Sets the email address for the submission. 266 | */ 267 | public function setEmail(string $email): void 268 | { 269 | $this->email = $email; 270 | } 271 | 272 | /** 273 | * Gets the phone number of the submission. 274 | */ 275 | public function getPhoneNumber(): string 276 | { 277 | return $this->phoneNumber; 278 | } 279 | 280 | /** 281 | * Sets the phone number for the submission. 282 | */ 283 | public function setPhoneNumber(string $phoneNumber): void 284 | { 285 | $this->phoneNumber = $phoneNumber; 286 | } 287 | 288 | /** 289 | * Alias for easier form handling. 290 | */ 291 | public function setPhone(string $phoneNumber): void 292 | { 293 | $this->setPhoneNumber($phoneNumber); 294 | } 295 | 296 | /** 297 | * Gets the company of the submission. 298 | */ 299 | public function getCompany(): string 300 | { 301 | return $this->company; 302 | } 303 | 304 | /** 305 | * Sets the company for the submission. 306 | */ 307 | public function setCompany(string $company): void 308 | { 309 | $this->company = $company; 310 | } 311 | 312 | /** 313 | * Gets the url of the submission. 314 | */ 315 | public function getUrl(): string 316 | { 317 | return $this->url; 318 | } 319 | 320 | /** 321 | * Sets the url for the submission. 322 | */ 323 | public function setUrl(string $url): void 324 | { 325 | $this->url = $url; 326 | } 327 | 328 | /** 329 | * Gets the location of the submission. 330 | */ 331 | public function getLocation(): string 332 | { 333 | return $this->location; 334 | } 335 | 336 | /** 337 | * Sets the location for the submission. 338 | */ 339 | public function setLocation(string $location): void 340 | { 341 | $this->location = $location; 342 | } 343 | 344 | /** 345 | * Gets the comment of the submission. 346 | * 347 | * @return string the submission's comment 348 | */ 349 | public function getComment() 350 | { 351 | return $this->comment; 352 | } 353 | 354 | /** 355 | * Sets the comment for the submission. 356 | */ 357 | public function setComment(string $comment): void 358 | { 359 | $this->comment = $comment; 360 | } 361 | 362 | /** 363 | * Gets the custom data of the submission. 364 | */ 365 | public function getCustomData(): array 366 | { 367 | return $this->customData; 368 | } 369 | 370 | /** 371 | * Sets the custom data for the submission. 372 | */ 373 | public function setCustomData(array $customData = []): void 374 | { 375 | $this->customData = $customData; 376 | } 377 | 378 | /** 379 | * Adds a value to the submission's custom data. 380 | */ 381 | public function addCustomData(string $key = '', string $value = ''): void 382 | { 383 | if ('' !== $key) { 384 | $this->customData[$key] = $value; 385 | } 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | 3 | This module has been deprecated as part of [Zikula 4 slimming diet](https://github.com/zikula/core/blob/main/ZIKULA-4.0.md). 4 | 5 | # Formicula Zikula Module 6 | 7 | A template-driven form mailer for Zikula. 8 | Formicula is a highly configurable contact mailer solution for Zikula Application Framework. 9 | You can create any kind of contact form with any number contact fields by changing templates. 10 | Forms can be controlled by permissions. 11 | It also supports multiple, permission controlled recipients, configurable notification emails, a simple captcha for spam protection, hooks to the Captcha module, javascript form validation and file uploads. 12 | 13 | ## Main branch 14 | 15 | The 6.0.x versions in the `main` branch target Zikula 3.0+. 16 | 17 | ## Older versions 18 | 19 | See [releases](https://github.com/zikula-modules/Formicula/releases). 20 | 21 | ## Installation 22 | 23 | 1. Extract the files to your Zikula `extensions` directory. 24 | 2. Initialize and activate Formicula in the extensions administration. 25 | 3. During installation, Formicula tries to create a `public/formicula/cache` directory containing a `.htaccess` file. 26 | If this fails (should happen very rarely), you will be notified and have to create them on your own: 27 | a) Create a directory `public/formicula/cache` and make it writable for the web server (e.g. `chmod 777`). 28 | b) Create a `.htacess` file within that directory containing the following lines to allow access to the 29 | images created for the captcha: 30 | ``` 31 | SetEnvIf Request_URI "\.gif$" object_is_gif=gif 32 | SetEnvIf Request_URI "\.png$" object_is_png=png 33 | SetEnvIf Request_URI "\.jpg$" object_is_jpg=jpg 34 | Order deny,allow 35 | Deny from all 36 | Allow from env=object_is_gif 37 | Allow from env=object_is_png 38 | Allow from env=object_is_jpg 39 | ``` 40 | 4. Create some contact names/topics with respective email adresses in the Formicula admin setion. 41 | Upon installation, Formicula creates a default contact with the admins mail address. 42 | 5. Add a basic permission rule, e.g. 43 | Unregistered (group) | ZikulaFormiculaModule::.* | .* | comment 44 | This enables unregistered users to use all existing forms. In a default installation 45 | the users group has a generic comment permission to do the same. 46 | 6. Add a link to your main menu using `/contact` as URL (whereby _contact_ corresponds 47 | to the module name defined for Formicula in the extensions list). 48 | This uses form 0. To call a specific form id use `/contact/?form=` 49 | e.g. `/contact/?form=5` to use form #5 50 | In the distribution package you will find sample forms 0, 1, 2 and 3. 51 | 0 is a normal contact form and form #1 and beyond are more extensive forms. 52 | 53 | ## Configuration 54 | 55 | - Show xxx: quick configuration enable/disable some fields in the userform. These fields may be (read: surely will be) removed in future versions. 56 | - Send confirmation email to user: Tick this to send an confirmation mail to the user directory for uploaded files: Uploaded files get stored here. Make sure this directory is secured with a `.htaccess` file! 57 | - Delete file after sending: does what it says when ticked. 58 | - Activate spamcheck: shows a little captcha in the form 59 | 60 | ## Contacts 61 | 62 | Each contact consists of several information: 63 | 64 | - Contact name or Topic: The name that is shown to the user in the form, e.g. Webmaster 65 | - Email: The email to send the data to 66 | - Public: tick this to make the contact available for use. 67 | - Sender name: senders name as used in the users confirmation mail 68 | - Sender email: senders email address as used in the users confirmation mail, e.g noreply@example.com 69 | - Subject: enter a static subject or use these placeholders: 70 | - %s = sitename 71 | - %l = slogan 72 | - %u = site url 73 | - %c = contact name 74 | - %n = user defined field name 75 | - %d = user defined field data 76 | 77 | ## Using own contacts 78 | 79 | It is possible to pass own contacts to formicula instead using the formicula database. To do this by a link 80 | you have to call the addSessionOwncontacts function in the User-API. This function will return you 81 | an integer which you should append with the index 'owncontacts' to the URL pointing to formicula. 82 | If you want to embed your form you can pass the owncontacts directly to the form by adding 83 | the owncontacts array to your arguments array. 84 | 85 | The owncontacts array should contain the following values (per item) in both cases: 86 | - name the contact full name (required) 87 | - sname the contact secure name wich will be send to the submitter (optional) 88 | - email the contact email (required) 89 | - semail the contact email wich will be send to the submiter (optional) 90 | - ssubject the subject of the confirmation mail (optional) 91 | 92 | ## Templates 93 | 94 | Everything you want to do with the form is handled in the templates. 95 | Store them in Resources/views/Form/ 96 | The '#' at the beginning of the template designates the number of form. 97 | 98 | The templates for the forms are named as follows: 99 | - The form with the input fields: `Form/#/userForm.html.twig` 100 | - The page with the confirmation after submitting the data: `Form/#/userConfirm.html.twig` 101 | - The page with error messages after submitting data: `Form/#/userError.html.twig` 102 | - The user's confirmation mail in text format: `Form/#/userMail.txt.twig` 103 | - The user's confirmation mail in html format: `Form/#/userMail.html.twig` 104 | - The admin mail in text format: `Form/#/adminMail.txt.twig` 105 | - The admin mail in html format: `Form/#/adminmail.html.twig` 106 | 107 | This is the email that the admin gets after the user sends submits the userform. 108 | 109 | ## Standard fields 110 | 111 | The standard fields to be used in forms are under userdata 112 | 113 | - userdata[uname]: the users name (mandatory) 114 | - userdata[uemail]: the users name (mandatory) 115 | - userdata[url]: the users homepage (optional) 116 | - userdata[location], userdata[phone], userdata[company]: these are obvious... (optional) 117 | - userdata[comment]: normally a textarea for entering free text. Since 0.6 this is not longer a mandatory field! HTML is stripped from the comments to avoid spam. In addition, the comment is send to Zikula's internal censor function. If the result differs from the original comment, the submission is also treated as spam and not sent. This results in an error message. 118 | - captcha: mandatory if spamcheck feature is enabled, see 0_userform.html for an example 119 | 120 | ## Custom fields 121 | 122 | You can add as many custom fields to your form as you want. 123 | This makes it easy to create e.g. an online job application form if needed. 124 | 125 | This makes it necessary to send certain information from the form page to the module. 126 | The custom fields are numbered in old versions and an associative array in newer versions. 127 | 128 | These are: 129 | 130 | - custom[fieldname][name] (hidden field) name of the custom field 131 | can be used in the confirmation email 132 | - custom[fieldname][mandatory] (hidden field) set to 1 if this is a mandatory field. 133 | Formicula checks this and shows an errormessage when this field is not filled 134 | - custom[fieldname][data] (any kind of input field) the data with fieldname 135 | the payload 136 | 137 | Example: 138 | 139 | ``` 140 |
141 | 142 | 143 | 144 | ``` 145 | 146 | ## Permissions 147 | 148 | To use a form you need the right to COMMENT. 149 | 150 | Unregistered | ZikulaFormiculaModule:: | .* | comment 151 | all unregistered users are allowed to use all forms and write to all contacts 152 | 153 | Unregistered | ZikulaFormiculaModule:: | 0:: | comment 154 | all unregistered users are allowed to use form 0 with all existing contacts. 155 | 156 | Users | ZikulaFormiculaModule:: | 1:(2|3): | comment 157 | all members of the group Users are allowed to use form 1 and write to contact 2 and 3. 158 | 159 | ## Use external information in the forms 160 | 161 | You can use external information in the form by sending them in the url used to call 162 | the form. These data are send in an associative array addinfo where the key is the name. 163 | 164 | With 165 | 166 | `/contact/?form=2&addinfo[tid]=4&addinfo[pid]=17` 167 | 168 | you send two different information to the form 2 which can used in the userform template (in 169 | this `example 2_userform.html`) with 170 | 171 | {{ addinfo.tid }} => 4 172 | {{ addinfo.pid }} => 17 173 | 174 | As you can see you can use this to e.g. load data from Pagesetter in the userform template. 175 | 176 | ## Client side input validation 177 | 178 | The supplied templates use a html5 input validation with webshims lib polyfill fallback. 179 | 180 | ## Captcha 181 | 182 | The simplecaptcha plugins adds an image with a very basic math equation (3 number from 1 to 2 183 | and either +, - or *) to the form if the spam check is enabled. If the user enters a wrong 184 | value, Formicula redirects back to the page where it came from. 185 | 186 | Formicula tries to create images in this order: gif, jpg, png. 187 | If all these image types are not supported by your server, captchas are deactivated, in this 188 | case Formicula turns the configuration option "Activate spamcheck" off. 189 | Please refer to for more information. 190 | 191 | Formicula also supports ztemp-directories located outside the websites root directory. In this case 192 | (when the temp directory points to an absolute path) the image is delivered by an internal 193 | function and not linked directly. 194 | -------------------------------------------------------------------------------- /Helper/CaptchaHelper.php: -------------------------------------------------------------------------------- 1 | translator = $translator; 75 | $this->variableApi = $variableApi; 76 | $this->permissionApi = $permissionApi; 77 | $this->environmentHelper = $environmentHelper; 78 | $this->router = $router; 79 | $this->requestStack = $requestStack; 80 | $this->projectDirectory = $projectDir; 81 | $this->cacheDirectory = $cacheDir; 82 | } 83 | 84 | /** 85 | * Determines whether the spam check is active for a certain form. 86 | */ 87 | public function isSpamCheckEnabled(int $form = 0): bool 88 | { 89 | $enableSpamCheck = $this->variableApi->get('ZikulaFormiculaModule', 'enableSpamCheck', true); 90 | if ($enableSpamCheck) { 91 | $excludeSpamCheck = explode(',', $this->variableApi->get('ZikulaFormiculaModule', 'excludeSpamCheck', '')); 92 | if (is_array($excludeSpamCheck) && array_key_exists($form, array_flip($excludeSpamCheck))) { 93 | $enableSpamCheck = false; 94 | } 95 | } 96 | 97 | return $enableSpamCheck; 98 | } 99 | 100 | /** 101 | * Determines whether a given captcha code is correct or not. 102 | */ 103 | public function isCaptchaValid(array $operands = [], int $captcha = 0): bool 104 | { 105 | $captchaValid = false; 106 | if (!is_array($operands)) { 107 | return $captchaValid; 108 | } 109 | 110 | $op1 = (int) $operands['x']; 111 | $op2 = (int) $operands['y']; 112 | $op3 = (int) $operands['v']; 113 | 114 | switch ($operands['z'] . '-' . $operands['w']) { 115 | case '0-0': 116 | $captchaValid = ($op1 + $op2 + $op3 === $captcha); 117 | break; 118 | case '0-1': 119 | $captchaValid = ($op1 + $op2 - $op3 === $captcha); 120 | break; 121 | case '1-0': 122 | $captchaValid = ($op1 - $op2 + $op3 === $captcha); 123 | break; 124 | case '1-1': 125 | $captchaValid = ($op1 - $op2 - $op3 === $captcha); 126 | break; 127 | default: 128 | // $captchaValid is false 129 | } 130 | 131 | return $captchaValid; 132 | } 133 | 134 | /** 135 | * Creates a captcha image and returns it's markup code. 136 | * 137 | * based on imagetext (c) guite.de which is 138 | * based on imagetext (c) Christoph Erdmann 139 | * 140 | * @param string $font Name of font to use (arial, freesans, quickhand, vera) 141 | * @param int $size Font size 142 | * @param string $bgColour Background colour (hex code without the # char) 143 | * @param string $fgColour Foreground colour (hex code without the # char) 144 | * 145 | * @return string The image markup 146 | */ 147 | public function createCaptcha( 148 | string $font = 'quickhand', 149 | int $size = 14, 150 | string $bgColour = 'ffffff', 151 | string $fgColour = '000000' 152 | ): string { 153 | // check which image types are supported 154 | $freetype = function_exists('imagettfbbox'); 155 | if ($freetype && (imagetypes() && IMG_PNG)) { 156 | $imageType = '.png'; 157 | $createImageFunction = 'imagepng'; 158 | } elseif ($freetype && (imagetypes() && IMG_JPG)) { 159 | $imageType = '.jpg'; 160 | $createImageFunction = 'imagejpeg'; 161 | } elseif ($freetype && (imagetypes() && IMG_GIF)) { 162 | $imageType = '.gif'; 163 | $createImageFunction = 'imagegif'; 164 | } else { 165 | // no image functions available 166 | $this->variableApi->set('ZikulaFormiculaModule', 'enableSpamCheck', false); 167 | if ($this->permissionApi->hasPermission('ZikulaFormiculaModule::', '.*', ACCESS_ADMIN)) { 168 | // admin permission, show error messages 169 | return '

' . $this->translator->trans('There are no image function available - Captchas have been disabled.') . '

'; 170 | } 171 | 172 | // return silently 173 | return ''; 174 | } 175 | 176 | // catch wrong input 177 | if (empty($font) || !is_numeric($size) || $size < 1 || empty($bgColour) || empty($fgColour)) { 178 | return ''; 179 | } 180 | 181 | $fontPath = $this->getFontPath($font); 182 | if (!file_exists($fontPath) || !is_readable($fontPath)) { 183 | return ''; 184 | } 185 | 186 | $operands = $this->determineOperands(); 187 | 188 | $m = ['+', '-']; 189 | 190 | $request = $this->requestStack->getCurrentRequest(); 191 | if (null !== $request) { 192 | // store the numbers in a session var 193 | $request->getSession()->set('formiculaCaptcha', serialize($operands)); 194 | } 195 | 196 | // create the text for the image 197 | $exerciseText = $operands['x'] . ' ' . $m[$operands['z']] . ' ' . $operands['y'] . ' ' . $m[$operands['w']] . ' ' . $operands['v'] . ' ='; 198 | 199 | // hash the params for cache filename 200 | $hash = hash('sha256', $font . $size . $bgColour . $fgColour . $exerciseText); 201 | // create uri of image 202 | $imagePath = $this->cacheDirectory . '/' . $hash . $imageType; 203 | 204 | // create the image if it does not already exist 205 | if (!file_exists($imagePath)) { 206 | // we create a larger picture than needed, this makes it looking better at the end 207 | $multi = 4; 208 | // get the textsize in the image 209 | $bbox = imagettfbbox($size * $multi, 0, $fontPath, $exerciseText); 210 | $xcorr = 0 - $bbox[6]; // northwest X 211 | $ycorr = 0 - $bbox[7]; // northwest Y 212 | $box['left'] = $bbox[6] + $xcorr; 213 | $box['height'] = abs($bbox[5]) + abs($bbox[1]); 214 | $box['width'] = abs($bbox[2]) + abs($bbox[0]); 215 | $box['top'] = abs($bbox[5]); 216 | 217 | // create the image 218 | $im = imagecreate($box['width'], $box['height']); 219 | 220 | $bgcolor = $this->hexToRgb($im, $bgColour); 221 | $fgcolor = $this->hexToRgb($im, $fgColour); 222 | 223 | // add the text to the image 224 | imagettftext($im, $size * $multi, 0, $box['left'], $box['top'], $fgcolor, $fontPath, $exerciseText); 225 | 226 | // resize the image now 227 | $finalWidth = (int) round($box['width'] / $multi); 228 | $finalHeight = (int) round($box['height'] / $multi); 229 | $ds = imagecreatetruecolor($finalWidth, $finalHeight); 230 | 231 | $bgcolor2 = $this->hexToRgb($ds, $bgColour); 232 | imagefill($ds, 0, 0, $bgcolor2); 233 | imagecopyresampled($ds, $im, 0, $box['left'], 0, 0, (int) ($box['width'] / $multi), (int) ($box['height'] / $multi), $box['width'], $box['height']); 234 | imagetruecolortopalette($ds, false, 256); 235 | imagepalettecopy($ds, $im); 236 | imagecolortransparent($ds, $bgcolor); 237 | 238 | // write the file 239 | $createImageFunction($ds, $imagePath); 240 | imagedestroy($im); 241 | imagedestroy($ds); 242 | } else { 243 | // file already exists, calculate image size 244 | $imageData = getimagesize($imagePath); 245 | $finalWidth = $imageData[0]; 246 | $finalHeight = $imageData[1]; 247 | } 248 | 249 | $relativeImagePath = str_replace($this->projectDirectory, '', $imagePath); 250 | 251 | return '' . $this->translator->trans('Math') . ''; 252 | } 253 | 254 | /** 255 | * Returns the path to a given font. 256 | * 257 | * @param string $font Name of font to use 258 | * 259 | * @return string Path to the font file 260 | */ 261 | private function getFontPath(string $font): string 262 | { 263 | $absolutePath = dirname(__DIR__); 264 | $fontPath = $absolutePath . '/Resources/public/fonts/' . $font . '.ttf'; 265 | 266 | return $fontPath; 267 | } 268 | 269 | /** 270 | * Determines random numbers for the calculation. 271 | * 272 | * @return array Random math exercise operands 273 | */ 274 | private function determineOperands(): array 275 | { 276 | $x = mt_rand(1, 10); 277 | $y = mt_rand(1, 10); 278 | $z = mt_rand(0, 1); /* 0=+, 1=- */ 279 | $v = mt_rand(1, 10); 280 | $w = mt_rand(0, 1); /* 0=+, 1=- */ 281 | 282 | // turn minus into plus when x=y 283 | if (1 === $z && $y === $x) { 284 | $z = 0; 285 | } 286 | 287 | // turn minus into plus when y=v 288 | if (1 === $w && $v === $y) { 289 | $w = 0; 290 | } 291 | 292 | // make sure that x>y if z=1 (minus) 293 | if (1 === $z && $y > $x) { 294 | $tmp = $x; 295 | $x = $y; 296 | $y = $tmp; 297 | } 298 | 299 | // turn minus into plus when v>x-y or v>x+y 300 | if (1 === $w && (1 === $z && $v > ($x - $y)) || (0 === $z && $v > ($x + $y))) { 301 | $w = 0; 302 | } 303 | 304 | return [ 305 | 'x' => $x, 306 | 'y' => $y, 307 | 'z' => $z, 308 | 'v' => $v, 309 | 'w' => $w 310 | ]; 311 | } 312 | 313 | /** 314 | * Converts a hex colour code into rgb values. 315 | * 316 | * @param resource $image The image resource 317 | * @param string $hexCode Colour hex code without the # char 318 | * 319 | * @return integer colour id determined by resulting rgb values 320 | */ 321 | private function hexToRgb($image, string $hexCode): int 322 | { 323 | sscanf($hexCode, "%2x%2x%2x", $red, $green, $blue); 324 | 325 | return imagecolorallocate($image, $red, $green, $blue); 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /Resources/views/Form/3/userForm.html.twig: -------------------------------------------------------------------------------- 1 | {{ include('@ZikulaFormiculaModule/Form/3/userHeader.html.twig') }} 2 | 3 | {{ form_start(form) }} 4 | {{ form_errors(form) }} 5 | 6 |

{% trans %}Mandatory fields are indicated with an asterisk.{% endtrans %}

7 | 8 |
9 | {% trans %}Make a reservation{% endtrans %} 10 | {{ form_row(form.form) }} 11 | {{ form_row(form.adminFormat) }} 12 | {% if modVars.sendConfirmationToUser and not modVars.showUserFormat %} 13 | {{ form_row(form.userFormat) }} 14 | {% endif %} 15 |
16 | {{ form_row(form.cid) }} 17 |
18 | 19 |

{% trans %}Personal data{% endtrans %}

20 | {{ form_row(form.name) }} 21 |
22 | 23 |
24 | 25 | 26 | 27 |
28 |
29 | {% if modVars.showCompany %} 30 | {{ form_row(form.company) }} 31 | {% endif %} 32 | {% if modVars.showLocation %} 33 |
34 | 35 |
36 | 37 | 38 | 39 |
40 |
41 | {{ form_row(form.location, {label: 'Zip City'|trans}) }} 42 | {% endif %} 43 | {{ form_row(form.emailAddress) }} 44 | {% if modVars.showPhone %} 45 | {{ form_row(form.phone) }} 46 | {% endif %} 47 | {% if modVars.showUrl %} 48 | {{ form_row(form.url) }} 49 | {% endif %} 50 |
51 | 52 |
53 | 54 | 55 | 56 |
57 |
58 |
59 | 60 |
61 | 62 | 63 | 66 | 69 |
70 |
71 | 72 |

{% trans %}Rental data{% endtrans %}

73 |
74 | 75 |
76 | 77 | 78 | 84 |
85 |
86 |
87 | 88 |
89 | 90 | 91 | 92 |
93 |
94 |
95 | 96 |
97 | 98 | 99 | 100 |
101 |
102 |
103 | 104 |
105 | 106 | 107 | 108 |
109 |
110 | 111 |

{% trans %}Included extras{% endtrans %}

112 |
113 |
114 | 118 | 122 | 126 |
127 |
128 | 129 |

{% trans %}Finish and send{% endtrans %}

130 | {% if modVars.showComment %} 131 | {{ form_row(form.comment, { required: false }) }} 132 | {% endif %} 133 | {% if modVars.sendConfirmationToUser and modVars.showUserFormat %} 134 | {{ form_row(form.userFormat) }} 135 | {% endif %} 136 | {% if modVars.showFileAttachment %} 137 | {{ form_row(form.fileUpload) }} 138 | {% endif %} 139 |
140 | 141 |
142 | 143 | 144 | 151 |
152 |
153 |
154 |
155 | 156 | 157 |
158 | 162 |
163 |
164 |
165 | 166 | {% if enableSpamCheck %} 167 | {{ include('@ZikulaFormiculaModule/Include/spamCheck.html.twig') }} 168 | {% endif %} 169 |
170 | 171 | {% set hooks = notifyDisplayHooks(eventName='zikulaformiculamodule.ui_hooks.forms.form_edit') %} 172 | {% if hooks is iterable and hooks|length > 0 %} 173 | {% for area, hook in hooks %} 174 |
{{ hook|raw }}
175 | {% endfor %} 176 | {% endif %} 177 | 178 |
179 |
180 | {{ form_widget(form.submit) }} 181 |
182 |
183 | 184 | {{ form_end(form) }} 185 | 186 | {{ include('@ZikulaFormiculaModule/Form/3/userFooter.html.twig') }} 187 | 188 | {% set customScript %} 189 | 196 | {% endset %} 197 | {{ pageAddAsset('footer', customScript) }} 198 | -------------------------------------------------------------------------------- /Resources/translations/zikulaformiculamodule.en.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Content-Type: text/plain; charset=UTF-8\n" 4 | "Content-Transfer-Encoding: 8bit\n" 5 | "Language: en\n" 6 | 7 | msgid "(to prevent spam)" 8 | msgstr "(to prevent spam)" 9 | msgid "- Make a choice -" 10 | msgstr "- Make a choice -" 11 | msgid "A visitor of to your web site used the form for contact and sent the following:" 12 | msgstr "A visitor of to your web site used the form for contact and sent the following:" 13 | msgid "A visitor to your website made a new rental request and sent the following:" 14 | msgstr "A visitor to your website made a new rental request and sent the following:" 15 | msgid "Actions" 16 | msgstr "Actions" 17 | msgid "Activate simple spam check" 18 | msgstr "Activate simple spam check" 19 | msgid "Add contact" 20 | msgstr "Add contact" 21 | msgid "Agree with terms and conditions" 22 | msgstr "Agree with terms and conditions" 23 | msgid "All public contacts or form default" 24 | msgstr "All public contacts or form default" 25 | msgid "Amount of persons" 26 | msgstr "Amount of persons" 27 | msgid "An email with the filled in data will be sent to our and your email address (%s). We will reply as soon as possible." 28 | msgstr "An email with the filled in data will be sent to our and your email address (%s). We will reply as soon as possible." 29 | msgid "An error occurred while creating the cache directory at %s." 30 | msgstr "An error occurred while creating the cache directory at %s." 31 | msgid "An error occurred while removing the cache directory at %s." 32 | msgstr "An error occurred while removing the cache directory at %s." 33 | msgid "Apply as" 34 | msgstr "Apply as" 35 | msgid "Apply online" 36 | msgstr "Apply online" 37 | msgid "Apply online!" 38 | msgstr "Apply online!" 39 | msgid "Attach a file" 40 | msgstr "Attach a file" 41 | msgid "Attached file" 42 | msgstr "Attached file" 43 | msgid "Basic contact information" 44 | msgstr "Basic contact information" 45 | msgid "Cache directory" 46 | msgstr "Cache directory" 47 | msgid "Cancel" 48 | msgstr "Cancel" 49 | msgid "Clear captcha image cache" 50 | msgstr "Clear captcha image cache" 51 | msgid "Comment" 52 | msgstr "Comment" 53 | msgid "Company" 54 | msgstr "Company" 55 | msgid "Confirmation of your submission will be emailed to you in a few minutes." 56 | msgstr "Confirmation of your submission will be emailed to you in a few minutes." 57 | msgid "Confirmation prompt" 58 | msgstr "Confirmation prompt" 59 | msgid "Contact" 60 | msgstr "Contact" 61 | msgid "Contact ID" 62 | msgstr "Contact ID" 63 | msgid "Contact could not be found." 64 | msgstr "Contact could not be found." 65 | msgid "Contact form" 66 | msgstr "Contact form" 67 | msgid "Contact information" 68 | msgstr "Contact information" 69 | msgid "Contact name" 70 | msgstr "Contact name" 71 | msgid "Contact our team" 72 | msgstr "Contact our team" 73 | msgid "Contact's sender name" 74 | msgstr "Contact's sender name" 75 | msgid "Could not create .htaccess file in %s, please refer to the manual before using the module!" 76 | msgstr "Could not create .htaccess file in %s, please refer to the manual before using the module!" 77 | msgid "Custom fields" 78 | msgstr "Custom fields" 79 | msgid "Date" 80 | msgstr "Date" 81 | msgid "Date of birth" 82 | msgstr "Date of birth" 83 | msgid "Default email format for admin emails" 84 | msgstr "Default email format for admin emails" 85 | msgid "Default email format for user emails" 86 | msgstr "Default email format for user emails" 87 | msgid "Default form" 88 | msgstr "Default form" 89 | msgid "Delete" 90 | msgstr "Delete" 91 | msgid "Delete contact" 92 | msgstr "Delete contact" 93 | msgid "Delete form submission" 94 | msgstr "Delete form submission" 95 | msgid "Delete uploaded file(s) after sending" 96 | msgstr "Delete uploaded file(s) after sending" 97 | msgid "Desired salary" 98 | msgstr "Desired salary" 99 | msgid "Directory for uploaded files" 100 | msgstr "Directory for uploaded files" 101 | msgid "Disable this if you experience problems with your SMTP server" 102 | msgstr "Disable this if you experience problems with your SMTP server" 103 | msgid "Display a specific Formicula form." 104 | msgstr "Display a specific Formicula form." 105 | msgid "Do not use spam check in these forms" 106 | msgstr "Do not use spam check in these forms" 107 | msgid "Do you really want to delete contact '%s'?" 108 | msgstr "Do you really want to delete contact '%s'?" 109 | msgid "Do you really want to delete form submission '%s'?" 110 | msgstr "Do you really want to delete form submission '%s'?" 111 | msgid "Done! Contact created." 112 | msgstr "Done! Contact created." 113 | msgid "Done! Contact deleted." 114 | msgstr "Done! Contact deleted." 115 | msgid "Done! Contact updated." 116 | msgstr "Done! Contact updated." 117 | msgid "Done! Module configuration updated." 118 | msgstr "Done! Module configuration updated." 119 | msgid "Done! Submission deleted." 120 | msgstr "Done! Submission deleted." 121 | msgid "Edit contact" 122 | msgstr "Edit contact" 123 | msgid "Email" 124 | msgstr "Email" 125 | msgid "Email address" 126 | msgstr "Email address" 127 | msgid "Email address(es)" 128 | msgstr "Email address(es)" 129 | msgid "Email and confirmation settings" 130 | msgstr "Email and confirmation settings" 131 | msgid "Email confirmation format" 132 | msgstr "Email confirmation format" 133 | msgid "Email: %1$s - UID: %2$s" 134 | msgstr "Email: %1$s - UID: %2$s" 135 | msgid "End of rental period" 136 | msgstr "End of rental period" 137 | msgid "Enter a valid email address" 138 | msgstr "Enter a valid email address" 139 | msgid "Enter a valid url" 140 | msgstr "Enter a valid url" 141 | msgid "Enter comma separated list of form ids or leave empty for storing all forms." 142 | msgstr "Enter comma separated list of form ids or leave empty for storing all forms." 143 | msgid "Enter comma separated list of form ids or leave empty for using the spam check in all forms." 144 | msgstr "Enter comma separated list of form ids or leave empty for using the spam check in all forms." 145 | msgid "Enter your comments here" 146 | msgstr "Enter your comments here" 147 | msgid "Entry date" 148 | msgstr "Entry date" 149 | msgid "Error! Could not store your submission into the database." 150 | msgstr "Error! Could not store your submission into the database." 151 | msgid "Error! Incorrect email address [%s] supplied." 152 | msgstr "Error! Incorrect email address [%s] supplied." 153 | msgid "Error! No or incorrect email address supplied." 154 | msgstr "Error! No or incorrect email address supplied." 155 | msgid "Error! No or invalid name given." 156 | msgstr "Error! No or invalid name given." 157 | msgid "Error! No value given for mandatory field \"%s\"." 158 | msgstr "Error! No value given for mandatory field \"%s\"." 159 | msgid "Extra 1" 160 | msgstr "Extra 1" 161 | msgid "Extra 2" 162 | msgstr "Extra 2" 163 | msgid "Extra 3" 164 | msgstr "Extra 3" 165 | msgid "Female" 166 | msgstr "Female" 167 | msgid "Field" 168 | msgstr "Field" 169 | msgid "File upload settings" 170 | msgstr "File upload settings" 171 | msgid "Finish and send" 172 | msgstr "Finish and send" 173 | msgid "For your information: There are better spam check modules out there. For example the Zikula Captcha module which can be hooked to Formicula. If you want to use this module, then please do not forget to add the required permissions for the Captcha module, too." 174 | msgstr "For your information: There are better spam check modules out there. For example the Zikula Captcha module which can be hooked to Formicula. If you want to use this module, then please do not forget to add the required permissions for the Captcha module, too." 175 | msgid "Form #" 176 | msgstr "Form #" 177 | msgid "Form #%1$s containing %2$s templates" 178 | msgstr "Form #%1$s containing %2$s templates" 179 | msgid "Form submission could not be found." 180 | msgstr "Form submission could not be found." 181 | msgid "Form submission storage" 182 | msgstr "Form submission storage" 183 | msgid "Form ui hooks subscriber" 184 | msgstr "Form ui hooks subscriber" 185 | msgid "Formicula cache directory does not contain the required .htaccess file - Captchas have been disabled." 186 | msgstr "Formicula cache directory does not contain the required .htaccess file - Captchas have been disabled." 187 | msgid "Formicula cache directory does not exist or is not writable - Captchas have been disabled." 188 | msgstr "Formicula cache directory does not exist or is not writable - Captchas have been disabled." 189 | msgid "Formicula form" 190 | msgstr "Formicula form" 191 | msgid "Formicula settings" 192 | msgstr "Formicula settings" 193 | msgid "Gender" 194 | msgstr "Gender" 195 | msgid "General settings" 196 | msgstr "General settings" 197 | msgid "Go back to the form" 198 | msgstr "Go back to the form" 199 | msgid "HTML" 200 | msgstr "HTML" 201 | msgid "Hello %s!" 202 | msgstr "Hello %s!" 203 | msgid "Hello!" 204 | msgstr "Hello!" 205 | msgid "Hostname" 206 | msgstr "Hostname" 207 | msgid "How did you find us?" 208 | msgstr "How did you find us?" 209 | msgid "ID" 210 | msgstr "ID" 211 | msgid "IP address" 212 | msgstr "IP address" 213 | msgid "Identification card number" 214 | msgstr "Identification card number" 215 | msgid "Included extras" 216 | msgstr "Included extras" 217 | msgid "Kind regards" 218 | msgstr "Kind regards" 219 | msgid "Location" 220 | msgstr "Location" 221 | msgid "Mailer module is not available - unable to send emails!" 222 | msgstr "Mailer module is not available - unable to send emails!" 223 | msgid "Make a reservation" 224 | msgstr "Make a reservation" 225 | msgid "Make sure you the necessary form fields are available, see the docs for more information. This option will be turned off by Formicula automatically if no PHP functions for creating images are available." 226 | msgstr "Make sure you the necessary form fields are available, see the docs for more information. This option will be turned off by Formicula automatically if no PHP functions for creating images are available." 227 | msgid "Male" 228 | msgstr "Male" 229 | msgid "Mandatory fields are indicated with an asterisk." 230 | msgstr "Mandatory fields are indicated with an asterisk." 231 | msgid "Math" 232 | msgstr "Math" 233 | msgid "Name" 234 | msgstr "Name" 235 | msgid "New application" 236 | msgstr "New application" 237 | msgid "New contact" 238 | msgstr "New contact" 239 | msgid "New rental request" 240 | msgstr "New rental request" 241 | msgid "No contacts found." 242 | msgstr "No contacts found." 243 | msgid "No form selected." 244 | msgstr "No form selected." 245 | msgid "No submissions found." 246 | msgstr "No submissions found." 247 | msgid "None" 248 | msgstr "None" 249 | msgid "Only store submissions from these forms" 250 | msgstr "Only store submissions from these forms" 251 | msgid "Operation cancelled." 252 | msgstr "Operation cancelled." 253 | msgid "Otherwise" 254 | msgstr "Otherwise" 255 | msgid "Personal data" 256 | msgstr "Personal data" 257 | msgid "Phone number" 258 | msgstr "Phone number" 259 | msgid "Plain text" 260 | msgstr "Plain text" 261 | msgid "Please enter a valid date (mm/dd/yyyy)." 262 | msgstr "Please enter a valid date (mm/dd/yyyy)." 263 | msgid "Please solve this calculation" 264 | msgstr "Please solve this calculation" 265 | msgid "Public" 266 | msgstr "Public" 267 | msgid "Rental data" 268 | msgstr "Rental data" 269 | msgid "Save" 270 | msgstr "Save" 271 | msgid "Send" 272 | msgstr "Send" 273 | msgid "Send confirmation email to user" 274 | msgstr "Send confirmation email to user" 275 | msgid "Sender email address" 276 | msgstr "Sender email address" 277 | msgid "Sender name" 278 | msgstr "Sender name" 279 | msgid "Settings" 280 | msgstr "Settings" 281 | msgid "Show comments textarea" 282 | msgstr "Show comments textarea" 283 | msgid "Show company" 284 | msgstr "Show company" 285 | msgid "Show contact" 286 | msgstr "Show contact" 287 | msgid "Show file attachment" 288 | msgstr "Show file attachment" 289 | msgid "Show location" 290 | msgstr "Show location" 291 | msgid "Show phone number" 292 | msgstr "Show phone number" 293 | msgid "Show url" 294 | msgstr "Show url" 295 | msgid "Show user email format selector" 296 | msgstr "Show user email format selector" 297 | msgid "Site name" 298 | msgstr "Site name" 299 | msgid "Site slogan" 300 | msgstr "Site slogan" 301 | msgid "Site url" 302 | msgstr "Site url" 303 | msgid "Spam check settings" 304 | msgstr "Spam check settings" 305 | msgid "Start of rental period" 306 | msgstr "Start of rental period" 307 | msgid "Store submitted data in database" 308 | msgstr "Store submitted data in database" 309 | msgid "Street" 310 | msgstr "Street" 311 | msgid "Subject" 312 | msgstr "Subject" 313 | msgid "Submission information" 314 | msgstr "Submission information" 315 | msgid "Successfully created the cache directory with a .htaccess file in it." 316 | msgstr "Successfully created the cache directory with a .htaccess file in it." 317 | msgid "Text" 318 | msgstr "Text" 319 | msgid "Thank you %s for your reservation." 320 | msgstr "Thank you %s for your reservation." 321 | msgid "Thank you for the comments posted from our website. The sent data is:" 322 | msgstr "Thank you for the comments posted from our website. The sent data is:" 323 | msgid "Thank you for your questions/comments to our website!" 324 | msgstr "Thank you for your questions/comments to our website!" 325 | msgid "Thank you for your reservation." 326 | msgstr "Thank you for your reservation." 327 | msgid "Thanks for applying, we will keep your data strictly confidential." 328 | msgstr "Thanks for applying, we will keep your data strictly confidential." 329 | msgid "The %s team" 330 | msgstr "The %s team" 331 | msgid "The Formicula form #%1$s is shown here with only contact %2$s" 332 | msgstr "The Formicula form #%1$s is shown here with only contact %2$s" 333 | msgid "The Formicula form #%s is shown here with all contacts" 334 | msgstr "The Formicula form #%s is shown here with all contacts" 335 | msgid "The calculation to prevent spam was incorrect. Please try again." 336 | msgstr "The calculation to prevent spam was incorrect. Please try again." 337 | msgid "The captcha image cache has been cleared." 338 | msgstr "The captcha image cache has been cleared." 339 | msgid "The user has the following IP address/hostname:" 340 | msgstr "The user has the following IP address/hostname:" 341 | msgid "The validation of the hooked security module was incorrect. Please try again." 342 | msgstr "The validation of the hooked security module was incorrect. Please try again." 343 | msgid "The webserver cannot write into this directory!" 344 | msgstr "The webserver cannot write into this directory!" 345 | msgid "There are no image function available - Captchas have been disabled." 346 | msgstr "There are no image function available - Captchas have been disabled." 347 | msgid "There is an error in your input." 348 | msgstr "There is an error in your input." 349 | msgid "There was an error sending the confirmation email to your email address." 350 | msgstr "There was an error sending the confirmation email to your email address." 351 | msgid "There was an error sending the email to our contact." 352 | msgstr "There was an error sending the email to our contact." 353 | msgid "There was an internal error when sending confirmation mail to you." 354 | msgstr "There was an internal error when sending confirmation mail to you." 355 | msgid "This data was sent to us:" 356 | msgstr "This data was sent to us:" 357 | msgid "This form is used when no form is specified." 358 | msgstr "This form is used when no form is specified." 359 | msgid "Type 1" 360 | msgstr "Type 1" 361 | msgid "Type 2" 362 | msgstr "Type 2" 363 | msgid "Type 3" 364 | msgstr "Type 3" 365 | msgid "Type of vehicle" 366 | msgstr "Type of vehicle" 367 | msgid "Use contact mail addresses as sender" 368 | msgstr "Use contact mail addresses as sender" 369 | msgid "User confirmation email data" 370 | msgstr "User confirmation email data" 371 | msgid "User defined field data #num" 372 | msgstr "User defined field data #num" 373 | msgid "User defined field name #num" 374 | msgstr "User defined field name #num" 375 | msgid "Value" 376 | msgstr "Value" 377 | msgid "View contacts" 378 | msgstr "View contacts" 379 | msgid "View form submission" 380 | msgstr "View form submission" 381 | msgid "View form submissions" 382 | msgstr "View form submissions" 383 | msgid "View submissions" 384 | msgstr "View submissions" 385 | msgid "View submitted form data" 386 | msgstr "View submitted form data" 387 | msgid "Visit website" 388 | msgstr "Visit website" 389 | msgid "We will reply as soon as possible." 390 | msgstr "We will reply as soon as possible." 391 | msgid "We will respond to your email address as soon as possible." 392 | msgstr "We will respond to your email address as soon as possible." 393 | msgid "Web Location 1" 394 | msgstr "Web Location 1" 395 | msgid "Web Location 2" 396 | msgstr "Web Location 2" 397 | msgid "Web Location 3" 398 | msgstr "Web Location 3" 399 | msgid "Webmaster" 400 | msgstr "Webmaster" 401 | msgid "Website" 402 | msgstr "Website" 403 | msgid "Yes" 404 | msgstr "Yes" 405 | msgid "Yes, I agree with the Terms and Conditions" 406 | msgstr "Yes, I agree with the Terms and Conditions" 407 | msgid "You can use the following placeholders within the subject:" 408 | msgstr "You can use the following placeholders within the subject:" 409 | msgid "You may enter a single address or a comma separated list of addresses." 410 | msgstr "You may enter a single address or a comma separated list of addresses." 411 | msgid "Your Name" 412 | msgstr "Your Name" 413 | msgid "Your mail to %s" 414 | msgstr "Your mail to %s" 415 | msgid "Your name" 416 | msgstr "Your name" 417 | msgid "Zip City" 418 | msgstr "Zip City" --------------------------------------------------------------------------------