Skip to content

Commit

Permalink
Merge branch 'release/1.0.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
rhukster committed Dec 1, 2015
2 parents bdae44c + fae31d4 commit e855ff1
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 33 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# v1.0.1
## 12/01/2015

1. [](#new)
* New **file upload** field
* Added modular form template
* Spanish translation
* Hungarian translation

# v1.0.0
## 11/21/2015

Expand Down
37 changes: 34 additions & 3 deletions blueprints.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Form
version: 1.0.0
version: 1.0.1
description: Enables the forms handling
icon: check-square
author:
Expand All @@ -20,7 +20,38 @@ form:
highlight: 1
default: 0
options:
1: Enabled
0: Disabled
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
files:
type: section
title: PLUGIN_FORM.FILES

fields:
multiple:
type: toggle
label: PLUGIN_FORM.ALLOW_MULTIPLE
help: PLUGIN_FORM.ALLOW_MULTIPLE_HELP
highlight: 1
default: 0
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
desination:
type: text
label: PLUGIN_FORM.DESTINATION
help: PLUGIN_FORM.DESTINATION_HELP
default: '@self'
accept:
type: selectize
size: large
label: PLUGIN_FORM.ACCEPT
help: PLUGIN_FORM.ACCEPT_HELP
classes: fancy
default:
- image/*
validate:
type: commalist
137 changes: 110 additions & 27 deletions classes/form.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Grav\Plugin;

use Grav\Common\Filesystem\Folder;
use Grav\Common\Iterator;
use Grav\Common\GravTrait;
use Grav\Common\Page\Page;
Expand Down Expand Up @@ -52,9 +53,9 @@ public function __construct(Page $page)
{
$this->page = $page;

$header = $page->header();
$header = $page->header();
$this->rules = isset($header->rules) ? $header->rules : array();
$this->data = isset($header->data) ? $header->data : array();
$this->data = isset($header->data) ? $header->data : array();
$this->items = $header->form;

// Set form name if not set.
Expand All @@ -68,6 +69,27 @@ public function __construct(Page $page)
self::getGrav()->fireEvent('onFormInitialized', new Event(['form' => $this]));
}

/**
* Reset values.
*/
public function reset()
{
$name = $this->items['name'];

// Fix naming for fields (presently only for toplevel fields)
foreach ($this->items['fields'] as $key => $field) {
if (is_numeric($key) && isset($field['name'])) {
unset($this->items['fields'][$key]);

$key = $field['name'];
$this->items['fields'][$key] = $field;
}
}

$blueprint = new Blueprint($name, ['form' => $this->items, 'rules' => $this->rules]);
$this->values = new Data($this->data, $blueprint);
}

/**
* Return page object for the form.
*
Expand All @@ -82,6 +104,7 @@ public function page()
* Get value of given variable (or all values).
*
* @param string $name
*
* @return mixed
*/
public function value($name = null)
Expand All @@ -96,6 +119,7 @@ public function value($name = null)
* Set value of given variable.
*
* @param string $name
*
* @return mixed
*/
public function setValue($name = null, $value = '')
Expand All @@ -107,34 +131,15 @@ public function setValue($name = null, $value = '')
$this->values->set($name, $value);
}

/**
* Reset values.
*/
public function reset()
{
$name = $this->items['name'];

// Fix naming for fields (presently only for toplevel fields)
foreach ($this->items['fields'] as $key => $field) {
if (is_numeric($key) && isset($field['name'])) {
unset($this->items['fields'][$key]);

$key = $field['name'];
$this->items['fields'][$key] = $field;
}
}

$blueprint = new Blueprint($name, ['form' => $this->items, 'rules' => $this->rules]);
$this->values = new Data($this->data, $blueprint);
}

