Skip to content

Commit

Permalink
Merge branch '4.0' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
rhukster committed Nov 6, 2019
2 parents df4fee4 + 0c57846 commit 586ab59
Show file tree
Hide file tree
Showing 19 changed files with 343 additions and 226 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# v4.0.0
## 10/06/2019

1. [](#new)
* Added `tabindex` to global attributes of default field
* Add ability to Sanitize SVGs on upload (Grav 1.7+ required)
1. [](#improved)
* Deprecate `select_optgroup` as `select` can handle optgroups now
* Added missing tabindex checks
* Refactored field inheritance to make things more reliable
* Removed jQuery dependency for the reCaptcha field and VanillaJS-ified it instead
* Removed a stray `dump()` command
* Refactored the base `templates/forms/default` twig templates to make things more extensible
* Added a new `templates/forms/layouts` set of twit templates to allow for easier customization
1. [](#bugfix)
* Fixed `Badly encoded JSON data` warning when uploading files [grav#2663](https://github.com/getgrav/grav/issues/2663)
* Fixed a number of escaping issues [#368](https://github.com/getgrav/grav-plugin-form/issues/368)

# v3.0.9
## 09/19/2019

Expand Down
2 changes: 1 addition & 1 deletion blueprints.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Form
version: 3.0.9
version: 4.0.0
testing: false
description: Enables the forms handling
icon: check-square
Expand Down
6 changes: 6 additions & 0 deletions classes/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Grav\Common\Inflector;
use Grav\Common\Language\Language;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Security;
use Grav\Common\Uri;
use Grav\Common\Utils;
use Grav\Framework\Filesystem\Filesystem;
Expand Down Expand Up @@ -652,6 +653,11 @@ public function uploadFiles()
$upload['file']['name'] = $filename;
$upload['file']['path'] = $path;

// Special Sanitization for SVG
if (method_exists('Grav\Common\Security', 'sanitizeSVG') && Utils::contains($mime, 'svg', false)) {
Security::sanitizeSVG($upload['file']['tmp_name']);
}

// We need to store the file into flash object or it will not be available upon save later on.
$flash = $this->getFlash();
$flash->setUrl($url)->setUser($grav['user'] ?? null);
Expand Down
216 changes: 116 additions & 100 deletions templates/forms/default/field.html.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{% if not field.validate.ignore %}
{% if not field.validate.ignore %}

{% use 'forms/layouts/field-variables.html.twig' %}
{% block field_override_variables_before %}{% endblock %}

{% set field_name = (scope ~ field.name)|fieldName %}
{% set vertical = field.style == 'vertical' %}
Expand Down Expand Up @@ -27,6 +30,12 @@
{# DEPRECATED: Needed by old form fields; remove when backwards compatibility breaks are allowed #}
{% set isDisabledToggleable = toggleable and not toggleableChecked %}

{% if toggleable %}
{% set form_field_toggleable %}
{% include 'forms/default/toggleable.html.twig' with {checked: toggleableChecked} %}
{% endset %}
{% endif %}

{% set errors = attribute(form.messages, field.name) %}
{% set required = client_side_validation and field.validate.required in ['on', 'true', 1] %}
{% set autofocus = (inline_errors == false) and field.autofocus in ['on', 'true', 1] %}
Expand All @@ -35,105 +44,112 @@
{% set autofocus = true %}
{% endif %}

{% block field %}
<div class="form-field {{ form_field_outer_classes }} {{ field.outerclasses }} {% if errors %} has-errors{% endif %} {% block outer_field_classes %}{% endblock %} {% if toggleable %} form-field-toggleable{% endif %}">
{% block contents %}
{% if field.label is not same as(false) and field.display_label is not same as(false) %}
<div class="{{ form_field_outer_label_classes ?: 'form-label' }} {{ field.labelclasses }}">
{% if toggleable %}
{% include 'forms/default/toggleable.html.twig' with {field_name: field_name, field: field, checked: toggleableChecked} %}
{% endif %}
<label class="{{ form_field_label_classes ?: 'inline' }} {{ toggleable ? 'toggleable' }}" {% if field.id is defined %}for="{{ toggleable ? 'toggleable_' ~ field.name : field.id|e }}" {% endif %} >
{% block label %}
{% if field.help %}
{% if field.markdown %}
<span class="tooltip" data-asTooltip-position="w" title="{{ field.help|t|markdown(false)|e }}">{{ field.label|markdown(false)|default(field.name|capitalize)|t }}</span>
{% else %}
<span class="tooltip" data-asTooltip-position="w" title="{{ field.help|t|e }}">{{ field.label|default(field.name|capitalize)|t }}</span>
{% endif %}
{% else %}
{% if field.markdown %}
{{ field.label|markdown(false)|default(field.name|capitalize)|t }}
{% else %}
{{ field.label|default(field.name|capitalize)|t|e('html_attr') }}
{% endif %}
{% endif %}

{{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
{% endblock %}
</label>
</div>
{% endif %}
<div class="{{ form_field_outer_data_classes ?: 'form-data' }} {{ field.dataclasses }}"
{% block global_attributes %}
data-grav-field="{{ field.type }}"
data-grav-disabled="{{ toggleable and toggleableChecked }}"
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
{% endblock %}
>
{% block group %}
{% block input %}
<div class="{{ form_field_wrapper_classes ?: 'form-input-wrapper' }} {{ field.size }} {{ field.wrapper_classes }}">
{% block prepend %}{% endblock prepend %}
<input
{# required attribute structures #}
name="{{ (scope ~ field.name)|fieldName }}"
value="{{ value|join(', ')|e('html_attr') }}"
{# input attribute structures #}
{% block input_attributes %}
class="{{ form_field_input_classes }} {{ field.classes }} {{ field.size }}"
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder|t|e('html_attr') }}"{% endif %}
{% if autofocus %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.autocomplete is defined %}autocomplete="{{ field.autocomplete }}"{% endif %}
{% if field.autocapitalize in ['off', 'characters', 'words', 'sentences'] %}autocapitalize="{{ field.autocapitalize }}"{% endif %}
{% if field.inputmode in ['none', 'text', 'decimal', 'numeric', 'tel', 'search', 'email', 'url'] %}inputmode="{{ field.inputmode }}"{% endif %}
{% if field.spellcheck in ['true', 'false'] %}spellcheck="{{ field.spellcheck }}"{% endif %}

{% if field.attributes is defined %}
{% for attribute in field.attributes %}
{{ attribute.name }}="{{ attribute.value|e }}"
{% endfor %}
{% endif %}
{% if required %}required="required"{% endif %}
{% if field.validate.pattern %}pattern="{{ field.validate.pattern|e }}"{% endif %}
{% if field.validate.message %}title="{{ field.validate.message|t|e }}"
{% elseif field.title is defined %}title="{{ field.title|t|e }}" {% endif %}
{% if field.datasets %}
{% for datakey, datavalue in field.datasets %}
data-{{ datakey }}="{{ datavalue|e('html_attr') }}"
{% endfor %}
{% endif %}
{% endblock %}
/>
{% block append %}{% endblock append %}
{% if inline_errors and errors %}
<div class="{{ form_errors_classes ?: 'form-errors' }}">
<p class="form-message"><i class="fa fa-exclamation-circle"></i> {{ errors|first }}</p>
</div>
{% endif %}
</div>
{% endblock %}
{% endblock %}
{% if field.description %}
<div class="form-extra-wrapper {{ field.wrapper_classes }}">
<span class="form-description">
{% if field.markdown %}
{{ field.description|t|markdown(false)|raw }}
{% else %}
{{ field.description|t|raw }}
{% endif %}
</span>
</div>
{% endif %}

</div>
{% endblock %}
</div>
{% set embed_outer_field_classes %}
{% block outer_field_classes %}{% endblock %}
{% endset %}

{# Field Classes #}
{%- if errors %}{% set form_field_outer_core = form_field_outer_core ~ ' has-errors' %}{% endif -%}
{%- if toggleable %}{% set form_field_outer_core = form_field_outer_core ~ ' form-field-toggleable' %}{% endif -%}

{% set layout_form_field_outer_classes = field.outerclasses %}
{% set layout_form_field_outer_classes = layout_form_field_outer_classes|trim ~ ' ' ~ form_field_outer_classes %}
{% set layout_form_field_outer_classes = layout_form_field_outer_classes|trim ~ ' ' ~ embed_outer_field_classes %}

{# Show Label logic #}
{% set show_label = field.label is not same as(false) and field.display_label is not same as(false )%}

{# Label Classes #}
{% set layout_form_field_outer_label_classes = ((form_field_outer_label_classes ?: 'form-label') ~ ' ' ~ field.labelclasses)|trim %}
{% set layout_form_field_label_classes = (form_field_label_classes ?: 'inline')|trim %}
{% set form_field_label_trim = toggleable ? 'toggleable' %}

{# Field Outer Data classes #}
{% set layout_form_field_outer_data_classes = ((form_field_outer_data_classes ?: ' form-data') ~ ' ' ~ field.dataclasses)|trim %}

{# Field Wrapper classes #}
{% set layout_form_field_wrapper_classes = ((form_field_wrapper_classes ?: ' form-input-wrapper') ~ ' ' ~ field.wrapper_classes)|trim %}

{# Field input classes #}
{% if field|of_type('array') %}
{% if field.classes %}
{% set field = field|merge({'classes': field.classes ~ ' ' ~ block('field_input_classes')|trim }) %}
{% else %}
{% set field = field|merge({'classes': block('field_input_classes') }) %}
{% endif %}
{% endif %}
{% set layout_form_field_input_classes = (form_field_input_classes ~ ' ' ~ field.classes)|trim %}

{# Inline error classes #}
{% set form_field_inline_error_classes = form_field_inline_error_classes ?: ' form-errors' %}

{# Field extra classes #}
{% set form_field_extra_wrapper_classes = 'form-extra-wrapper ' ~ field.wrapper_classes %}

{# Field For #}
{% set form_field_for = toggleable ? 'toggleable_' ~ field.name : field.id|e %}

{# Field Label #}
{% set form_field_label = field.markdown ? field.label|markdown(false) : field.label %}
{% set form_field_label = form_field_label|default(field.name|capitalize)|t|e %}

{# Field Help #}
{% if field.help %}
{% set form_field_help = field.markdown ? field.help|t|markdown(false)|e : field.help|t|e %}
{% endif %}

{# Field Requied #}
{% set form_field_required = field.validate.required in ['on', 'true', 1] ? true : false %}

{# Field Description #}
{% set form_field_description = field.markdown ? field.description|t|markdown(false)|raw : field.description|t|raw %}

{% extends 'forms/layouts/field.html.twig' %}

{% block global_attributes %}
data-grav-field="{{ field.type }}"
data-grav-disabled="{{ toggleable and toggleableChecked }}"
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
{% endblock %}

{% block input_attributes %}
class="{{ layout_form_field_input_classes|trim }} {{ field.size }}"
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder|t|e('html_attr') }}"{% endif %}
{% if autofocus %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.autocomplete is defined %}autocomplete="{{ field.autocomplete }}"{% endif %}
{% if field.autocapitalize in ['off', 'characters', 'words', 'sentences'] %}autocapitalize="{{ field.autocapitalize }}"{% endif %}
{% if field.inputmode in ['none', 'text', 'decimal', 'numeric', 'tel', 'search', 'email', 'url'] %}inputmode="{{ field.inputmode }}"{% endif %}
{% if field.tabindex %}tabindex="{{ field.tabindex }}" %}{% endif %}
{% if field.spellcheck in ['true', 'false'] %}spellcheck="{{ field.spellcheck }}"{% endif %}
{% if required %}required="required"{% endif %}
{% if field.validate.pattern %}pattern="{{ field.validate.pattern|e }}"{% endif %}
{% if field.validate.message %}title="{{ field.validate.message|t|e }}"
{% elseif field.title is defined %}title="{{ field.title|t|e }}" {% endif %}

{# Support key/value and .name/.value styles #}
{% if field.attributes is defined %}
{% for key,attribute in field.attributes %}
{% if attribute|of_type('array') %}
{{ attribute.name }}="{{ attribute.value|e('html_attr') }}"
{% else %}
{{ key }}="{{ attribute|e('html_attr') }}"
{% endif %}
{% endfor %}
{% endif %}

{# Support for Custom data attributes#}
{% if field.datasets %}
{% for key, attribute in field.datasets %}
data-{{ key }}="{{ attribute|e('html_attr') }}"
{% endfor %}
{% endif %}
{% endblock %}



{% endif %}
4 changes: 2 additions & 2 deletions templates/forms/default/fields.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
{% endif %}

{% set value = form ? form.value(field_name) : data.value(field_name) %}
{% block field_open %}{% endblock %}
{% block inner_markup_field_open %}{% endblock %}
{% block field %}
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
{% endblock %}
{% block field_close %}{% endblock %}
{% block inner_markup_field_close %}{% endblock %}
{% endif %}
{% endfor %}
Loading

0 comments on commit 586ab59

Please sign in to comment.