1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of slick/form package |
5
|
|
|
* |
6
|
|
|
* For the full copyright and license information, please view the LICENSE |
7
|
|
|
* file that was distributed with this source code. |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace Slick\Form\Parser; |
11
|
|
|
|
12
|
|
|
use Slick\Form\Exception\InvalidArgumentException; |
13
|
|
|
use Slick\Form\Exception\ParserErrorException; |
14
|
|
|
use Slick\Form\FormInterface; |
15
|
|
|
use Slick\Form\Parser\Worker\AddElements; |
16
|
|
|
use Slick\Form\Parser\Worker\FormId; |
17
|
|
|
use Symfony\Component\Yaml\Yaml; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Form Definitions Parser |
21
|
|
|
* |
22
|
|
|
* This class is used by the FormRegistry when creating forms |
23
|
|
|
* based on YAML definitions. |
24
|
|
|
* |
25
|
|
|
* @package Slick\Form\Parser |
26
|
|
|
* @author Filipe Silva <[email protected]> |
27
|
|
|
*/ |
28
|
|
|
class YamlParser implements ParserInterface |
29
|
|
|
{ |
30
|
|
|
|
31
|
|
|
/** Default form class to create */ |
32
|
|
|
const DEFAULT_FORM_CLASS = 'Slick\Form\Form'; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var array The YAML parser data |
36
|
|
|
*/ |
37
|
|
|
protected $parsedData; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var WorkerInterface[] |
41
|
|
|
*/ |
42
|
|
|
protected static $workers = [ |
43
|
|
|
'formId' => FormId::class, |
44
|
|
|
'addElements' => AddElements::class |
45
|
|
|
]; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Crates a definition parser |
49
|
|
|
* |
50
|
|
|
* @param string $definitions The full path for definitions file |
51
|
|
|
*/ |
52
|
28 |
|
public function __construct($definitions) |
53
|
|
|
{ |
54
|
28 |
|
$this->setData($definitions); |
55
|
28 |
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Create form using provided definitions |
59
|
|
|
* |
60
|
|
|
* @param string $definitions |
61
|
|
|
* |
62
|
|
|
* @return FormInterface |
63
|
|
|
*/ |
64
|
16 |
|
public static function create($definitions) |
65
|
|
|
{ |
66
|
16 |
|
$parser = new static($definitions); |
67
|
8 |
|
return $parser->getForm(); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Gets the resulting form object |
72
|
|
|
* |
73
|
|
|
* @return FormInterface |
74
|
|
|
*/ |
75
|
20 |
|
public function getForm() |
76
|
|
|
{ |
77
|
20 |
|
$form = $this->createForm(); |
78
|
12 |
|
$this->workout($form); |
79
|
12 |
|
return $form; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Updates the form with definitions from parsed data |
84
|
|
|
* |
85
|
|
|
* @param FormInterface $form |
86
|
|
|
*/ |
87
|
12 |
|
protected function workout(FormInterface $form) |
88
|
|
|
{ |
89
|
12 |
|
foreach (self::$workers as $worker) { |
90
|
12 |
|
call_user_func_array( |
91
|
12 |
|
[$worker, 'execute'], |
92
|
12 |
|
[$form, $this->parsedData] |
93
|
12 |
|
); |
94
|
12 |
|
} |
95
|
12 |
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Creates the form class |
99
|
|
|
* |
100
|
|
|
* @return FormInterface |
101
|
|
|
*/ |
102
|
20 |
|
protected function createForm() |
103
|
|
|
{ |
104
|
20 |
|
$class = self::DEFAULT_FORM_CLASS; |
105
|
20 |
|
if (array_key_exists('class', $this->parsedData)) { |
106
|
14 |
|
$class = $this->checkClass($this->parsedData['class']); |
107
|
6 |
|
} |
108
|
|
|
|
109
|
12 |
|
return new $class; |
110
|
|
|
} |
111
|
|
|
|
112
|
14 |
|
protected function checkClass($name) |
113
|
|
|
{ |
114
|
14 |
|
if (! class_exists($name)) { |
115
|
4 |
|
throw new InvalidArgumentException( |
116
|
4 |
|
"The form class '{$name}' does not exists." |
117
|
4 |
|
); |
118
|
|
|
} |
119
|
|
|
|
120
|
10 |
|
if (! is_subclass_of($name, FormInterface::class)) { |
121
|
4 |
|
throw new InvalidArgumentException( |
122
|
4 |
|
"The class '{$name}' does not implements the " . |
123
|
|
|
"FormInterface interface" |
124
|
4 |
|
); |
125
|
|
|
} |
126
|
6 |
|
return $name; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Sets definition data for form creation |
131
|
|
|
* |
132
|
|
|
* @param mixed $definitions |
133
|
|
|
* |
134
|
|
|
* @return self|$this|ParserInterface |
135
|
|
|
*/ |
136
|
14 |
View Code Duplication |
public function setData($definitions) |
|
|
|
|
137
|
|
|
{ |
138
|
14 |
|
if (is_array($definitions)) { |
139
|
4 |
|
$this->parsedData = $definitions; |
140
|
4 |
|
return; |
141
|
|
|
} |
142
|
|
|
|
143
|
14 |
|
if (!is_file($definitions)) { |
144
|
2 |
|
throw new InvalidArgumentException( |
145
|
2 |
|
"The form definition file '{$definitions}' does not exists." |
146
|
2 |
|
); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
try { |
150
|
14 |
|
$this->parsedData = Yaml::parse(file_get_contents($definitions)); |
|
|
|
|
151
|
14 |
|
} catch (\Exception $caught) { |
152
|
2 |
|
throw new ParserErrorException( |
153
|
2 |
|
'Error parsing form definitions: '.$caught->getMessage(), |
154
|
2 |
|
0, |
155
|
|
|
$caught |
156
|
2 |
|
); |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.