Skip to content

Commit 00ae66c

Browse files
committed
Merge branch 'master' into feat/docs
2 parents a97bc58 + d500b49 commit 00ae66c

27 files changed

+276
-77
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ composer.lock
55
*.sublime-project
66
*.sublime-workspace
77
/build
8-
/env
8+
env
99
site

CHANGELOG.md

+25-5
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,26 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7-
## [1.1.0] - XXXX-XX-XX
7+
## [2.0.3] - 2017-12-13
88
### Added
9+
- `setRequired` to `Field` class;
10+
- Twig Filter `merge_str` to merge value into as array value through implode.
11+
12+
### Fixed
13+
- Form field error class being ignored in `Bootstrap4TemplatePack`.
14+
15+
## [2.0.2] - 2017-12-12
16+
### Changed
17+
- `Twig` minimal version supported setted to `>=1.35`.
18+
19+
## [2.0.1] - 2017-12-11
20+
### Changed
21+
- Loading `Twig` classes with psr-4 mode;
22+
- Select `option` tag don't render `value` if it is empty.
23+
24+
## [2.0.0] - 2017-12-11
25+
### Added
26+
- Documentation of package;
927
- Renderers to facilitate integrations of template-engines:
1028
- Added `Renderer` interface;
1129
- Added `TwigRenderer` that integrates `twig/twig`;
@@ -15,12 +33,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1533
- Added template pack `DefaultTemplatePack`. Defined as default template pack;
1634
- Added template pack `Bootstrap4TemplatePack` that integrates Bootstrap v4.0.0-beta.2.
1735
- `Config` singleton class allowing:
18-
- Configure custom template packs class;
19-
- Configure custom messages class;
20-
- Configure custom renderers class.
21-
- Added extra arg `label` to method `getContext` of `Widget` class.
36+
- Configure custom template packs;
37+
- Configure custom messages;
38+
- Configure custom renderers.
39+
- Added extra arg `label` to method `getContext` of `Widget` class;
40+
- `BoundWidget` class to represent the choices of a `ChoiceWidget` in `BoundField`, allowing individual render or data access to each option.
2241