/**
* Handle form processing on POST action.
*/
public function post()
{
$files = [];
if (isset($_POST)) {
$values = (array) $_POST;
$values = (array)$_POST;
$files = (array)$_FILES;

if (method_exists('Grav\Common\Utils', 'getNonce')) {
if (!isset($values['form-nonce']) || !Utils::verifyNonce($values['form-nonce'], 'form')) {
Expand All @@ -146,22 +151,31 @@ public function post()

unset($values['form-nonce']);

foreach($this->items['fields'] as $field) {
foreach ($this->items['fields'] as $field) {
$name = $field['name'];
if ($field['type'] == 'checkbox') {
$name = $field['name'];
$values[$name] = isset($values[$name]) ? true : false;
}
}


// Add post values to form dataset
$this->values->merge($values);
$this->values->merge($files);
}

// Validate and filter data
try {
$this->values->validate();
$this->values->filter();

foreach ($files as $key => $file) {
$cleanFiles = $this->cleanFilesData($key, $file);
if ($cleanFiles) {
$this->values->set($key, $cleanFiles);
}
}

self::getGrav()->fireEvent('onFormValidationProcessed', new Event(['form' => $this]));
} catch (\RuntimeException $e) {
$event = new Event(['form' => $this, 'message' => $e->getMessage()]);
Expand All @@ -176,12 +190,81 @@ public function post()
foreach ($process as $action => $data) {
if (is_numeric($action)) {
$action = \key($data);
$data = $data[$action];
$data = $data[$action];
}
self::getGrav()->fireEvent('onFormProcessed', new Event(['form' => $this, 'action' => $action, 'params' => $data]));
}
} else {
// Default action.
}
}

private function cleanFilesData($key, $file)
{
/** @var Page $page */
$page = null;
$blueprint = $this->items['fields'][$key]['files'];
$cleanFiles[$key] = [];
if (!isset($blueprint)) {
return false;
}

$cleanFiles = [ $key => []];
foreach ((array)$file['error'] as $index => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $file['tmp_name'][$index];
$name = $file['name'][$index];
$type = $file['type'][$index];
$destination = Folder::getRelativePath(rtrim($blueprint['destination'], '/'));

if (!$this->match_in_array($type, $blueprint['accept'])) {
throw new \RuntimeException('File "' . $name . '" is not an accepted MIME type.');
}

if (Utils::startsWith($destination, '@page:')) {
$parts = explode(':', $destination);
$route = $parts[1];
$page = self::getGrav()['page']->find($route);

if (!$page) {
throw new \RuntimeException('Unable to upload file to destination. Page route not found.');
}

$destination = $page->relativePagePath();
} else if ($destination == '@self') {
$page = self::getGrav()['page'];
$destination = $page->relativePagePath();
} else {
Folder::mkdir($destination);
}

if (move_uploaded_file($tmp_name, "$destination/$name")) {
$path = $page ? self::getGrav()['uri']->convertUrl($page, $page->route() . '/' . $name) : $destination . '/' . $name;
$cleanFiles[$key][$path] = [
'name' => $file['name'][$index],
'type' => $file['type'][$index],
'size' => $file['size'][$index],
'file' => $destination . '/' . $name,
'route' => $page ? $path : null
];
} else {
throw new \RuntimeException('Unable to upload file(s). Error Code: ' . $error);
}
}
}

return $cleanFiles[$key];
}

private function match_in_array($needle, $haystack)
{
foreach((array) $haystack as $item) {
if (true == preg_match("#^".strtr(preg_quote($item, '#'), array('\*' => '.*', '\?' => '.'))."$#i", $needle))
{
return true;
}
}

return false;
}
}
5 changes: 5 additions & 0 deletions form.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
enabled: true
files:
multiple: false
destination: '@self'
accept:
- image/*
31 changes: 30 additions & 1 deletion languages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,37 @@ en:
PLUGIN_FORM:
NOT_VALIDATED: "Form not validated. One or more required fields are missing."
NONCE_NOT_VALIDATED: "Oops there was a problem, please check your input and submit the form again."
FILES: "Files Upload"
ALLOW_MULTIPLE: "Allow More than one file"
ALLOW_MULTIPLE_HELP: "Allows to select more than one file for upload."
DESTINATION: "Destination"
DESTINATION_HELP: "The location where the files should be uploaded to"
ACCEPT: "Allowed MIME Types"
ACCEPT_HELP: "A list of MIME Types that are allowed for upload"

it:
PLUGIN_FORM:
NOT_VALIDATED: "Il Form risulta invalido. Uno o più campi risultano omessi."
NONCE_NOT_VALIDATED: "Oops è stato riscontrato un errore, si prega di ricontrollare i dati inseriti e provare di nuovo."
FILES: "Invio dei Files"
ALLOW_MULTIPLE: "Consenti più di un file"
ALLOW_MULTIPLE_HELP: "Permette la selezione di più di un file per l'upload"
DESTINATION: "Destinazione"
DESTINATION_HELP: "La destinazione dove i files vengono uploadati"
ACCEPT: "Tipi di MIME Concessi"
ACCEPT_HELP: "Una lista di tipi di MIME che sono permessi per l'upload"

fr:
PLUGIN_FORM:
NOT_VALIDATED: "Formulaire non validé. Un ou plusieurs champs obligatoires sont manquants."
NONCE_NOT_VALIDATED: "Oops, il y a un problème. Vérifiez s'il vous plait votre saisie et soumettez de nouveau le formulaire."
NONCE_NOT_VALIDATED: "Oups, un problème est survenu. Veuillez vérifier votre saisie et soumettez à nouveau le formulaire."

es:
PLUGIN_FORM:
NOT_VALIDATED: "Falló la validación del formulario. Uno o más campos obligatorios no fueron capturados."
NONCE_NOT_VALIDATED: "Oops, hay un problema, por favor revice la información capturada e intente enviar el formulario otra vez."

hu:
PLUGIN_FORM:
NOT_VALIDATED: "Érvénytelen az űrlap. Egy vagy több kötelező mező nincs kitöltve."
NONCE_NOT_VALIDATED: "Upsz, van egy kis probléma, kérlek nézd át az űrlapot, majd küld el újra."
11 changes: 10 additions & 1 deletion templates/forms/default/form.html.twig
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
{% if form.message %}<div class="alert">{{ form.message }}</div>{% endif %}
{% set multipart = '' %}
{% set method = form.method|upper|default('POST') %}

{% for field in form.fields %}
{% if (method == 'POST' and field.type == 'file') %}
{% set multipart = ' enctype="multipart/form-data"' %}
{% endif %}
{% endfor %}

<form name="{{ form.name }}"
action="{{ form.action ? base_url ~ form.action : page.url }}"
method="{{ form.method|upper|default('POST') }}">
method="{{ method }}"{{ multipart }}>

{% for field in form.fields %}
{% set value = form.value(field.name) %}
<div>
Expand Down
2 changes: 1 addition & 1 deletion templates/forms/fields/captcha/captcha.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
'callback': captchaValidatedCallback,
'expired-callback': captchaExpiredCallback
});
}
};
var captchaValidatedCallback = function captchaValidatedCallback() {
Expand Down
18 changes: 18 additions & 0 deletions templates/forms/fields/file/file.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "forms/field.html.twig" %}
{% set defaults = config.plugins.form %}
{% set files = defaults.files|merge(field.files|default([])) %}

{% block input %}
<div class="form-input-wrapper {{ field.size }}">
<input
{# required attribute structures #}
name="{{ (scope ~ field.name)|fieldName ~ (files.multiple ? '[]' : '[]') }}"
{% block input_attributes %}
type="file"
{% if files.multiple %}multiple="multiple"{% endif %}
{% if files.accept %}accept="{{ files.accept|join(',') }}"{% endif %}
{{ parent() }}
{% endblock %}
/>
</div>
{% endblock %}
4 changes: 4 additions & 0 deletions templates/modular/form.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{% block content %}
{{ content }}
{% include "forms/form.html.twig" %}
{% endblock %}

0 comments on commit e855ff1

Please sign in to comment.