|
1
|
|
|
<?php |
|
2
|
|
|
namespace Former\Traits; |
|
3
|
|
|
|
|
4
|
|
|
use Former\Interfaces\FrameworkInterface; |
|
5
|
|
|
use HtmlObject\Element; |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* Base helpers and common methods to all frameworks |
|
9
|
|
|
*/ |
|
10
|
|
|
abstract class Framework implements FrameworkInterface |
|
11
|
|
|
{ |
|
12
|
|
|
/** |
|
13
|
|
|
* The Container |
|
14
|
|
|
* |
|
15
|
|
|
* @var Container |
|
16
|
|
|
*/ |
|
17
|
|
|
protected $app; |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* Form types that trigger special styling |
|
21
|
|
|
* |
|
22
|
|
|
* @var array |
|
23
|
|
|
*/ |
|
24
|
|
|
protected $availableTypes = array(); |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* The field states available |
|
28
|
|
|
* |
|
29
|
|
|
* @var array |
|
30
|
|
|
*/ |
|
31
|
|
|
protected $states = array(); |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* The default label width (for horizontal forms) |
|
35
|
|
|
* |
|
36
|
|
|
* @var string |
|
37
|
|
|
*/ |
|
38
|
|
|
protected $labelWidth; |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* The default field width (for horizontal forms) |
|
42
|
|
|
* |
|
43
|
|
|
* @var string |
|
44
|
|
|
*/ |
|
45
|
|
|
protected $fieldWidth; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* The default offset for fields (for horizontal form fields |
|
49
|
|
|
* with no label, so usually equal to the default label width) |
|
50
|
|
|
* |
|
51
|
|
|
* @var string |
|
52
|
|
|
*/ |
|
53
|
|
|
protected $fieldOffset; |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* The default HTML tag used for icons |
|
57
|
|
|
* |
|
58
|
|
|
* @var string |
|
59
|
|
|
*/ |
|
60
|
|
|
protected $iconTag; |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* The default set for icon fonts |
|
64
|
|
|
* |
|
65
|
|
|
* @var string |
|
66
|
|
|
*/ |
|
67
|
|
|
protected $iconSet; |
|
68
|
|
|
|
|
69
|
|
|
/** |
|
70
|
|
|
* The default prefix icon names |
|
71
|
|
|
* |
|
72
|
|
|
* @var string |
|
73
|
|
|
*/ |
|
74
|
|
|
protected $iconPrefix; |
|
75
|
|
|
|
|
76
|
|
|
//////////////////////////////////////////////////////////////////// |
|
77
|
|
|
//////////////////////// CURRENT FRAMEWORK ///////////////////////// |
|
78
|
|
|
//////////////////////////////////////////////////////////////////// |
|
79
|
|
|
|
|
80
|
|
|
/** |
|
81
|
|
|
* Get the name of the current framework |
|
82
|
|
|
* |
|
83
|
|
|
* @return string |
|
84
|
|
|
*/ |
|
85
|
|
|
public function current() |
|
86
|
|
|
{ |
|
87
|
|
|
return basename(str_replace('\\', '/', get_class($this))); |
|
88
|
|
|
} |
|
89
|
|
|
|
|
90
|
|
|
/** |
|
91
|
|
|
* Check if the current framework matches something |
|
92
|
|
|
* |
|
93
|
|
|
* @param string $framework |
|
94
|
|
|
* |
|
95
|
|
|
* @return boolean |
|
96
|
|
|
*/ |
|
97
|
|
|
public function is($framework) |
|
98
|
|
|
{ |
|
99
|
|
|
return $framework == $this->current(); |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* Check if the current framework doesn't match something |
|
104
|
|
|
* |
|
105
|
|
|
* @param string $framework |
|
106
|
|
|
* |
|
107
|
|
|
* @return boolean |
|
108
|
|
|
*/ |
|
109
|
|
|
public function isnt($framework) |
|
110
|
|
|
{ |
|
111
|
|
|
return $framework != $this->current(); |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
//////////////////////////////////////////////////////////////////// |
|
115
|
|
|
/////////////////////////// COMMON METHODS ///////////////////////// |
|
116
|
|
|
//////////////////////////////////////////////////////////////////// |
|
117
|
|
|
|
|
118
|
|
|
/** |
|
119
|
|
|
* List form types triggered special styling form current framework |
|
120
|
|
|
* |
|
121
|
|
|
* @return array |
|
122
|
|
|
*/ |
|
123
|
|
|
public function availableTypes() |
|
124
|
|
|
{ |
|
125
|
|
|
return $this->availableTypes; |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
/** |
|
129
|
|
|
* Filter a field state |
|
130
|
|
|
* |
|
131
|
|
|
* @param string $state |
|
132
|
|
|
* |
|
133
|
|
|
* @return string |
|
134
|
|
|
*/ |
|
135
|
|
|
public function filterState($state) |
|
136
|
|
|
{ |
|
137
|
|
|
// Filter out wrong states |
|
138
|
|
|
return in_array($state, $this->states) ? $state : null; |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
/** |
|
142
|
|
|
* Framework error state |
|
143
|
|
|
* |
|
144
|
|
|
* @return string |
|
145
|
|
|
*/ |
|
146
|
|
|
public function errorState() |
|
147
|
|
|
{ |
|
148
|
|
|
return 'error'; |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
/** |
|
152
|
|
|
* Returns corresponding inline class of a field |
|
153
|
|
|
* |
|
154
|
|
|
* @param Field $field |
|
155
|
|
|
* |
|
156
|
|
|
* @return string |
|
157
|
|
|
*/ |
|
158
|
|
|
public function getInlineLabelClass($field) |
|
159
|
|
|
{ |
|
160
|
|
|
return 'inline'; |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
/** |
|
164
|
|
|
* Set framework defaults from its config file |
|
165
|
|
|
*/ |
|
166
|
|
|
protected function setFrameworkDefaults() |
|
167
|
|
|
{ |
|
168
|
|
|
$this->setFieldWidths($this->getFrameworkOption('labelWidths')); |
|
169
|
|
|
$this->setIconDefaults(); |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
/** |
|
173
|
|
|
* @param string $widths |
|
174
|
|
|
*/ |
|
175
|
|
|
protected function setFieldWidths($widths) |
|
176
|
|
|
{ |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* Override framework defaults for icons with config values where set |
|
181
|
|
|
*/ |
|
182
|
|
|
protected function setIconDefaults() |
|
183
|
|
|
{ |
|
184
|
|
|
$this->iconTag = $this->getFrameworkOption('icon.tag'); |
|
185
|
|
|
$this->iconSet = $this->getFrameworkOption('icon.set'); |
|
186
|
|
|
$this->iconPrefix = $this->getFrameworkOption('icon.prefix'); |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
|
|
/** |
|
190
|
|
|
* Render an icon |
|
191
|
|
|
* |
|
192
|
|
|
* @param array $attributes Its general attributes |
|
193
|
|
|
* |
|
194
|
|
|
* @return string |
|
195
|
|
|
*/ |
|
196
|
|
|
public function createIcon($iconType, $attributes = array(), $iconSettings = array()) |
|
197
|
|
|
{ |
|
198
|
|
|
// Check for empty icons |
|
199
|
|
|
if (!$iconType) { |
|
200
|
|
|
return false; |
|
|
|
|
|
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
// icon settings can be overridden for a specific icon |
|
204
|
|
|
$tag = array_get($iconSettings, 'tag', $this->iconTag); |
|
205
|
|
|
$set = array_get($iconSettings, 'set', $this->iconSet); |
|
206
|
|
|
$prefix = array_get($iconSettings, 'prefix', $this->iconPrefix); |
|
207
|
|
|
|
|
208
|
|
|
return Element::create($tag, null, $attributes)->addClass("$set $prefix-$iconType"); |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
//////////////////////////////////////////////////////////////////// |
|
212
|
|
|
///////////////////////////// HELPERS ////////////////////////////// |
|
213
|
|
|
//////////////////////////////////////////////////////////////////// |
|
214
|
|
|
|
|
215
|
|
|
/** |
|
216
|
|
|
* Add classes to a field |
|
217
|
|
|
* |
|
218
|
|
|
* @param Field $field |
|
219
|
|
|
* @param array $classes |
|
220
|
|
|
* |
|
221
|
|
|
* @return \Former\Traits\Field |
|
222
|
|
|
*/ |
|
223
|
|
|
protected function addClassesToField($field, $classes) |
|
224
|
|
|
{ |
|
225
|
|
|
// If we found any class, add them |
|
226
|
|
|
if ($classes) { |
|
|
|
|
|
|
227
|
|
|
$field->addClass(implode(' ', $classes)); |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
return $field; |
|
231
|
|
|
} |
|
232
|
|
|
|
|
233
|
|
|
/** |
|
234
|
|
|
* Prepend an array of classes with a string |
|
235
|
|
|
* |
|
236
|
|
|
* @param array $classes The classes to prepend |
|
237
|
|
|
* @param string $with The string to prepend them with |
|
238
|
|
|
* |
|
239
|
|
|
* @return array A prepended array |
|
240
|
|
|
*/ |
|
241
|
|
|
protected function prependWith($classes, $with) |
|
242
|
|
|
{ |
|
243
|
|
|
return array_map(function ($class) use ($with) { |
|
244
|
|
|
return $with.$class; |
|
245
|
|
|
}, $classes); |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
/** |
|
249
|
|
|
* Create a label for a field |
|
250
|
|
|
* |
|
251
|
|
|
* @param Field $field |
|
252
|
|
|
* @param Element $label The field label if non provided |
|
253
|
|
|
* |
|
254
|
|
|
* @return string A label |
|
255
|
|
|
*/ |
|
256
|
|
|
public function createLabelOf(Field $field, Element $label = null) |
|
257
|
|
|
{ |
|
258
|
|
|
// Get the label and its informations |
|
259
|
|
|
if (!$label) { |
|
260
|
|
|
$label = $field->getLabel(); |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
// Get label "for" |
|
264
|
|
|
$for = $field->id ?: $field->getName(); |
|
|
|
|
|
|
265
|
|
|
|
|
266
|
|
|
// Get label text |
|
267
|
|
|
$text = $label->getValue(); |
|
|
|
|
|
|
268
|
|
|
if (!$text) { |
|
269
|
|
|
return false; |
|
270
|
|
|
} |
|
271
|
|
|
|
|
272
|
|
|
// Append required text |
|
273
|
|
|
if ($field->isRequired()) { |
|
274
|
|
|
$text .= $this->app['former']->getOption('required_text'); |
|
275
|
|
|
} |
|
276
|
|
|
|
|
277
|
|
|
// Render plain label if checkable, else a classic one |
|
278
|
|
|
$label->setValue($text); |
|
279
|
|
|
if (!$field->isCheckable()) { |
|
280
|
|
|
$label->for($for); |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
return $label; |
|
284
|
|
|
} |
|
285
|
|
|
|
|
286
|
|
|
/** |
|
287
|
|
|
* Get an option for the current framework |
|
288
|
|
|
* |
|
289
|
|
|
* @param string $option |
|
290
|
|
|
* |
|
291
|
|
|
* @return string |
|
292
|
|
|
*/ |
|
293
|
|
|
protected function getFrameworkOption($option) |
|
294
|
|
|
{ |
|
295
|
|
|
return $this->app['config']->get("former.{$this->current()}.$option"); |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
|
|
//////////////////////////////////////////////////////////////////// |
|
299
|
|
|
//////////////////////////// WRAP BLOCKS /////////////////////////// |
|
300
|
|
|
//////////////////////////////////////////////////////////////////// |
|
301
|
|
|
|
|
302
|
|
|
/** |
|
303
|
|
|
* Wraps all label contents with potential additional tags. |
|
304
|
|
|
* |
|
305
|
|
|
* @param string $label |
|
306
|
|
|
* |
|
307
|
|
|
* @return string A wrapped label |
|
308
|
|
|
*/ |
|
309
|
|
|
public function wrapLabel($label) |
|
310
|
|
|
{ |
|
311
|
|
|
return $label; |
|
312
|
|
|
} |
|
313
|
|
|
|
|
314
|
|
|
//////////////////////////////////////////////////////////////////// |
|
315
|
|
|
//////////////////////////// RENDER BLOCKS ///////////////////////// |
|
316
|
|
|
//////////////////////////////////////////////////////////////////// |
|
317
|
|
|
|
|
318
|
|
|
/** |
|
319
|
|
|
* Render an validation error text |
|
320
|
|
|
* |
|
321
|
|
|
* @param string $text |
|
322
|
|
|
* @param array $attributes |
|
323
|
|
|
* |
|
324
|
|
|
* @return string |
|
325
|
|
|
*/ |
|
326
|
|
|
public function createValidationError($text, $attributes = array()) |
|
327
|
|
|
{ |
|
328
|
|
|
return $this->createHelp($text, $attributes); |
|
329
|
|
|
} |
|
330
|
|
|
} |
|
331
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.