2342
### Changed
43+
- `BoundField` moved from `Fields` to new namespace `Bounds`;
2444
- `BoundField` attribute name `choices` changed to `options`;
2545
- `BoundField` attribute `options` now return an array instead of formated string;
2646
- `Widgets`, `labelTag` and `ErrorList` now render through default renderer instead of formatter `fleshgrinder/format`;

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# PHP Form
22
[![Build Status](https://travis-ci.org/dipcode-software/php-form.svg?branch=master)](https://travis-ci.org/dipcode-software/php-form)
33
[![Coverage Status](https://coveralls.io/repos/github/dipcode-software/php-form/badge.svg?branch=master)](https://coveralls.io/github/dipcode-software/php-form?branch=master)
4+
[![Latest Stable Version](https://poser.pugx.org/dipcode/php-form/v/stable)](https://packagist.org/packages/dipcode/php-form)
5+
[![Documentation](https://alexandriadocs.io/projects/php-form/badge-url/?style=flat)](https://alexandriadocs.io/docs/php-form/index.html)
46
[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](http://www.opensource.org/licenses/MIT)
57

6-
PHP class for form handling abstraction inspired in Django Framework forms.
8+
Full featured form engine library inspired in Django Framework.
79

810
## Instalation
911
Library can be installed using Composer like so:

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"require": {
2121
"php": ">=7.0.0",
2222
"fleshgrinder/format": "^1.1",
23-
"twig/twig": "^2.4"
23+
"twig/twig": ">=1.35"
2424
},
2525
"require-dev": {
2626
"phpunit/phpunit": "~6.0",

docs/deploy.sh

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
#!/bin/sh
2-
pip install -r docs/requirements.txt
3-
cd docs/php-form
4-
mkdocs build
5-
tar -zcvf phpform.tar.gz -C site .
6-
curl -X POST -H "Content-Type: multipart/form-data" -H "Api-Key: ${1}" -F "[email protected]" https://alexandriadocs.io/api/v1/projects/upload/
7-
rm phpform.tar.gz
1+
#!/bin/bash
2+
3+
cd docs/
4+
source env/bin/activate && \
5+
pip install -r requirements.txt && \
6+
cd php-form && \
7+
mkdocs build && \
8+
tar -zcvf phpform.tar.gz -C site . && \
9+
curl -X POST -H "Content-Type: multipart/form-data" -H "Api-Key: ${1}" -F "[email protected]" https://alexandriadocs.io/api/v1/projects/upload/ && \
10+
rm phpform.tar.gz

docs/php-form/docs/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Welcome to PHPForm documentation
22
[![Build Status](https://travis-ci.org/dipcode-software/php-form.svg?branch=master)](https://travis-ci.org/dipcode-software/php-form)
33
[![Coverage Status](https://coveralls.io/repos/github/dipcode-software/php-form/badge.svg?branch=master)](https://coveralls.io/github/dipcode-software/php-form?branch=master)
4+
[![Latest Stable Version](https://poser.pugx.org/dipcode/php-form/v/stable)](https://packagist.org/packages/dipcode/php-form)
45
[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](http://www.opensource.org/licenses/MIT)
5-
[![Documentation](https://alexandriadocs.io/projects/php-form/badge-url/?style=flat)](https://alexandriadocs.io/docs/php-form/index.html)
66

77
PHP class for form handling abstraction inspired in the fantastic Django Framework Forms.
88

src/Fields/BoundField.php renamed to src/Bounds/BoundField.php

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?php
2-
namespace PHPForm\Fields;
2+
namespace PHPForm\Bounds;
33

44
use PHPForm\Config;
55

@@ -10,7 +10,7 @@ class BoundField
1010
private $form;
1111
private $field;
1212
private $name;
13-
private $options_cache;
13+
private $bound_widgets_cache;
1414

1515
public $html_name;
1616
public $help_text;
@@ -55,18 +55,25 @@ public function __get($name)
5555
}
5656

5757
if ($name == 'options') {
58-
if (!isset($options_cache)) {
59-
$options_cache = $this->getOptions();
58+
if (!isset($bound_widgets_cache)) {
59+
$bound_widgets_cache = $this->getSubWidgets();
6060
}
61-
return $options_cache;
61+
return $bound_widgets_cache;
6262
}
6363
}
6464

65-
private function getOptions(array $attrs = array())
65+
private function getSubWidgets(array $attrs = array())
6666
{
67+
$bounds = [];
68+
6769
$attrs = $this->buildWidgetAttrs($attrs);
70+
$options = $this->field->getWidget()->getOptions($this->html_name, $this->getValue(), $attrs);
71+
72+
foreach ($options as $option) {
73+
$bounds[] = new BoundWidget($option);
74+
}
6875

69-
return $this->field->getWidget()->getOptions($this->html_name, $this->getValue(), $attrs);
76+
return $bounds;
7077
}
7178

7279
protected function asWidget($widget = null, array $attrs = array())

src/Bounds/BoundWidget.php

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
namespace PHPForm\Bounds;
3+
4+
use PHPForm\Config;
5+
6+
class BoundWidget
7+
{
8+
private $data;
9+
private $template;
10+
11+
public $for;
12+
public $type;
13+
public $name;
14+
public $value;
15+
public $label;
16+
17+
public function __construct(array $data)
18+
{
19+
$this->for = $data["for"];
20+
$this->type = $data["type"];
21+
$this->name = $data["name"];
22+
$this->value = $data["value"];
23+
$this->label = $data["label"];
24+
$this->template = $data["template"];
25+
26+
unset($data["template"]);
27+
28+
$this->data = $data;
29+
}
30+
31+
public function __toString()
32+
{
33+
$renderer = Config::getInstance()->getRenderer();
34+
35+
return $renderer->render($this->template, $this->data);
36+
}
37+
}

src/Config.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
class Config extends Singleton
99
{
10-
const VERSION = "v1.1.0";
10+
const VERSION = "v2.0.3";
1111

1212
/**
1313
* @var array Template packs to be used. The templates will be loaded
@@ -39,17 +39,17 @@ class Config extends Singleton
3939
*/
4040
public function setTemplatePack(string $template_pack)
4141
{
42-
$this->template_packs = array_unshift($this->template_packs, $template_pack);
42+
array_unshift($this->template_packs, $template_pack);
4343
}
4444

4545
/**
46-
* Set messages class.
46+
* Redefine default messages.
4747
*
48-
* @param string Class name of Renderer.
48+
* @param array Messages array.
4949
*/
50-
public function setMessages(string $messages_class)
50+
public function setMessages(array $messages)
5151
{
52-
$this->messages_class = $messages_class;
52+
$this->messages_class::setMessages($messages);
5353
}
5454

5555
/**

src/Fields/Field.php

+10
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,16 @@ public function isDisabled()
137137
return $this->disabled;
138138
}
139139

140+
/**
141+
* Set disabled value.
142+
*
143+
* @param bool
144+
*/
145+
public function setDisabled(bool $value)
146+
{
147+
$this->disabled = $value;
148+
}
149+
140150
/**
141151
* Return defined label or construct one based on the field name.
142152
*

src/Forms/Form.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
use Iterator;
88
use UnexpectedValueException;
99

10+
use PHPForm\Bounds\BoundField;
1011
use PHPForm\Errors\ErrorList;
1112
use PHPForm\Exceptions\ValidationError;
12-
use PHPForm\Fields\BoundField;
1313

1414
abstract class Form implements ArrayAccess, Iterator, Countable
1515
{

src/Messages.php

+27-17
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,32 @@
88

99
class Messages
1010
{
11-
const REQUIRED = 'This field is required.';
12-
const INVALID_CHOICE = 'Select a valid choice. "{choice}" is not one of the available choices.';
13-
const INVALID_LIST = 'Enter a list of values.';
14-
const INVALID_DATE = 'Enter a valid date.';
15-
const INVALID_DATETIME = 'Enter a valid date/time.';
16-
const INVALID_NUMBER = 'Enter a whole number.';
17-
const INVALID_EMAIL = 'Enter a valid email address.';
18-
const INVALID_URL = 'Enter a valid URL.';
19-
const INVALID_FILE = 'Invalid file submitted.';
20-
const EMPTY_FILE = 'The submitted file is empty.';
21-
const INVALID_FILE_MAX_SIZE = 'Ensure the file has at most {limit} bytes (it has {value} bytes).';
22-
const INVALID_FILE_TYPE = 'Ensure the file is one of "{valid_types}" types (it has {type}).';
23-
const INVALID_MAX_LENGTH = 'Ensure this value has at most {limit} character (it has {value}).';
24-
const INVALID_MAX_VALUE = 'Ensure this value is less than or equal to {limit}.';
25-
const INVALID_MIN_LENGTH = 'Ensure this value has at least {limit} character (it has {value}).';
26-
const INVALID_MIN_VALUE = 'Ensure this value is greater than or equal to {limit}.';
11+
/**
12+
* @var array Default messages
13+
*/
14+
private static $messages = array(
15+
"REQUIRED" => 'This field is required.',
16+
"INVALID_CHOICE" => 'Select a valid choice. "{choice}" is not one of the available choices.',
17+
"INVALID_LIST" => 'Enter a list of values.',
18+
"INVALID_DATE" => 'Enter a valid date.',
19+
"INVALID_DATETIME" => 'Enter a valid date/time.',
20+
"INVALID_NUMBER" => 'Enter a whole number.',
21+
"INVALID_EMAIL" => 'Enter a valid email address.',
22+
"INVALID_URL" => 'Enter a valid URL.',
23+
"INVALID_FILE" => 'Invalid file submitted.',
24+
"EMPTY_FILE" => 'The submitted file is empty.',
25+
"INVALID_FILE_MAX_SIZE" => 'Ensure the file has at most {limit} bytes (it has {value} bytes).',
26+
"INVALID_FILE_TYPE" => 'Ensure the file is one of "{valid_types}" types (it has {type}).',
27+
"INVALID_MAX_LENGTH" => 'Ensure this value has at most {limit} character (it has {value}).',
28+
"INVALID_MAX_VALUE" => 'Ensure this value is less than or equal to {limit}.',
29+
"INVALID_MIN_LENGTH" => 'Ensure this value has at least {limit} character (it has {value}).',
30+
"INVALID_MIN_VALUE" => 'Ensure this value is greater than or equal to {limit}.'
31+
);
32+
33+
public static function setMessages(array $messages)
34+
{
35+
self::$messages = array_merge(self::$messages, $messages);
36+
}
2737

2838
/**
2939
* Format message witg context.
@@ -35,7 +45,7 @@ class Messages
3545
*/
3646
public static function format(string $id, array $context = null)
3747
{
38-
$message = defined("static::$id") ? constant("static::$id") : $id;
48+
$message = array_key_exists($id, self::$messages) ? self::$messages[$id] : $id;
3949

4050
if (!is_null($context)) {
4151
$message = Formatter::format($message, $context);

src/Renderers/TwigRenderer.php

+27-7
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
*/
55
namespace PHPForm\Renderers;
66

7-
use Twig_Loader_Filesystem;
8-
use Twig_Environment;
9-
use Twig_Loader_Chain;
7+
use Twig\Loader\ChainLoader;
8+
use Twig\Environment;
9+
use Twig\Loader\FilesystemLoader;
10+
use Twig\TwigFilter;
1011

1112
class TwigRenderer implements Renderer
1213
{
@@ -22,15 +23,34 @@ class TwigRenderer implements Renderer
2223
*
2324
* @param array $template_dirs
2425
*/
25-
public function __construct(array $templates_dirs)
26+
public function __construct(array $templates_dirs, array $options = array())
2627
{
27-
$loaders = new Twig_Loader_Chain();
28+
$loaders = new ChainLoader();
2829

2930
foreach ($templates_dirs as $template_dir) {
30-
$loaders->addLoader(new Twig_Loader_Filesystem($template_dir));
31+
$loaders->addLoader(new FilesystemLoader($template_dir));
3132
}
3233

33-
$this->twig = new Twig_Environment($loaders);
34+
$this->twig = new Environment($loaders, $options);
35+
$this->setFilters();
36+
}
37+
38+
public function setFilters()
39+
{
40+
$filter_merge_str = new TwigFilter('merge_str', function ($attrs, array $options = array()) {
41+
$key = $options[0];
42+
$value = $options[1];
43+
44+
if (array_key_exists($key, $attrs)) {
45+
$attrs[$key] = implode(' ', [$value, $attrs[$key]]);
46+
} else {
47+
$attrs[$key] = $value;
48+
}
49+
50+
return $attrs;
51+
}, array('is_variadic' => true));
52+
53+
$this->twig->addFilter($filter_merge_str);
3454
}
3555

3656
/**
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<label class="custom-file">
2-
{% set attrs = attrs|merge({'class': 'custom-file-input'}) %}
2+
{% set attrs = attrs|merge_str("class", "custom-file-input") %}
33
{% include 'input.html' %}
44
<span class="custom-file-control"></span>
55
</label>

src/TemplatePacks/templates/bootstrap4/multiple_input_option.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<label for="{{for|e}}" class="custom-control custom-{{ type|e }}">
2-
{% set attrs = attrs|merge({'class': 'custom-control-input'}) %}
2+
{% set attrs = attrs|merge_str("class", "custom-control-input") %}
33
{% include 'input.html' %}
44
<span class="custom-control-indicator"></span>
55
<span class="custom-control-description">{{ label|e }}</span>
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<option value="{{value|e}}"{% include 'attrs.html' with attrs %}>{{label|e}}</option>
1+
<option {% if value is not empty %}value="{{value|e}}"{% endif %}{% include 'attrs.html' with attrs %}>{{label|e}}</option>

src/Widgets/FileInput.php

+1-5
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ public function formatValue($value)
3232
*/
3333
public function valueFromData($data, $files, string $name)
3434
{
35-
if (array_key_exists($name, $files)) {
36-
return $files[$name];
37-
}
38-
39-
return null;
35+
return !is_null($files) && array_key_exists($name, $files) ? $files[$name] : null;
4036
}
4137
}

0 commit comments

Comments
 (0)