Completed
Branch scrutinizer-patch-1 (42a7d0)
by Ben
02:17
created
src/Former/LiveValidation.php 1 patch
Indentation   +334 added lines, -334 removed lines patch added patch discarded remove patch
@@ -9,338 +9,338 @@
 block discarded – undo
9 9
  */
10 10
 class LiveValidation
11 11
 {
12
-	/**
13
-	 * The field being worked on
14
-	 *
15
-	 * @var Field
16
-	 */
17
-	public $field;
18
-
19
-	/**
20
-	 * Load a Field instance to apply rules to it
21
-	 *
22
-	 * @param Field $field The field
23
-	 */
24
-	public function __construct(Field&$field)
25
-	{
26
-		$this->field = $field;
27
-	}
28
-
29
-	/**
30
-	 * Apply live validation rules to a field
31
-	 *
32
-	 * @param array $rules The rules to apply
33
-	 */
34
-	public function apply($rules)
35
-	{
36
-		// If no rules to apply, cancel
37
-		if (!$rules) {
38
-			return false;
39
-		}
40
-
41
-		foreach ($rules as $rule => $parameters) {
42
-
43
-			// If the rule is unsupported yet, skip it
44
-			if (!method_exists($this, $rule)) {
45
-				continue;
46
-			}
47
-
48
-			$this->$rule($parameters);
49
-		}
50
-	}
51
-
52
-	////////////////////////////////////////////////////////////////////
53
-	//////////////////////////////// RULES /////////////////////////////
54
-	////////////////////////////////////////////////////////////////////
55
-
56
-	// Field types
57
-	////////////////////////////////////////////////////////////////////
58
-
59
-	/**
60
-	 * Email field
61
-	 */
62
-	public function email()
63
-	{
64
-		$this->field->setType('email');
65
-	}
66
-
67
-	/**
68
-	 * URL field
69
-	 */
70
-	public function url()
71
-	{
72
-		$this->field->setType('url');
73
-	}
74
-
75
-	/**
76
-	 * Required field
77
-	 */
78
-	public function required()
79
-	{
80
-		$this->field->required();
81
-	}
82
-
83
-	// Patterns
84
-	////////////////////////////////////////////////////////////////////
85
-
86
-	/**
87
-	 * Integer field
88
-	 */
89
-	public function integer()
90
-	{
91
-		$this->field->pattern('\d+');
92
-	}
93
-
94
-	/**
95
-	 * Numeric field
96
-	 */
97
-	public function numeric()
98
-	{
99
-		if ($this->field->isOfType('number')) {
100
-			$this->field->step('any');
101
-		} else {
102
-			$this->field->pattern('[+-]?\d*\.?\d+');
103
-		}
104
-	}
105
-
106
-	/**
107
-	 * Not numeric field
108
-	 */
109
-	public function not_numeric()
110
-	{
111
-		$this->field->pattern('\D+');
112
-	}
113
-
114
-	/**
115
-	 * Only alphanumerical
116
-	 */
117
-	public function alpha()
118
-	{
119
-		$this->field->pattern('[a-zA-Z]+');
120
-	}
121
-
122
-	/**
123
-	 * Only alphanumerical and numbers
124
-	 */
125
-	public function alpha_num()
126
-	{
127
-		$this->field->pattern('[a-zA-Z0-9]+');
128
-	}
129
-
130
-	/**
131
-	 * Alphanumerical, numbers and dashes
132
-	 */
133
-	public function alpha_dash()
134
-	{
135
-		$this->field->pattern('[a-zA-Z0-9_\-]+');
136
-	}
137
-
138
-	/**
139
-	 * In []
140
-	 */
141
-	public function in($possible)
142
-	{
143
-		// Create the corresponding regex
144
-		$possible = (sizeof($possible) == 1) ? $possible[0] : '('.join('|', $possible).')';
145
-
146
-		$this->field->pattern('^'.$possible.'$');
147
-	}
148
-
149
-	/**
150
-	 * Not in []
151
-	 */
152
-	public function not_in($impossible)
153
-	{
154
-		$this->field->pattern('(?:(?!^'.join('$|^', $impossible).'$).)*');
155
-	}
156
-
157
-	/**
158
-	 * Matches a pattern
159
-	 */
160
-	public function match($pattern)
161
-	{
162
-		// Remove delimiters from existing regex
163
-		$pattern = substr($pattern[0], 1, -1);
164
-
165
-		$this->field->pattern($pattern);
166
-	}
167
-
168
-	/**
169
-	 * Alias for match
170
-	 */
171
-	public function regex($pattern)
172
-	{
173
-		return $this->match($pattern);
174
-	}
175
-
176
-	// Boundaries
177
-	////////////////////////////////////////////////////////////////////
178
-
179
-	/**
180
-	 * Max value
181
-	 */
182
-	public function max($max)
183
-	{
184
-		if ($this->field->isOfType('file')) {
185
-			$this->size($max);
186
-		} else {
187
-			$this->setMax($max[0]);
188
-		}
189
-	}
190
-
191
-	/**
192
-	 * Max size
193
-	 */
194
-	public function size($size)
195
-	{
196
-		$this->field->max($size[0]);
197
-	}
198
-
199
-	/**
200
-	 * Min value
201
-	 */
202
-	public function min($min)
203
-	{
204
-		$this->setMin($min[0]);
205
-	}
206
-
207
-	/**
208
-	 * Set boundaries
209
-	 */
210
-	public function between($between)
211
-	{
212
-		list($min, $max) = $between;
213
-
214
-		$this->setBetween($min, $max);
215
-	}
216
-
217
-	/**
218
-	 * Set accepted mime types
219
-	 *
220
-	 * @param string[] $mimes
221
-	 */
222
-	public function mimes($mimes)
223
-	{
224
-		// Only useful on file fields
225
-		if (!$this->field->isOfType('file')) {
226
-			return false;
227
-		}
228
-
229
-		$this->field->accept($this->setAccepted($mimes));
230
-	}
231
-
232
-	/**
233
-	 * Set accept only images
234
-	 */
235
-	public function image()
236
-	{
237
-		$this->mimes(array('jpg', 'png', 'gif', 'bmp'));
238
-	}
239
-
240
-	// Dates
241
-	////////////////////////////////////////////////////////////////////
242
-
243
-	/**
244
-	 * Before a date
245
-	 */
246
-	public function before($date)
247
-	{
248
-		list($format, $date) = $this->formatDate($date[0]);
249
-
250
-		$this->field->max(date($format, $date));
251
-	}
252
-
253
-	/**
254
-	 * After a date
255
-	 */
256
-	public function after($date)
257
-	{
258
-		list($format, $date) = $this->formatDate($date[0]);
259
-
260
-		$this->field->min(date($format, $date));
261
-	}
262
-
263
-	////////////////////////////////////////////////////////////////////
264
-	////////////////////////////// HELPERS /////////////////////////////
265
-	////////////////////////////////////////////////////////////////////
266
-
267
-	/**
268
-	 * Transform extensions and mime groups into a list of mime types
269
-	 *
270
-	 * @param  string[] $mimes An array of mimes
271
-	 *
272
-	 * @return string A concatenated list of mimes
273
-	 */
274
-	private function setAccepted($mimes)
275
-	{
276
-		// Transform extensions or mime groups into mime types
277
-		$mimes = array_map(array('\Laravel\File', 'mime'), $mimes);
278
-
279
-		return implode(',', $mimes);
280
-	}
281
-
282
-	/**
283
-	 * Format a date to a pattern
284
-	 *
285
-	 * @param  string $date The date
286
-	 *
287
-	 * @return string The pattern
288
-	 */
289
-	private function formatDate($date)
290
-	{
291
-		$format = 'Y-m-d';
292
-
293
-		// Add hour for datetime fields
294
-		if ($this->field->isOfType('datetime', 'datetime-local')) {
295
-			$format .= '\TH:i:s';
296
-		}
297
-
298
-		return array($format, strtotime($date));
299
-	}
300
-
301
-	/**
302
-	 * Set a maximum value to a field
303
-	 *
304
-	 * @param integer $max
305
-	 */
306
-	private function setMax($max)
307
-	{
308
-		$attribute = $this->field->isOfType('number') ? 'max' : 'maxlength';
309
-
310
-		$this->field->$attribute($max);
311
-	}
312
-
313
-	/**
314
-	 * Set a minimum value to a field
315
-	 *
316
-	 * @param integer $min
317
-	 */
318
-	private function setMin($min)
319
-	{
320
-		if ($this->field->isOfType('number') == 'min') {
321
-			$this->field->min($min);
322
-		} else {
323
-			$this->field->pattern(".{".$min.",}");
324
-		}
325
-	}
326
-
327
-	/**
328
-	 * Set a minimum and maximum value to a field
329
-	 *
330
-	 * @param $min
331
-	 * @param $max
332
-	 */
333
-	public function setBetween($min, $max)
334
-	{
335
-		if ($this->field->isOfType('number') == 'min') {
336
-			// min, max values for generation of the pattern
337
-			$this->field->min($min);
338
-			$this->field->max($max);
339
-		} else {
340
-			$this->field->pattern('.{'.$min.','.$max.'}');
341
-
342
-			// still let the browser limit text input after reaching the max
343
-			$this->field->maxlength($max);
344
-		}
345
-	}
12
+    /**
13
+     * The field being worked on
14
+     *
15
+     * @var Field
16
+     */
17
+    public $field;
18
+
19
+    /**
20
+     * Load a Field instance to apply rules to it
21
+     *
22
+     * @param Field $field The field
23
+     */
24
+    public function __construct(Field&$field)
25
+    {
26
+        $this->field = $field;
27
+    }
28
+
29
+    /**
30
+     * Apply live validation rules to a field
31
+     *
32
+     * @param array $rules The rules to apply
33
+     */
34
+    public function apply($rules)
35
+    {
36
+        // If no rules to apply, cancel
37
+        if (!$rules) {
38
+            return false;
39
+        }
40
+
41
+        foreach ($rules as $rule => $parameters) {
42
+
43
+            // If the rule is unsupported yet, skip it
44
+            if (!method_exists($this, $rule)) {
45
+                continue;
46
+            }
47
+
48
+            $this->$rule($parameters);
49
+        }
50
+    }
51
+
52
+    ////////////////////////////////////////////////////////////////////
53
+    //////////////////////////////// RULES /////////////////////////////
54
+    ////////////////////////////////////////////////////////////////////
55
+
56
+    // Field types
57
+    ////////////////////////////////////////////////////////////////////
58
+
59
+    /**
60
+     * Email field
61
+     */
62
+    public function email()
63
+    {
64
+        $this->field->setType('email');
65
+    }
66
+
67
+    /**
68
+     * URL field
69
+     */
70
+    public function url()
71
+    {
72
+        $this->field->setType('url');
73
+    }
74
+
75
+    /**
76
+     * Required field
77
+     */
78
+    public function required()
79
+    {
80
+        $this->field->required();
81
+    }
82
+
83
+    // Patterns
84
+    ////////////////////////////////////////////////////////////////////
85
+
86
+    /**
87
+     * Integer field
88
+     */
89
+    public function integer()
90
+    {
91
+        $this->field->pattern('\d+');
92
+    }
93
+
94
+    /**
95
+     * Numeric field
96
+     */
97
+    public function numeric()
98
+    {
99
+        if ($this->field->isOfType('number')) {
100
+            $this->field->step('any');
101
+        } else {
102
+            $this->field->pattern('[+-]?\d*\.?\d+');
103
+        }
104
+    }
105
+
106
+    /**
107
+     * Not numeric field
108
+     */
109
+    public function not_numeric()
110
+    {
111
+        $this->field->pattern('\D+');
112
+    }
113
+
114
+    /**
115
+     * Only alphanumerical
116
+     */
117
+    public function alpha()
118
+    {
119
+        $this->field->pattern('[a-zA-Z]+');
120
+    }
121
+
122
+    /**
123
+     * Only alphanumerical and numbers
124
+     */
125
+    public function alpha_num()
126
+    {
127
+        $this->field->pattern('[a-zA-Z0-9]+');
128
+    }
129
+
130
+    /**
131
+     * Alphanumerical, numbers and dashes
132
+     */
133
+    public function alpha_dash()
134
+    {
135
+        $this->field->pattern('[a-zA-Z0-9_\-]+');
136
+    }
137
+
138
+    /**
139
+     * In []
140
+     */
141
+    public function in($possible)
142
+    {
143
+        // Create the corresponding regex
144
+        $possible = (sizeof($possible) == 1) ? $possible[0] : '('.join('|', $possible).')';
145
+
146
+        $this->field->pattern('^'.$possible.'$');
147
+    }
148
+
149
+    /**
150
+     * Not in []
151
+     */
152
+    public function not_in($impossible)
153
+    {
154
+        $this->field->pattern('(?:(?!^'.join('$|^', $impossible).'$).)*');
155
+    }
156
+
157
+    /**
158
+     * Matches a pattern
159
+     */
160
+    public function match($pattern)
161
+    {
162
+        // Remove delimiters from existing regex
163
+        $pattern = substr($pattern[0], 1, -1);
164
+
165
+        $this->field->pattern($pattern);
166
+    }
167
+
168
+    /**
169
+     * Alias for match
170
+     */
171
+    public function regex($pattern)
172
+    {
173
+        return $this->match($pattern);
174
+    }
175
+
176
+    // Boundaries
177
+    ////////////////////////////////////////////////////////////////////
178
+
179
+    /**
180
+     * Max value
181
+     */
182
+    public function max($max)
183
+    {
184
+        if ($this->field->isOfType('file')) {
185
+            $this->size($max);
186
+        } else {
187
+            $this->setMax($max[0]);
188
+        }
189
+    }
190
+
191
+    /**
192
+     * Max size
193
+     */
194
+    public function size($size)
195
+    {
196
+        $this->field->max($size[0]);
197
+    }
198
+
199
+    /**
200
+     * Min value
201
+     */
202
+    public function min($min)
203
+    {
204
+        $this->setMin($min[0]);
205
+    }
206
+
207
+    /**
208
+     * Set boundaries
209
+     */
210
+    public function between($between)
211
+    {
212
+        list($min, $max) = $between;
213
+
214
+        $this->setBetween($min, $max);
215
+    }
216
+
217
+    /**
218
+     * Set accepted mime types
219
+     *
220
+     * @param string[] $mimes
221
+     */
222
+    public function mimes($mimes)
223
+    {
224
+        // Only useful on file fields
225
+        if (!$this->field->isOfType('file')) {
226
+            return false;
227
+        }
228
+
229
+        $this->field->accept($this->setAccepted($mimes));
230
+    }
231
+
232
+    /**
233
+     * Set accept only images
234
+     */
235
+    public function image()
236
+    {
237
+        $this->mimes(array('jpg', 'png', 'gif', 'bmp'));
238
+    }
239
+
240
+    // Dates
241
+    ////////////////////////////////////////////////////////////////////
242
+
243
+    /**
244
+     * Before a date
245
+     */
246
+    public function before($date)
247
+    {
248
+        list($format, $date) = $this->formatDate($date[0]);
249
+
250
+        $this->field->max(date($format, $date));
251
+    }
252
+
253
+    /**
254
+     * After a date
255
+     */
256
+    public function after($date)
257
+    {
258
+        list($format, $date) = $this->formatDate($date[0]);
259
+
260
+        $this->field->min(date($format, $date));
261
+    }
262
+
263
+    ////////////////////////////////////////////////////////////////////
264
+    ////////////////////////////// HELPERS /////////////////////////////
265
+    ////////////////////////////////////////////////////////////////////
266
+
267
+    /**
268
+     * Transform extensions and mime groups into a list of mime types
269
+     *
270
+     * @param  string[] $mimes An array of mimes
271
+     *
272
+     * @return string A concatenated list of mimes
273
+     */
274
+    private function setAccepted($mimes)
275
+    {
276
+        // Transform extensions or mime groups into mime types
277
+        $mimes = array_map(array('\Laravel\File', 'mime'), $mimes);
278
+
279
+        return implode(',', $mimes);
280
+    }
281
+
282
+    /**
283
+     * Format a date to a pattern
284
+     *
285
+     * @param  string $date The date
286
+     *
287
+     * @return string The pattern
288
+     */
289
+    private function formatDate($date)
290
+    {
291
+        $format = 'Y-m-d';
292
+
293
+        // Add hour for datetime fields
294
+        if ($this->field->isOfType('datetime', 'datetime-local')) {
295
+            $format .= '\TH:i:s';
296
+        }
297
+
298
+        return array($format, strtotime($date));
299
+    }
300
+
301
+    /**
302
+     * Set a maximum value to a field
303
+     *
304
+     * @param integer $max
305
+     */
306
+    private function setMax($max)
307
+    {
308
+        $attribute = $this->field->isOfType('number') ? 'max' : 'maxlength';
309
+
310
+        $this->field->$attribute($max);
311
+    }
312
+
313
+    /**
314
+     * Set a minimum value to a field
315
+     *
316
+     * @param integer $min
317
+     */
318
+    private function setMin($min)
319
+    {
320
+        if ($this->field->isOfType('number') == 'min') {
321
+            $this->field->min($min);
322
+        } else {
323
+            $this->field->pattern(".{".$min.",}");
324
+        }
325
+    }
326
+
327
+    /**
328
+     * Set a minimum and maximum value to a field
329
+     *
330
+     * @param $min
331
+     * @param $max
332
+     */
333
+    public function setBetween($min, $max)
334
+    {
335
+        if ($this->field->isOfType('number') == 'min') {
336
+            // min, max values for generation of the pattern
337
+            $this->field->min($min);
338
+            $this->field->max($max);
339
+        } else {
340
+            $this->field->pattern('.{'.$min.','.$max.'}');
341
+
342
+            // still let the browser limit text input after reaching the max
343
+            $this->field->maxlength($max);
344
+        }
345
+    }
346 346
 }
Please login to merge, or discard this patch.
src/Former/Exceptions/InvalidFrameworkException.php 1 patch
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -2,33 +2,33 @@
 block discarded – undo
2 2
 
3 3
 class InvalidFrameworkException extends \RuntimeException {
4 4
 
5
-	/**
6
-	 * reference to framework class
7
-	 *
8
-	 * @var
9
-	 */
10
-	private $framework;
5
+    /**
6
+     * reference to framework class
7
+     *
8
+     * @var
9
+     */
10
+    private $framework;
11 11
 
12
-	/**
13
-	 * Set framework
14
-	 *
15
-	 * @param string $framework
16
-	 * @return $this
17
-	 */
18
-	public function setFramework($framework)
19
-	{
20
-		$this->framework = $framework;
21
-		$this->message = "Framework was not found [{$this->framework}]";
12
+    /**
13
+     * Set framework
14
+     *
15
+     * @param string $framework
16
+     * @return $this
17
+     */
18
+    public function setFramework($framework)
19
+    {
20
+        $this->framework = $framework;
21
+        $this->message = "Framework was not found [{$this->framework}]";
22 22
 
23
-		return $this;
24
-	}
25
-	/**
26
-	 * Gets the errors object.
27
-	 *
28
-	 * @return string
29
-	 */
30
-	public function getFramework()
31
-	{
32
-		return $this->framework;
33
-	}
23
+        return $this;
24
+    }
25
+    /**
26
+     * Gets the errors object.
27
+     *
28
+     * @return string
29
+     */
30
+    public function getFramework()
31
+    {
32
+        return $this->framework;
33
+    }
34 34
 }
Please login to merge, or discard this patch.
src/Former/Traits/Field.php 1 patch
Indentation   +431 added lines, -431 removed lines patch added patch discarded remove patch
@@ -16,435 +16,435 @@
 block discarded – undo
16 16
  */
17 17
 abstract class Field extends FormerObject implements FieldInterface
18 18
 {
19
-	/**
20
-	 * The IoC Container
21
-	 *
22
-	 * @var Container
23
-	 */
24
-	protected $app;
25
-
26
-	/**
27
-	 * The Form instance
28
-	 *
29
-	 * @var Former\Form
30
-	 */
31
-	protected $form;
32
-
33
-	/**
34
-	 * A label for the field (if not using Bootstrap)
35
-	 *
36
-	 * @var string
37
-	 */
38
-	protected $label;
39
-
40
-	/**
41
-	 * The field's group
42
-	 *
43
-	 * @var Group
44
-	 */
45
-	protected $group;
46
-
47
-	/**
48
-	 * The field's default element
49
-	 *
50
-	 * @var string
51
-	 */
52
-	protected $element = 'input';
53
-
54
-	/**
55
-	 * Whether the Field is self-closing or not
56
-	 *
57
-	 * @var boolean
58
-	 */
59
-	protected $isSelfClosing = true;
60
-
61
-	/**
62
-	 * The field's bind destination
63
-	 *
64
-	 * @var string
65
-	 */
66
-	protected $bind;
67
-
68
-	/**
69
-	 * Get the current framework instance
70
-	 *
71
-	 * @return Framework
72
-	 */
73
-	protected function currentFramework()
74
-	{
75
-		if ($this->app->bound('former.form.framework')) {
76
-			return $this->app['former.form.framework'];
77
-		}
78
-
79
-		return $this->app['former.framework'];
80
-	}
81
-
82
-	////////////////////////////////////////////////////////////////////
83
-	///////////////////////////// INTERFACE ////////////////////////////
84
-	////////////////////////////////////////////////////////////////////
85
-
86
-	/**
87
-	 * Set up a Field instance
88
-	 *
89
-	 * @param string $type A field type
90
-	 */
91
-	public function __construct(Container $app, $type, $name, $label, $value, $attributes)
92
-	{
93
-		// Set base parameters
94
-		$this->app   = $app;
95
-		$this->type  = $type;
96
-		$this->value = $value;
97
-		$this->setAttributes($attributes);
98
-		$this->form = $this->app->bound('former.form') ? $this->app['former.form'] : null;
99
-
100
-		// Compute and translate label
101
-		$this->automaticLabels($name, $label);
102
-
103
-		// Repopulate field
104
-		if ($type != 'password' && $name !== '_token') {
105
-			$this->value = $this->repopulate();
106
-		}
107
-
108
-		// Apply Live validation rules
109
-		if ($this->app['former']->getOption('live_validation')) {
110
-			$rules = new LiveValidation($this);
111
-			$rules->apply($this->getRules());
112
-		}
113
-
114
-		// Bind the Group class
115
-		$groupClass = $this->isCheckable() ? 'CheckableGroup' : 'Group';
116
-		$groupClass = Former::FORMSPACE.$groupClass;
117
-
118
-		$this->group = new $groupClass($this->app, $this->label);
119
-	}
120
-
121
-	/**
122
-	 * Redirect calls to the group if necessary
123
-	 *
124
-	 * @param string $method
125
-	 */
126
-	public function __call($method, $parameters)
127
-	{
128
-		// Translate attributes
129
-		$translatable = $this->app['former']->getOption('translatable', array());
130
-		if (in_array($method, $translatable) and isset($parameters[0])) {
131
-			$parameters[0] = Helpers::translate($parameters[0]);
132
-		}
133
-
134
-		// Redirect calls to the Control Group
135
-		if (method_exists($this->group, $method) or Str::startsWith($method, 'onGroup')) {
136
-			$method = str_replace('onGroup', '', $method);
137
-			$method = lcfirst($method);
138
-
139
-			call_user_func_array(array($this->group, $method), $parameters);
140
-
141
-			return $this;
142
-		}
143
-
144
-		return parent::__call($method, $parameters);
145
-	}
146
-
147
-	/**
148
-	 * Prints out the field, wrapped in its group
149
-	 *
150
-	 * @return string
151
-	 */
152
-	public function wrapAndRender()
153
-	{
154
-		// Dry syntax (hidden fields, plain fields)
155
-		if ($this->isUnwrappable()) {
156
-			$html = $this->render();
157
-			// Control group syntax
158
-		} elseif (Form::hasInstanceOpened()) {
159
-			$html = $this->group->wrapField($this);
160
-			// Classic syntax
161
-		} else {
162
-			$html = $this->currentFramework()->createLabelOf($this);
163
-			$html .= $this->render();
164
-		}
165
-
166
-		return $html;
167
-	}
168
-
169
-	/**
170
-	 * Prints out the field
171
-	 *
172
-	 * @return string
173
-	 */
174
-	public function __toString()
175
-	{
176
-		return $this->wrapAndRender();
177
-	}
178
-
179
-	////////////////////////////////////////////////////////////////////
180
-	////////////////////////// PUBLIC INTERFACE ////////////////////////
181
-	////////////////////////////////////////////////////////////////////
182
-
183
-	/**
184
-	 * Whether the current field is required or not
185
-	 *
186
-	 * @return boolean
187
-	 */
188
-	public function isRequired()
189
-	{
190
-		return isset($this->attributes['required']);
191
-	}
192
-
193
-	/**
194
-	 * Check if a field is unwrappable (no label)
195
-	 *
196
-	 * @return boolean
197
-	 */
198
-	public function isUnwrappable()
199
-	{
200
-		return
201
-			($this->form and $this->currentFramework()->is('Nude')) or
202
-			($this->form and $this->isOfType('inline')) or
203
-			$this->isButton() or
204
-			$this->isOfType('hidden') or
205
-			\Former\Form\Group::$opened or
206
-			$this->group and $this->group->isRaw();
207
-	}
208
-
209
-	/**
210
-	 * Check if field is a checkbox or a radio
211
-	 *
212
-	 * @return boolean
213
-	 */
214
-	public function isCheckable()
215
-	{
216
-		return $this->isOfType('checkbox', 'checkboxes', 'radio', 'radios');
217
-	}
218
-
219
-	/**
220
-	 * Check if the field is a button
221
-	 *
222
-	 * @return boolean
223
-	 */
224
-	public function isButton()
225
-	{
226
-		return false;
227
-	}
228
-
229
-	/**
230
-	 * Get the rules applied to the current field
231
-	 *
232
-	 * @return array An array of rules
233
-	 */
234
-	public function getRules()
235
-	{
236
-		return $this->app['former']->getRules($this->name);
237
-	}
238
-
239
-	////////////////////////////////////////////////////////////////////
240
-	//////////////////////// SETTERS AND GETTERS ///////////////////////
241
-	////////////////////////////////////////////////////////////////////
242
-
243
-	/**
244
-	 * Apply a Live Validation rule by chaining
245
-	 *
246
-	 * @param string $rule The rule
247
-	 */
248
-	public function rule($rule)
249
-	{
250
-		$parameters = func_get_args();
251
-		array_shift($parameters);
252
-
253
-		$live = new LiveValidation($this);
254
-		$live->apply(array(
255
-			$rule => $parameters,
256
-		));
257
-
258
-		return $this;
259
-	}
260
-
261
-	/**
262
-	 * Apply multiple rules passed as a string.
263
-	 *
264
-	 * @param $rules
265
-	 * @return $this
266
-	 */
267
-	public function rules($rules)
268
-	{
269
-		if (!is_array($rules)) {
270
-			$rules = explode('|', $rules);
271
-		}
272
-
273
-		foreach ($rules as $rule) {
274
-			$parameters = null;
275
-
276
-			// If we have a rule with a value
277
-			if (($colon = strpos($rule, ':')) !== false) {
278
-				$rulename = substr($rule, 0, $colon) ;
279
-
280
-				/**
281
-				 * Regular expressions may contain commas and should not be divided by str_getcsv.
282
-				 * For regular expressions we are just using the complete expression as a parameter.
283
-				 */
284
-				if ($rulename !== 'regex') {
285
-					$parameters = str_getcsv(substr($rule, $colon + 1));
286
-				} else {
287
-					$parameters = [substr($rule, $colon + 1)];
288
-				}
289
-			}
290
-
291
-			// Exclude unsupported rules
292
-			$rule = is_numeric($colon) ? substr($rule, 0, $colon) : $rule;
293
-
294
-			// Store processed rule in Former's array
295
-			if (!isset($parameters)) {
296
-				$parameters = array();
297
-			}
298
-
299
-			call_user_func_array([$this, 'rule'], array_merge([$rule], $parameters));
300
-		}
301
-
302
-		return $this;
303
-	}
304
-
305
-	/**
306
-	 * Adds a label to the group/field
307
-	 *
308
-	 * @param  string $text       A label
309
-	 * @param  array  $attributes The label's attributes
310
-	 *
311
-	 * @return Field              A field
312
-	 */
313
-	public function label($text, $attributes = array())
314
-	{
315
-		// Create the Label element
316
-		$for   = $this->id ?: $this->name;
317
-		$label = $this->app['former']->label($text, $for, $attributes);
318
-
319
-		// Set label
320
-		$this->label = $label;
321
-		if ($this->group) {
322
-			$this->group->setLabel($label);
323
-		}
324
-
325
-		return $this;
326
-	}
327
-
328
-	/**
329
-	 * Set the Field value no matter what
330
-	 *
331
-	 * @param string $value A new value
332
-	 */
333
-	public function forceValue($value)
334
-	{
335
-		$this->value = $value;
336
-
337
-		return $this;
338
-	}
339
-
340
-	/**
341
-	 * Classic setting of attribute, won't overwrite any populate() attempt
342
-	 *
343
-	 * @param  string $value A new value
344
-	 */
345
-	public function value($value)
346
-	{
347
-		// Check if we already have a value stored for this field or in POST data
348
-		$already = $this->repopulate();
349
-
350
-		if (!$already) {
351
-			$this->value = $value;
352
-		}
353
-
354
-		return $this;
355
-	}
356
-
357
-	/**
358
-	 * Change the field's name
359
-	 *
360
-	 * @param  string $name The new name
361
-	 */
362
-	public function name($name)
363
-	{
364
-		$this->name = $name;
365
-
366
-		// Also relink the label to the new name
367
-		$this->label($name);
368
-
369
-		return $this;
370
-	}
371
-
372
-	/**
373
-	 * Get the field's labels
374
-	 *
375
-	 * @return string
376
-	 */
377
-	public function getLabel()
378
-	{
379
-		return $this->label;
380
-	}
381
-
382
-	/**
383
-	 * Change the field's bind destination
384
-	 *
385
-	 * @param $destination
386
-	 */
387
-	public function bind($destination) {
388
-		$this->bind = $destination;
389
-		if ($this->type != 'password') {
390
-			$this->value = $this->repopulate();
391
-		}
392
-
393
-		return $this;
394
-	}
395
-
396
-	////////////////////////////////////////////////////////////////////
397
-	//////////////////////////////// HELPERS ///////////////////////////
398
-	////////////////////////////////////////////////////////////////////
399
-
400
-	/**
401
-	 * Use values stored in Former to populate the current field
402
-	 */
403
-	private function repopulate($fallback = null)
404
-	{
405
-		// Get values from POST, populated, and manually set value
406
-		$post      = $this->app['former']->getPost($this->name);
407
-		$populator = $this->form ? $this->form->getPopulator() : $this->app['former.populator'];
408
-		$populate  = $populator->get($this->bind ?: $this->name);
409
-
410
-		// Assign a priority to each
411
-		if (!is_null($post)) {
412
-			return $post;
413
-		}
414
-		if (!is_null($populate)) {
415
-			return $populate;
416
-		}
417
-
418
-		return $fallback ?: $this->value;
419
-	}
420
-
421
-	/**
422
-	 * Ponders a label and a field name, and tries to get the best out of it
423
-	 *
424
-	 * @param  string $label A label
425
-	 * @param  string $name  A field name
426
-	 *
427
-	 * @return false|null         A label and a field name
428
-	 */
429
-	private function automaticLabels($name, $label)
430
-	{
431
-		// Disabled automatic labels
432
-		if (!$this->app['former']->getOption('automatic_label')) {
433
-			$this->name = $name;
434
-			$this->label($label);
435
-
436
-			return false;
437
-		}
438
-
439
-		// Check for the two possibilities
440
-		if ($label and is_null($name)) {
441
-			$name = Str::slug($label);
442
-		} elseif (is_null($label) and $name) {
443
-			$label = preg_replace('/\[\]$/', '', $name);
444
-		}
445
-
446
-		// Save values
447
-		$this->name = $name;
448
-		$this->label($label);
449
-	}
19
+    /**
20
+     * The IoC Container
21
+     *
22
+     * @var Container
23
+     */
24
+    protected $app;
25
+
26
+    /**
27
+     * The Form instance
28
+     *
29
+     * @var Former\Form
30
+     */
31
+    protected $form;
32
+
33
+    /**
34
+     * A label for the field (if not using Bootstrap)
35
+     *
36
+     * @var string
37
+     */
38
+    protected $label;
39
+
40
+    /**
41
+     * The field's group
42
+     *
43
+     * @var Group
44
+     */
45
+    protected $group;
46
+
47
+    /**
48
+     * The field's default element
49
+     *
50
+     * @var string
51
+     */
52
+    protected $element = 'input';
53
+
54
+    /**
55
+     * Whether the Field is self-closing or not
56
+     *
57
+     * @var boolean
58
+     */
59
+    protected $isSelfClosing = true;
60
+
61
+    /**
62
+     * The field's bind destination
63
+     *
64
+     * @var string
65
+     */
66
+    protected $bind;
67
+
68
+    /**
69
+     * Get the current framework instance
70
+     *
71
+     * @return Framework
72
+     */
73
+    protected function currentFramework()
74
+    {
75
+        if ($this->app->bound('former.form.framework')) {
76
+            return $this->app['former.form.framework'];
77
+        }
78
+
79
+        return $this->app['former.framework'];
80
+    }
81
+
82
+    ////////////////////////////////////////////////////////////////////
83
+    ///////////////////////////// INTERFACE ////////////////////////////
84
+    ////////////////////////////////////////////////////////////////////
85
+
86
+    /**
87
+     * Set up a Field instance
88
+     *
89
+     * @param string $type A field type
90
+     */
91
+    public function __construct(Container $app, $type, $name, $label, $value, $attributes)
92
+    {
93
+        // Set base parameters
94
+        $this->app   = $app;
95
+        $this->type  = $type;
96
+        $this->value = $value;
97
+        $this->setAttributes($attributes);
98
+        $this->form = $this->app->bound('former.form') ? $this->app['former.form'] : null;
99
+
100
+        // Compute and translate label
101
+        $this->automaticLabels($name, $label);
102
+
103
+        // Repopulate field
104
+        if ($type != 'password' && $name !== '_token') {
105
+            $this->value = $this->repopulate();
106
+        }
107
+
108
+        // Apply Live validation rules
109
+        if ($this->app['former']->getOption('live_validation')) {
110
+            $rules = new LiveValidation($this);
111
+            $rules->apply($this->getRules());
112
+        }
113
+
114
+        // Bind the Group class
115
+        $groupClass = $this->isCheckable() ? 'CheckableGroup' : 'Group';
116
+        $groupClass = Former::FORMSPACE.$groupClass;
117
+
118
+        $this->group = new $groupClass($this->app, $this->label);
119
+    }
120
+
121
+    /**
122
+     * Redirect calls to the group if necessary
123
+     *
124
+     * @param string $method
125
+     */
126
+    public function __call($method, $parameters)
127
+    {
128
+        // Translate attributes
129
+        $translatable = $this->app['former']->getOption('translatable', array());
130
+        if (in_array($method, $translatable) and isset($parameters[0])) {
131
+            $parameters[0] = Helpers::translate($parameters[0]);
132
+        }
133
+
134
+        // Redirect calls to the Control Group
135
+        if (method_exists($this->group, $method) or Str::startsWith($method, 'onGroup')) {
136
+            $method = str_replace('onGroup', '', $method);
137
+            $method = lcfirst($method);
138
+
139
+            call_user_func_array(array($this->group, $method), $parameters);
140
+
141
+            return $this;
142
+        }
143
+
144
+        return parent::__call($method, $parameters);
145
+    }
146
+
147
+    /**
148
+     * Prints out the field, wrapped in its group
149
+     *
150
+     * @return string
151
+     */
152
+    public function wrapAndRender()
153
+    {
154
+        // Dry syntax (hidden fields, plain fields)
155
+        if ($this->isUnwrappable()) {
156
+            $html = $this->render();
157
+            // Control group syntax
158
+        } elseif (Form::hasInstanceOpened()) {
159
+            $html = $this->group->wrapField($this);
160
+            // Classic syntax
161
+        } else {
162
+            $html = $this->currentFramework()->createLabelOf($this);
163
+            $html .= $this->render();
164
+        }
165
+
166
+        return $html;
167
+    }
168
+
169
+    /**
170
+     * Prints out the field
171
+     *
172
+     * @return string
173
+     */
174
+    public function __toString()
175
+    {
176
+        return $this->wrapAndRender();
177
+    }
178
+
179
+    ////////////////////////////////////////////////////////////////////
180
+    ////////////////////////// PUBLIC INTERFACE ////////////////////////
181
+    ////////////////////////////////////////////////////////////////////
182
+
183
+    /**
184
+     * Whether the current field is required or not
185
+     *
186
+     * @return boolean
187
+     */
188
+    public function isRequired()
189
+    {
190
+        return isset($this->attributes['required']);
191
+    }
192
+
193
+    /**
194
+     * Check if a field is unwrappable (no label)
195
+     *
196
+     * @return boolean
197
+     */
198
+    public function isUnwrappable()
199
+    {
200
+        return
201
+            ($this->form and $this->currentFramework()->is('Nude')) or
202
+            ($this->form and $this->isOfType('inline')) or
203
+            $this->isButton() or
204
+            $this->isOfType('hidden') or
205
+            \Former\Form\Group::$opened or
206
+            $this->group and $this->group->isRaw();
207
+    }
208
+
209
+    /**
210
+     * Check if field is a checkbox or a radio
211
+     *
212
+     * @return boolean
213
+     */
214
+    public function isCheckable()
215
+    {
216
+        return $this->isOfType('checkbox', 'checkboxes', 'radio', 'radios');
217
+    }
218
+
219
+    /**
220
+     * Check if the field is a button
221
+     *
222
+     * @return boolean
223
+     */
224
+    public function isButton()
225
+    {
226
+        return false;
227
+    }
228
+
229
+    /**
230
+     * Get the rules applied to the current field
231
+     *
232
+     * @return array An array of rules
233
+     */
234
+    public function getRules()
235
+    {
236
+        return $this->app['former']->getRules($this->name);
237
+    }
238
+
239
+    ////////////////////////////////////////////////////////////////////
240
+    //////////////////////// SETTERS AND GETTERS ///////////////////////
241
+    ////////////////////////////////////////////////////////////////////
242
+
243
+    /**
244
+     * Apply a Live Validation rule by chaining
245
+     *
246
+     * @param string $rule The rule
247
+     */
248
+    public function rule($rule)
249
+    {
250
+        $parameters = func_get_args();
251
+        array_shift($parameters);
252
+
253
+        $live = new LiveValidation($this);
254
+        $live->apply(array(
255
+            $rule => $parameters,
256
+        ));
257
+
258
+        return $this;
259
+    }
260
+
261
+    /**
262
+     * Apply multiple rules passed as a string.
263
+     *
264
+     * @param $rules
265
+     * @return $this
266
+     */
267
+    public function rules($rules)
268
+    {
269
+        if (!is_array($rules)) {
270
+            $rules = explode('|', $rules);
271
+        }
272
+
273
+        foreach ($rules as $rule) {
274
+            $parameters = null;
275
+
276
+            // If we have a rule with a value
277
+            if (($colon = strpos($rule, ':')) !== false) {
278
+                $rulename = substr($rule, 0, $colon) ;
279
+
280
+                /**
281
+                 * Regular expressions may contain commas and should not be divided by str_getcsv.
282
+                 * For regular expressions we are just using the complete expression as a parameter.
283
+                 */
284
+                if ($rulename !== 'regex') {
285
+                    $parameters = str_getcsv(substr($rule, $colon + 1));
286
+                } else {
287
+                    $parameters = [substr($rule, $colon + 1)];
288
+                }
289
+            }
290
+
291
+            // Exclude unsupported rules
292
+            $rule = is_numeric($colon) ? substr($rule, 0, $colon) : $rule;
293
+
294
+            // Store processed rule in Former's array
295
+            if (!isset($parameters)) {
296
+                $parameters = array();
297
+            }
298
+
299
+            call_user_func_array([$this, 'rule'], array_merge([$rule], $parameters));
300
+        }
301
+
302
+        return $this;
303
+    }
304
+
305
+    /**
306
+     * Adds a label to the group/field
307
+     *
308
+     * @param  string $text       A label
309
+     * @param  array  $attributes The label's attributes
310
+     *
311
+     * @return Field              A field
312
+     */
313
+    public function label($text, $attributes = array())
314
+    {
315
+        // Create the Label element
316
+        $for   = $this->id ?: $this->name;
317
+        $label = $this->app['former']->label($text, $for, $attributes);
318
+
319
+        // Set label
320
+        $this->label = $label;
321
+        if ($this->group) {
322
+            $this->group->setLabel($label);
323
+        }
324
+
325
+        return $this;
326
+    }
327
+
328
+    /**
329
+     * Set the Field value no matter what
330
+     *
331
+     * @param string $value A new value
332
+     */
333
+    public function forceValue($value)
334
+    {
335
+        $this->value = $value;
336
+
337
+        return $this;
338
+    }
339
+
340
+    /**
341
+     * Classic setting of attribute, won't overwrite any populate() attempt
342
+     *
343
+     * @param  string $value A new value
344
+     */
345
+    public function value($value)
346
+    {
347
+        // Check if we already have a value stored for this field or in POST data
348
+        $already = $this->repopulate();
349
+
350
+        if (!$already) {
351
+            $this->value = $value;
352
+        }
353
+
354
+        return $this;
355
+    }
356
+
357
+    /**
358
+     * Change the field's name
359
+     *
360
+     * @param  string $name The new name
361
+     */
362
+    public function name($name)
363
+    {
364
+        $this->name = $name;
365
+
366
+        // Also relink the label to the new name
367
+        $this->label($name);
368
+
369
+        return $this;
370
+    }
371
+
372
+    /**
373
+     * Get the field's labels
374
+     *
375
+     * @return string
376
+     */
377
+    public function getLabel()
378
+    {
379
+        return $this->label;
380
+    }
381
+
382
+    /**
383
+     * Change the field's bind destination
384
+     *
385
+     * @param $destination
386
+     */
387
+    public function bind($destination) {
388
+        $this->bind = $destination;
389
+        if ($this->type != 'password') {
390
+            $this->value = $this->repopulate();
391
+        }
392
+
393
+        return $this;
394
+    }
395
+
396
+    ////////////////////////////////////////////////////////////////////
397
+    //////////////////////////////// HELPERS ///////////////////////////
398
+    ////////////////////////////////////////////////////////////////////
399
+
400
+    /**
401
+     * Use values stored in Former to populate the current field
402
+     */
403
+    private function repopulate($fallback = null)
404
+    {
405
+        // Get values from POST, populated, and manually set value
406
+        $post      = $this->app['former']->getPost($this->name);
407
+        $populator = $this->form ? $this->form->getPopulator() : $this->app['former.populator'];
408
+        $populate  = $populator->get($this->bind ?: $this->name);
409
+
410
+        // Assign a priority to each
411
+        if (!is_null($post)) {
412
+            return $post;
413
+        }
414
+        if (!is_null($populate)) {
415
+            return $populate;
416
+        }
417
+
418
+        return $fallback ?: $this->value;
419
+    }
420
+
421
+    /**
422
+     * Ponders a label and a field name, and tries to get the best out of it
423
+     *
424
+     * @param  string $label A label
425
+     * @param  string $name  A field name
426
+     *
427
+     * @return false|null         A label and a field name
428
+     */
429
+    private function automaticLabels($name, $label)
430
+    {
431
+        // Disabled automatic labels
432
+        if (!$this->app['former']->getOption('automatic_label')) {
433
+            $this->name = $name;
434
+            $this->label($label);
435
+
436
+            return false;
437
+        }
438
+
439
+        // Check for the two possibilities
440
+        if ($label and is_null($name)) {
441
+            $name = Str::slug($label);
442
+        } elseif (is_null($label) and $name) {
443
+            $label = preg_replace('/\[\]$/', '', $name);
444
+        }
445
+
446
+        // Save values
447
+        $this->name = $name;
448
+        $this->label($label);
449
+    }
450 450
 }
Please login to merge, or discard this patch.
src/Former/Traits/Framework.php 1 patch
Indentation   +301 added lines, -301 removed lines patch added patch discarded remove patch
@@ -8,305 +8,305 @@
 block discarded – undo
8 8
  */
9 9
 abstract class Framework
10 10
 {
11
-	/**
12
-	 * The Container
13
-	 *
14
-	 * @var Container
15
-	 */
16
-	protected $app;
17
-
18
-	/**
19
-	 * Form types that trigger special styling
20
-	 *
21
-	 * @var array
22
-	 */
23
-	protected $availableTypes = array();
24
-
25
-	/**
26
-	 * The field states available
27
-	 *
28
-	 * @var array
29
-	 */
30
-	protected $states = array();
31
-
32
-	/**
33
-	 * The default label width (for horizontal forms)
34
-	 *
35
-	 * @var string
36
-	 */
37
-	protected $labelWidth;
38
-
39
-	/**
40
-	 * The default field width (for horizontal forms)
41
-	 *
42
-	 * @var string
43
-	 */
44
-	protected $fieldWidth;
45
-
46
-	/**
47
-	 * The default offset for fields (for horizontal form fields
48
-	 * with no label, so usually equal to the default label width)
49
-	 *
50
-	 * @var string
51
-	 */
52
-	protected $fieldOffset;
53
-
54
-	/**
55
-	 * The default HTML tag used for icons
56
-	 *
57
-	 * @var string
58
-	 */
59
-	protected $iconTag;
60
-
61
-	/**
62
-	 * The default set for icon fonts
63
-	 *
64
-	 * @var string
65
-	 */
66
-	protected $iconSet;
67
-
68
-	/**
69
-	 * The default prefix icon names
70
-	 *
71
-	 * @var string
72
-	 */
73
-	protected $iconPrefix;
74
-
75
-	////////////////////////////////////////////////////////////////////
76
-	//////////////////////// CURRENT FRAMEWORK /////////////////////////
77
-	////////////////////////////////////////////////////////////////////
78
-
79
-	/**
80
-	 * Get the name of the current framework
81
-	 *
82
-	 * @return string
83
-	 */
84
-	public function current()
85
-	{
86
-		return basename(str_replace('\\', '/', get_class($this)));
87
-	}
88
-
89
-	/**
90
-	 * Check if the current framework matches something
91
-	 *
92
-	 * @param  string $framework
93
-	 *
94
-	 * @return boolean
95
-	 */
96
-	public function is($framework)
97
-	{
98
-		return $framework == $this->current();
99
-	}
100
-
101
-	/**
102
-	 * Check if the current framework doesn't match something
103
-	 *
104
-	 * @param  string $framework
105
-	 *
106
-	 * @return boolean
107
-	 */
108
-	public function isnt($framework)
109
-	{
110
-		return $framework != $this->current();
111
-	}
112
-
113
-	////////////////////////////////////////////////////////////////////
114
-	/////////////////////////// COMMON METHODS /////////////////////////
115
-	////////////////////////////////////////////////////////////////////
116
-
117
-	/**
118
-	 * List form types triggered special styling form current framework
119
-	 *
120
-	 * @return array
121
-	 */
122
-	public function availableTypes()
123
-	{
124
-		return $this->availableTypes;
125
-	}
126
-
127
-	/**
128
-	 * Filter a field state
129
-	 *
130
-	 * @param string $state
131
-	 *
132
-	 * @return string
133
-	 */
134
-	public function filterState($state)
135
-	{
136
-		// Filter out wrong states
137
-		return in_array($state, $this->states) ? $state : null;
138
-	}
139
-
140
-	/**
141
-	 * Framework error state
142
-	 *
143
-	 * @return string
144
-	 */
145
-	public function errorState()
146
-	{
147
-		return 'error';
148
-	}
149
-
150
-	/**
151
-	 * Returns corresponding inline class of a field
152
-	 *
153
-	 * @param Field $field
154
-	 *
155
-	 * @return string
156
-	 */
157
-	public function getInlineLabelClass($field)
158
-	{
159
-		return 'inline';
160
-	}
161
-
162
-	/**
163
-	 * Set framework defaults from its config file
164
-	 */
165
-	protected function setFrameworkDefaults()
166
-	{
167
-		$this->setFieldWidths($this->getFrameworkOption('labelWidths'));
168
-		$this->setIconDefaults();
169
-	}
170
-
171
-	/**
172
-	 * @param string $widths
173
-	 */
174
-	protected function setFieldWidths($widths)
175
-	{
176
-	}
177
-
178
-	/**
179
-	 * Override framework defaults for icons with config values where set
180
-	 */
181
-	protected function setIconDefaults()
182
-	{
183
-		$this->iconTag    = $this->getFrameworkOption('icon.tag');
184
-		$this->iconSet    = $this->getFrameworkOption('icon.set');
185
-		$this->iconPrefix = $this->getFrameworkOption('icon.prefix');
186
-	}
187
-
188
-	/**
189
-	 * Render an icon
190
-	 *
191
-	 * @param array $attributes Its general attributes
192
-	 *
193
-	 * @return string
194
-	 */
195
-	public function createIcon($iconType, $attributes = array(), $iconSettings = array())
196
-	{
197
-		// Check for empty icons
198
-		if (!$iconType) {
199
-			return false;
200
-		}
201
-
202
-		// icon settings can be overridden for a specific icon
203
-		$tag    = array_get($iconSettings, 'tag', $this->iconTag);
204
-		$set    = array_get($iconSettings, 'set', $this->iconSet);
205
-		$prefix = array_get($iconSettings, 'prefix', $this->iconPrefix);
206
-
207
-		return Element::create($tag, null, $attributes)->addClass("$set $prefix-$iconType");
208
-	}
209
-
210
-	////////////////////////////////////////////////////////////////////
211
-	///////////////////////////// HELPERS //////////////////////////////
212
-	////////////////////////////////////////////////////////////////////
213
-
214
-	/**
215
-	 * Add classes to a field
216
-	 *
217
-	 * @param Field $field
218
-	 * @param array $classes
219
-	 *
220
-	 * @return \Former\Traits\Field
221
-	 */
222
-	protected function addClassesToField($field, $classes)
223
-	{
224
-		// If we found any class, add them
225
-		if ($classes) {
226
-			$field->addClass(implode(' ', $classes));
227
-		}
228
-
229
-		return $field;
230
-	}
231
-
232
-	/**
233
-	 * Prepend an array of classes with a string
234
-	 *
235
-	 * @param array  $classes The classes to prepend
236
-	 * @param string $with    The string to prepend them with
237
-	 *
238
-	 * @return array A prepended array
239
-	 */
240
-	protected function prependWith($classes, $with)
241
-	{
242
-		return array_map(function($class) use ($with) {
243
-			return $with.$class;
244
-		}, $classes);
245
-	}
246
-
247
-	/**
248
-	 * Create a label for a field
249
-	 *
250
-	 * @param Field   $field
251
-	 * @param Element $label The field label if non provided
252
-	 *
253
-	 * @return string A label
254
-	 */
255
-	public function createLabelOf(Field $field, Element $label = null)
256
-	{
257
-		// Get the label and its informations
258
-		if (!$label) {
259
-			$label = $field->getLabel();
260
-		}
261
-
262
-		// Get label "for"
263
-		$for = $field->id ?: $field->getName();
264
-
265
-		// Get label text
266
-		$text = $label->getValue();
267
-		if (!$text) {
268
-			return false;
269
-		}
270
-
271
-		// Append required text
272
-		if ($field->isRequired()) {
273
-			$text .= $this->app['former']->getOption('required_text');
274
-		}
275
-
276
-		// Render plain label if checkable, else a classic one
277
-		$label->setValue($text);
278
-		if (!$field->isCheckable()) {
279
-			$label->for($for);
280
-		}
281
-
282
-		return $label;
283
-	}
284
-
285
-	/**
286
-	 * Get an option for the current framework
287
-	 *
288
-	 * @param string $option
289
-	 *
290
-	 * @return string
291
-	 */
292
-	protected function getFrameworkOption($option)
293
-	{
294
-		return $this->app['config']->get("former.{$this->current()}.$option");
295
-	}
296
-
297
-	////////////////////////////////////////////////////////////////////
298
-	//////////////////////////// WRAP BLOCKS ///////////////////////////
299
-	////////////////////////////////////////////////////////////////////
300
-
301
-	/**
302
-	 * Wraps all label contents with potential additional tags.
303
-	 *
304
-	 * @param  string $label
305
-	 *
306
-	 * @return string A wrapped label
307
-	 */
308
-	public function wrapLabel($label)
309
-	{
310
-		return $label;
311
-	}
11
+    /**
12
+     * The Container
13
+     *
14
+     * @var Container
15
+     */
16
+    protected $app;
17
+
18
+    /**
19
+     * Form types that trigger special styling
20
+     *
21
+     * @var array
22
+     */
23
+    protected $availableTypes = array();
24
+
25
+    /**
26
+     * The field states available
27
+     *
28
+     * @var array
29
+     */
30
+    protected $states = array();
31
+
32
+    /**
33
+     * The default label width (for horizontal forms)
34
+     *
35
+     * @var string
36
+     */
37
+    protected $labelWidth;
38
+
39
+    /**
40
+     * The default field width (for horizontal forms)
41
+     *
42
+     * @var string
43
+     */
44
+    protected $fieldWidth;
45
+
46
+    /**
47
+     * The default offset for fields (for horizontal form fields
48
+     * with no label, so usually equal to the default label width)
49
+     *
50
+     * @var string
51
+     */
52
+    protected $fieldOffset;
53
+
54
+    /**
55
+     * The default HTML tag used for icons
56
+     *
57
+     * @var string
58
+     */
59
+    protected $iconTag;
60
+
61
+    /**
62
+     * The default set for icon fonts
63
+     *
64
+     * @var string
65
+     */
66
+    protected $iconSet;
67
+
68
+    /**
69
+     * The default prefix icon names
70
+     *
71
+     * @var string
72
+     */
73
+    protected $iconPrefix;
74
+
75
+    ////////////////////////////////////////////////////////////////////
76
+    //////////////////////// CURRENT FRAMEWORK /////////////////////////
77
+    ////////////////////////////////////////////////////////////////////
78
+
79
+    /**
80
+     * Get the name of the current framework
81
+     *
82
+     * @return string
83
+     */
84
+    public function current()
85
+    {
86
+        return basename(str_replace('\\', '/', get_class($this)));
87
+    }
88
+
89
+    /**
90
+     * Check if the current framework matches something
91
+     *
92
+     * @param  string $framework
93
+     *
94
+     * @return boolean
95
+     */
96
+    public function is($framework)
97
+    {
98
+        return $framework == $this->current();
99
+    }
100
+
101
+    /**
102
+     * Check if the current framework doesn't match something
103
+     *
104
+     * @param  string $framework
105
+     *
106
+     * @return boolean
107
+     */
108
+    public function isnt($framework)
109
+    {
110
+        return $framework != $this->current();
111
+    }
112
+
113
+    ////////////////////////////////////////////////////////////////////
114
+    /////////////////////////// COMMON METHODS /////////////////////////
115
+    ////////////////////////////////////////////////////////////////////
116
+
117
+    /**
118
+     * List form types triggered special styling form current framework
119
+     *
120
+     * @return array
121
+     */
122
+    public function availableTypes()
123
+    {
124
+        return $this->availableTypes;
125
+    }
126
+
127
+    /**
128
+     * Filter a field state
129
+     *
130
+     * @param string $state
131
+     *
132
+     * @return string
133
+     */
134
+    public function filterState($state)
135
+    {
136
+        // Filter out wrong states
137
+        return in_array($state, $this->states) ? $state : null;
138
+    }
139
+
140
+    /**
141
+     * Framework error state
142
+     *
143
+     * @return string
144
+     */
145
+    public function errorState()
146
+    {
147
+        return 'error';
148
+    }
149
+
150
+    /**
151
+     * Returns corresponding inline class of a field
152
+     *
153
+     * @param Field $field
154
+     *
155
+     * @return string
156
+     */
157
+    public function getInlineLabelClass($field)
158
+    {
159
+        return 'inline';
160
+    }
161
+
162
+    /**
163
+     * Set framework defaults from its config file
164
+     */
165
+    protected function setFrameworkDefaults()
166
+    {
167
+        $this->setFieldWidths($this->getFrameworkOption('labelWidths'));
168
+        $this->setIconDefaults();
169
+    }
170
+
171
+    /**
172
+     * @param string $widths
173
+     */
174
+    protected function setFieldWidths($widths)
175
+    {
176
+    }
177
+
178
+    /**
179
+     * Override framework defaults for icons with config values where set
180
+     */
181
+    protected function setIconDefaults()
182
+    {
183
+        $this->iconTag    = $this->getFrameworkOption('icon.tag');
184
+        $this->iconSet    = $this->getFrameworkOption('icon.set');
185
+        $this->iconPrefix = $this->getFrameworkOption('icon.prefix');
186
+    }
187
+
188
+    /**
189
+     * Render an icon
190
+     *
191
+     * @param array $attributes Its general attributes
192
+     *
193
+     * @return string
194
+     */
195
+    public function createIcon($iconType, $attributes = array(), $iconSettings = array())
196
+    {
197
+        // Check for empty icons
198
+        if (!$iconType) {
199
+            return false;
200
+        }
201
+
202
+        // icon settings can be overridden for a specific icon
203
+        $tag    = array_get($iconSettings, 'tag', $this->iconTag);
204
+        $set    = array_get($iconSettings, 'set', $this->iconSet);
205
+        $prefix = array_get($iconSettings, 'prefix', $this->iconPrefix);
206
+
207
+        return Element::create($tag, null, $attributes)->addClass("$set $prefix-$iconType");
208
+    }
209
+
210
+    ////////////////////////////////////////////////////////////////////
211
+    ///////////////////////////// HELPERS //////////////////////////////
212
+    ////////////////////////////////////////////////////////////////////
213
+
214
+    /**
215
+     * Add classes to a field
216
+     *
217
+     * @param Field $field
218
+     * @param array $classes
219
+     *
220
+     * @return \Former\Traits\Field
221
+     */
222
+    protected function addClassesToField($field, $classes)
223
+    {
224
+        // If we found any class, add them
225
+        if ($classes) {
226
+            $field->addClass(implode(' ', $classes));
227
+        }
228
+
229
+        return $field;
230
+    }
231
+
232
+    /**
233
+     * Prepend an array of classes with a string
234
+     *
235
+     * @param array  $classes The classes to prepend
236
+     * @param string $with    The string to prepend them with
237
+     *
238
+     * @return array A prepended array
239
+     */
240
+    protected function prependWith($classes, $with)
241
+    {
242
+        return array_map(function($class) use ($with) {
243
+            return $with.$class;
244
+        }, $classes);
245
+    }
246
+
247
+    /**
248
+     * Create a label for a field
249
+     *
250
+     * @param Field   $field
251
+     * @param Element $label The field label if non provided
252
+     *
253
+     * @return string A label
254
+     */
255
+    public function createLabelOf(Field $field, Element $label = null)
256
+    {
257
+        // Get the label and its informations
258
+        if (!$label) {
259
+            $label = $field->getLabel();
260
+        }
261
+
262
+        // Get label "for"
263
+        $for = $field->id ?: $field->getName();
264
+
265
+        // Get label text
266
+        $text = $label->getValue();
267
+        if (!$text) {
268
+            return false;
269
+        }
270
+
271
+        // Append required text
272
+        if ($field->isRequired()) {
273
+            $text .= $this->app['former']->getOption('required_text');
274
+        }
275
+
276
+        // Render plain label if checkable, else a classic one
277
+        $label->setValue($text);
278
+        if (!$field->isCheckable()) {
279
+            $label->for($for);
280
+        }
281
+
282
+        return $label;
283
+    }
284
+
285
+    /**
286
+     * Get an option for the current framework
287
+     *
288
+     * @param string $option
289
+     *
290
+     * @return string
291
+     */
292
+    protected function getFrameworkOption($option)
293
+    {
294
+        return $this->app['config']->get("former.{$this->current()}.$option");
295
+    }
296
+
297
+    ////////////////////////////////////////////////////////////////////
298
+    //////////////////////////// WRAP BLOCKS ///////////////////////////
299
+    ////////////////////////////////////////////////////////////////////
300
+
301
+    /**
302
+     * Wraps all label contents with potential additional tags.
303
+     *
304
+     * @param  string $label
305
+     *
306
+     * @return string A wrapped label
307
+     */
308
+    public function wrapLabel($label)
309
+    {
310
+        return $label;
311
+    }
312 312
 }
Please login to merge, or discard this patch.
src/Former/Traits/Checkable.php 1 patch
Indentation   +544 added lines, -544 removed lines patch added patch discarded remove patch
@@ -12,548 +12,548 @@
 block discarded – undo
12 12
  */
13 13
 abstract class Checkable extends Field
14 14
 {
15
-	/**
16
-	 * Renders the checkables as inline
17
-	 *
18
-	 * @var boolean
19
-	 */
20
-	protected $inline = false;
21
-
22
-	/**
23
-	 * Add a text to a single element
24
-	 *
25
-	 * @var string
26
-	 */
27
-	protected $text = null;
28
-
29
-	/**
30
-	 * Renders the checkables as grouped
31
-	 *
32
-	 * @var boolean
33
-	 */
34
-	protected $grouped = false;
35
-
36
-	/**
37
-	 * The checkable items currently stored
38
-	 *
39
-	 * @var array
40
-	 */
41
-	protected $items = array();
42
-
43
-	/**
44
-	 * The type of checkable item
45
-	 *
46
-	 * @var string
47
-	 */
48
-	protected $checkable = null;
49
-
50
-	/**
51
-	 * An array of checked items
52
-	 *
53
-	 * @var array
54
-	 */
55
-	protected $checked = array();
56
-
57
-	/**
58
-	 * The checkable currently being focused on
59
-	 *
60
-	 * @var integer
61
-	 */
62
-	protected $focus = null;
63
-
64
-	/**
65
-	 * Whether this particular checkable is to be pushed
66
-	 *
67
-	 * @var boolean
68
-	 */
69
-	protected $isPushed = null;
70
-
71
-	////////////////////////////////////////////////////////////////////
72
-	//////////////////////////// CORE METHODS //////////////////////////
73
-	////////////////////////////////////////////////////////////////////
74
-
75
-	/**
76
-	 * Build a new checkable
77
-	 *
78
-	 * @param Container $app
79
-	 * @param string    $type
80
-	 * @param array     $name
81
-	 * @param           $label
82
-	 * @param           $value
83
-	 * @param           $attributes
84
-	 */
85
-	public function __construct(Container $app, $type, $name, $label, $value, $attributes)
86
-	{
87
-		// Unify auto and chained methods of grouping checkboxes
88
-		if (ends_with($name, '[]')) {
89
-			$name = substr($name, 0, -2);
90
-			$this->grouped();
91
-		}
92
-		parent::__construct($app, $type, $name, $label, $value, $attributes);
93
-
94
-		if (is_array($this->value)) {
95
-			$this->items($this->value);
96
-		}
97
-	}
98
-
99
-	/**
100
-	 * Apply methods to focused checkable
101
-	 *
102
-	 * @param string $method
103
-	 * @param array  $parameters
104
-	 *
105
-	 * @return $this
106
-	 */
107
-	public function __call($method, $parameters)
108
-	{
109
-		$focused = $this->setOnFocused('attributes.'.$method, array_get($parameters, 0));
110
-		if ($focused) {
111
-			return $this;
112
-		}
113
-
114
-		return parent::__call($method, $parameters);
115
-	}
116
-
117
-	/**
118
-	 * Prints out the currently stored checkables
119
-	 */
120
-	public function render()
121
-	{
122
-		$html = null;
123
-
124
-		// Multiple items
125
-		if ($this->items) {
126
-			unset($this->app['former']->labels[array_search($this->name, $this->app['former']->labels)]);
127
-			foreach ($this->items as $key => $item) {
128
-				$value = $this->isCheckbox() && !$this->isGrouped() ? 1 : $key;
129
-				$html .= $this->createCheckable($item, $value);
130
-			}
131
-
132
-			return $html;
133
-		}
134
-
135
-		// Single item
136
-		return $this->createCheckable(array(
137
-			'name'  => $this->name,
138
-			'label' => $this->text,
139
-			'value' => $this->value,
140
-			'attributes' => $this->attributes,
141
-		));
142
-	}
143
-
144
-	////////////////////////////////////////////////////////////////////
145
-	////////////////////////// FIELD METHODS ///////////////////////////
146
-	////////////////////////////////////////////////////////////////////
147
-
148
-	/**
149
-	 * Focus on a particular checkable
150
-	 *
151
-	 * @param integer $on The checkable to focus on
152
-	 *
153
-	 * @return $this
154
-	 */
155
-	public function on($on)
156
-	{
157
-		if (!isset($this->items[$on])) {
158
-			return $this;
159
-		} else {
160
-			$this->focus = $on;
161
-		}
162
-
163
-		return $this;
164
-	}
165
-
166
-	/**
167
-	 * Set the checkables as inline
168
-	 */
169
-	public function inline()
170
-	{
171
-		$this->inline = true;
172
-
173
-		return $this;
174
-	}
175
-
176
-	/**
177
-	 * Set the checkables as stacked
178
-	 */
179
-	public function stacked()
180
-	{
181
-		$this->inline = false;
182
-
183
-		return $this;
184
-	}
185
-
186
-	/**
187
-	 * Set the checkables as grouped
188
-	 */
189
-	public function grouped()
190
-	{
191
-		$this->grouped = true;
192
-
193
-		return $this;
194
-	}
195
-
196
-	/**
197
-	 * Add text to a single checkable
198
-	 *
199
-	 * @param  string $text The checkable label
200
-	 *
201
-	 * @return $this
202
-	 */
203
-	public function text($text)
204
-	{
205
-		// Translate and format
206
-		$text = Helpers::translate($text);
207
-
208
-		// Apply on focused if any
209
-		$focused = $this->setOnFocused('label', $text);
210
-		if ($focused) {
211
-			return $this;
212
-		}
213
-
214
-		$this->text = $text;
215
-
216
-		return $this;
217
-	}
218
-
219
-	/**
220
-	 * Push this particular checkbox
221
-	 *
222
-	 * @param boolean $pushed
223
-	 *
224
-	 * @return $this
225
-	 */
226
-	public function push($pushed = true)
227
-	{
228
-		$this->isPushed = $pushed;
229
-
230
-		return $this;
231
-	}
232
-
233
-	/**
234
-	 * Check a specific item
235
-	 *
236
-	 * @param bool|string $checked The checkable to check, or an array of checked items
237
-	 *
238
-	 * @return $this
239
-	 */
240
-	public function check($checked = true)
241
-	{
242
-		// If we're setting all the checked items at once
243
-		if (is_array($checked)) {
244
-			$this->checked = $checked;
245
-			// Checking an item in particular
246
-		} elseif (is_string($checked) or is_int($checked)) {
247
-			$this->checked[$checked] = true;
248
-			// Only setting a single item
249
-		} else {
250
-			$this->checked[$this->name] = (bool) $checked;
251
-		}
252
-
253
-		return $this;
254
-	}
255
-
256
-	////////////////////////////////////////////////////////////////////
257
-	////////////////////////// INTERNAL METHODS ////////////////////////
258
-	////////////////////////////////////////////////////////////////////
259
-
260
-	/**
261
-	 * Creates a series of checkable items
262
-	 *
263
-	 * @param array $_items Items to create
264
-	 */
265
-	protected function items($_items)
266
-	{
267
-		// If passing an array
268
-		if (sizeof($_items) == 1 and
269
-			isset($_items[0]) and
270
-			is_array($_items[0])
271
-		) {
272
-			$_items = $_items[0];
273
-		}
274
-
275
-		// Fetch models if that's what we were passed
276
-		if (isset($_items[0]) and is_object($_items[0])) {
277
-			$_items = Helpers::queryToArray($_items);
278
-			$_items = array_flip($_items);
279
-		}
280
-
281
-		// Iterate through items, assign a name and a label to each
282
-		$count = 0;
283
-		foreach ($_items as $label => $name) {
284
-
285
-			// Define a fallback name in case none is found
286
-			$fallback = $this->isCheckbox()
287
-				? $this->name.'_'.$count
288
-				: $this->name;
289
-
290
-			// Grouped fields
291
-			if ($this->isGrouped()) {
292
-				$attributes['id'] = str_replace('[]', null, $fallback);
293
-				$fallback         = str_replace('[]', null, $this->name).'[]';
294
-			}
295
-
296
-			// If we haven't any name defined for the checkable, try to compute some
297
-			if (!is_string($label) and !is_array($name)) {
298
-				$label = $name;
299
-				$name  = $fallback;
300
-			}
301
-
302
-			// If we gave custom information on the item, add them
303
-			if (is_array($name)) {
304
-				$attributes = $name;
305
-				$name       = array_get($attributes, 'name', $fallback);
306
-				unset($attributes['name']);
307
-			}
308
-
309
-			// Store all informations we have in an array
310
-			$item = array(
311
-				'name'  => $name,
312
-				'label' => Helpers::translate($label),
313
-				'count' => $count,
314
-			);
315
-			if (isset($attributes)) {
316
-				$item['attributes'] = $attributes;
317
-			}
318
-
319
-			$this->items[] = $item;
320
-			$count++;
321
-		}
322
-	}
323
-
324
-	/**
325
-	 * Renders a checkable
326
-	 *
327
-	 * @param string|array $item          A checkable item
328
-	 * @param integer      $fallbackValue A fallback value if none is set
329
-	 *
330
-	 * @return string
331
-	 */
332
-	protected function createCheckable($item, $fallbackValue = 1)
333
-	{
334
-		// Extract informations
335
-		extract($item);
336
-
337
-		// Set default values
338
-		if (!isset($attributes)) {
339
-			$attributes = array();
340
-		}
341
-		if (isset($attributes['value'])) {
342
-			$value = $attributes['value'];
343
-		}
344
-		if (!isset($value) or $value === $this->app['former']->getOption('unchecked_value')) {
345
-			$value = $fallbackValue;
346
-		}
347
-
348
-		// If inline items, add class
349
-		$isInline = $this->inline ? ' '.$this->app['former.framework']->getInlineLabelClass($this) : null;
350
-
351
-		// In Bootsrap 3, don't append the the checkable type (radio/checkbox) as a class if
352
-		// rendering inline.
353
-		$class = $this->app['former']->framework() == 'TwitterBootstrap3' ? trim($isInline) : $this->checkable.$isInline;
354
-
355
-		// Merge custom attributes with global attributes
356
-		$attributes = array_merge($this->attributes, $attributes);
357
-		if (!isset($attributes['id'])) {
358
-			$attributes['id'] = $name.$this->unique($name);
359
-		}
360
-
361
-		// Create field
362
-		$field = Input::create($this->checkable, $name, $value, $attributes);
363
-		if ($this->isChecked($item, $value)) {
364
-			$field->checked('checked');
365
-		}
366
-
367
-		// Add hidden checkbox if requested
368
-		if ($this->isOfType('checkbox', 'checkboxes')) {
369
-			if ($this->isPushed or ($this->app['former']->getOption('push_checkboxes') and $this->isPushed !== false)) {
370
-				$field = $this->app['former']->hidden($name)->forceValue($this->app['former']->getOption('unchecked_value')).$field->render();
371
-
372
-				// app['former.field'] was overwritten by Former::hidden() call in the line above, so here
373
-				// we reset it to $this to enable $this->app['former']->getErrors() to retrieve the correct object
374
-				$this->app->instance('former.field', $this);
375
-			}
376
-		}
377
-
378
-		// If no label to wrap, return plain checkable
379
-		if (!$label) {
380
-			$element = (is_object($field)) ? $field->render() : $field;
381
-		} else {
382
-			$element = Element::create('label', $field.$label)->for($attributes['id'])->class($class)->render();
383
-		}
384
-
385
-		// If BS3, if checkables are stacked, wrap them in a div with the checkable type
386
-		if (!$isInline && $this->app['former']->framework() == 'TwitterBootstrap3') {
387
-			$wrapper = Element::create('div', $element)->class($this->checkable);
388
-			if ($this->getAttribute('disabled')) {
389
-				$wrapper->addClass('disabled');
390
-			}
391
-			$element = $wrapper->render();
392
-		}
393
-
394
-		// Return the field
395
-		return $element;
396
-	}
397
-
398
-	////////////////////////////////////////////////////////////////////
399
-	///////////////////////////// HELPERS //////////////////////////////
400
-	////////////////////////////////////////////////////////////////////
401
-
402
-	/**
403
-	 * Generate an unique ID for a field
404
-	 *
405
-	 * @param string $name The field's name
406
-	 *
407
-	 * @return string A field number to use
408
-	 */
409
-	protected function unique($name)
410
-	{
411
-		$this->app['former']->labels[] = $name;
412
-
413
-		// Count number of fields with the same ID
414
-		$where  = array_filter($this->app['former']->labels, function($label) use ($name) {
415
-			return $label == $name;
416
-		});
417
-		$unique = sizeof($where);
418
-
419
-		// In case the field doesn't need to be numbered
420
-		if ($unique < 2 or empty($this->items)) {
421
-			return false;
422
-		}
423
-
424
-		return $unique;
425
-	}
426
-
427
-	/**
428
-	 * Set something on the currently focused checkable
429
-	 *
430
-	 * @param string $attribute The key to set
431
-	 * @param string $value     Its value
432
-	 *
433
-	 * @return $this|bool
434
-	 */
435
-	protected function setOnFocused($attribute, $value)
436
-	{
437
-		if (is_null($this->focus)) {
438
-			return false;
439
-		}
440
-
441
-		$this->items[$this->focus] = array_set($this->items[$this->focus], $attribute, $value);
442
-
443
-		return $this;
444
-	}
445
-
446
-	/**
447
-	 * Check if a checkable is checked
448
-	 *
449
-	 * @return boolean Checked or not
450
-	 */
451
-	protected function isChecked($item = null, $value = null)
452
-	{
453
-		if (isset($item['name'])) {
454
-			$name = $item['name'];
455
-		}
456
-		if (empty($name)) {
457
-			$name = $this->name;
458
-		}
459
-
460
-		// If it's a checkbox, see if we marqued that one as checked in the array
461
-		// Or if it's a single radio, simply see if we called check
462
-		if ($this->isCheckbox() or
463
-			!$this->isCheckbox() and !$this->items
464
-		) {
465
-			$checked = array_get($this->checked, $name, false);
466
-
467
-			// If there are multiple, search for the value
468
-			// as the name are the same between radios
469
-		} else {
470
-			$checked = array_get($this->checked, $value, false);
471
-		}
472
-
473
-		// Check the values and POST array
474
-		if ($this->isGrouped()) {
475
-			// The group index. (e.g. 'bar' if the item name is foo[bar], or the item index for foo[])
476
-			$groupIndex = self::getGroupIndexFromItem($item);
477
-
478
-			// Search using the bare name, not the individual item name
479
-			$post   = $this->app['former']->getPost($this->name);
480
-			$static = $this->app['former']->getValue($this->bind ?: $this->name);
481
-
482
-			if (isset($post[$groupIndex])) {
483
-				$post = $post[$groupIndex];
484
-			}
485
-
486
-			/**
487
-			 * Support for Laravel Collection repopulating for grouped checkboxes. Note that the groupIndex must
488
-			 * match the value in order for the checkbox to be considered checked, e.g.:
489
-			 *
490
-			 *  array(
491
-			 *    'name' = 'roles[foo]',
492
-			 *    'value' => 'foo',
493
-			 *  )
494
-			 */
495
-			if ($static instanceof Collection) {
496
-				// If the repopulate value is a collection, search for an item matching the $groupIndex
497
-				foreach ($static as $staticItem) {
498
-					$staticItemValue = method_exists($staticItem, 'getKey') ? $staticItem->getKey() : $staticItem;
499
-					if ($staticItemValue == $groupIndex) {
500
-						$static = $staticItemValue;
501
-						break;
502
-					}
503
-				}
504
-			} else if (isset($static[$groupIndex])) {
505
-				$static = $static[$groupIndex];
506
-			}
507
-		} else {
508
-			$post   = $this->app['former']->getPost($name);
509
-			$static = $this->app['former']->getValue($this->bind ?: $name);
510
-		}
511
-
512
-		if (!is_null($post) and $post !== $this->app['former']->getOption('unchecked_value')) {
513
-			$isChecked = ($post == $value);
514
-		} elseif (!is_null($static)) {
515
-			$isChecked = ($static == $value);
516
-		} else {
517
-			$isChecked = $checked;
518
-		}
519
-
520
-		return $isChecked ? true : false;
521
-	}
522
-
523
-	/**
524
-	 * Check if the current element is a checkbox
525
-	 *
526
-	 * @return boolean Checkbox or radio
527
-	 */
528
-	protected function isCheckbox()
529
-	{
530
-		return $this->checkable == 'checkbox';
531
-	}
532
-
533
-	/**
534
-	 * Check if the checkables are grouped or not
535
-	 *
536
-	 * @return boolean
537
-	 */
538
-	protected function isGrouped()
539
-	{
540
-		return
541
-			$this->grouped == true or
542
-			strpos($this->name, '[]') !== false;
543
-	}
544
-
545
-	/**
546
-	 * @param array $item The item array, containing at least name and count keys.
547
-	 *
548
-	 * @return mixed The group index. (e.g. returns bar if the item name is foo[bar], or the item count for foo[])
549
-	 */
550
-	public static function getGroupIndexFromItem($item)
551
-	{
552
-		$groupIndex = preg_replace('/^.*?\[(.*)\]$/', '$1', $item['name']);
553
-		if (empty($groupIndex) or $groupIndex == $item['name']) {
554
-			return $item['count'];
555
-		}
556
-
557
-		return $groupIndex;
558
-	}
15
+    /**
16
+     * Renders the checkables as inline
17
+     *
18
+     * @var boolean
19
+     */
20
+    protected $inline = false;
21
+
22
+    /**
23
+     * Add a text to a single element
24
+     *
25
+     * @var string
26
+     */
27
+    protected $text = null;
28
+
29
+    /**
30
+     * Renders the checkables as grouped
31
+     *
32
+     * @var boolean
33
+     */
34
+    protected $grouped = false;
35
+
36
+    /**
37
+     * The checkable items currently stored
38
+     *
39
+     * @var array
40
+     */
41
+    protected $items = array();
42
+
43
+    /**
44
+     * The type of checkable item
45
+     *
46
+     * @var string
47
+     */
48
+    protected $checkable = null;
49
+
50
+    /**
51
+     * An array of checked items
52
+     *
53
+     * @var array
54
+     */
55
+    protected $checked = array();
56
+
57
+    /**
58
+     * The checkable currently being focused on
59
+     *
60
+     * @var integer
61
+     */
62
+    protected $focus = null;
63
+
64
+    /**
65
+     * Whether this particular checkable is to be pushed
66
+     *
67
+     * @var boolean
68
+     */
69
+    protected $isPushed = null;
70
+
71
+    ////////////////////////////////////////////////////////////////////
72
+    //////////////////////////// CORE METHODS //////////////////////////
73
+    ////////////////////////////////////////////////////////////////////
74
+
75
+    /**
76
+     * Build a new checkable
77
+     *
78
+     * @param Container $app
79
+     * @param string    $type
80
+     * @param array     $name
81
+     * @param           $label
82
+     * @param           $value
83
+     * @param           $attributes
84
+     */
85
+    public function __construct(Container $app, $type, $name, $label, $value, $attributes)
86
+    {
87
+        // Unify auto and chained methods of grouping checkboxes
88
+        if (ends_with($name, '[]')) {
89
+            $name = substr($name, 0, -2);
90
+            $this->grouped();
91
+        }
92
+        parent::__construct($app, $type, $name, $label, $value, $attributes);
93
+
94
+        if (is_array($this->value)) {
95
+            $this->items($this->value);
96
+        }
97
+    }
98
+
99
+    /**
100
+     * Apply methods to focused checkable
101
+     *
102
+     * @param string $method
103
+     * @param array  $parameters
104
+     *
105
+     * @return $this
106
+     */
107
+    public function __call($method, $parameters)
108
+    {
109
+        $focused = $this->setOnFocused('attributes.'.$method, array_get($parameters, 0));
110
+        if ($focused) {
111
+            return $this;
112
+        }
113
+
114
+        return parent::__call($method, $parameters);
115
+    }
116
+
117
+    /**
118
+     * Prints out the currently stored checkables
119
+     */
120
+    public function render()
121
+    {
122
+        $html = null;
123
+
124
+        // Multiple items
125
+        if ($this->items) {
126
+            unset($this->app['former']->labels[array_search($this->name, $this->app['former']->labels)]);
127
+            foreach ($this->items as $key => $item) {
128
+                $value = $this->isCheckbox() && !$this->isGrouped() ? 1 : $key;
129
+                $html .= $this->createCheckable($item, $value);
130
+            }
131
+
132
+            return $html;
133
+        }
134
+
135
+        // Single item
136
+        return $this->createCheckable(array(
137
+            'name'  => $this->name,
138
+            'label' => $this->text,
139
+            'value' => $this->value,
140
+            'attributes' => $this->attributes,
141
+        ));
142
+    }
143
+
144
+    ////////////////////////////////////////////////////////////////////
145
+    ////////////////////////// FIELD METHODS ///////////////////////////
146
+    ////////////////////////////////////////////////////////////////////
147
+
148
+    /**
149
+     * Focus on a particular checkable
150
+     *
151
+     * @param integer $on The checkable to focus on
152
+     *
153
+     * @return $this
154
+     */
155
+    public function on($on)
156
+    {
157
+        if (!isset($this->items[$on])) {
158
+            return $this;
159
+        } else {
160
+            $this->focus = $on;
161
+        }
162
+
163
+        return $this;
164
+    }
165
+
166
+    /**
167
+     * Set the checkables as inline
168
+     */
169
+    public function inline()
170
+    {
171
+        $this->inline = true;
172
+
173
+        return $this;
174
+    }
175
+
176
+    /**
177
+     * Set the checkables as stacked
178
+     */
179
+    public function stacked()
180
+    {
181
+        $this->inline = false;
182
+
183
+        return $this;
184
+    }
185
+
186
+    /**
187
+     * Set the checkables as grouped
188
+     */
189
+    public function grouped()
190
+    {
191
+        $this->grouped = true;
192
+
193
+        return $this;
194
+    }
195
+
196
+    /**
197
+     * Add text to a single checkable
198
+     *
199
+     * @param  string $text The checkable label
200
+     *
201
+     * @return $this
202
+     */
203
+    public function text($text)
204
+    {
205
+        // Translate and format
206
+        $text = Helpers::translate($text);
207
+
208
+        // Apply on focused if any
209
+        $focused = $this->setOnFocused('label', $text);
210
+        if ($focused) {
211
+            return $this;
212
+        }
213
+
214
+        $this->text = $text;
215
+
216
+        return $this;
217
+    }
218
+
219
+    /**
220
+     * Push this particular checkbox
221
+     *
222
+     * @param boolean $pushed
223
+     *
224
+     * @return $this
225
+     */
226
+    public function push($pushed = true)
227
+    {
228
+        $this->isPushed = $pushed;
229
+
230
+        return $this;
231
+    }
232
+
233
+    /**
234
+     * Check a specific item
235
+     *
236
+     * @param bool|string $checked The checkable to check, or an array of checked items
237
+     *
238
+     * @return $this
239
+     */
240
+    public function check($checked = true)
241
+    {
242
+        // If we're setting all the checked items at once
243
+        if (is_array($checked)) {
244
+            $this->checked = $checked;
245
+            // Checking an item in particular
246
+        } elseif (is_string($checked) or is_int($checked)) {
247
+            $this->checked[$checked] = true;
248
+            // Only setting a single item
249
+        } else {
250
+            $this->checked[$this->name] = (bool) $checked;
251
+        }
252
+
253
+        return $this;
254
+    }
255
+
256
+    ////////////////////////////////////////////////////////////////////
257
+    ////////////////////////// INTERNAL METHODS ////////////////////////
258
+    ////////////////////////////////////////////////////////////////////
259
+
260
+    /**
261
+     * Creates a series of checkable items
262
+     *
263
+     * @param array $_items Items to create
264
+     */
265
+    protected function items($_items)
266
+    {
267
+        // If passing an array
268
+        if (sizeof($_items) == 1 and
269
+            isset($_items[0]) and
270
+            is_array($_items[0])
271
+        ) {
272
+            $_items = $_items[0];
273
+        }
274
+
275
+        // Fetch models if that's what we were passed
276
+        if (isset($_items[0]) and is_object($_items[0])) {
277
+            $_items = Helpers::queryToArray($_items);
278
+            $_items = array_flip($_items);
279
+        }
280
+
281
+        // Iterate through items, assign a name and a label to each
282
+        $count = 0;
283
+        foreach ($_items as $label => $name) {
284
+
285
+            // Define a fallback name in case none is found
286
+            $fallback = $this->isCheckbox()
287
+                ? $this->name.'_'.$count
288
+                : $this->name;
289
+
290
+            // Grouped fields
291
+            if ($this->isGrouped()) {
292
+                $attributes['id'] = str_replace('[]', null, $fallback);
293
+                $fallback         = str_replace('[]', null, $this->name).'[]';
294
+            }
295
+
296
+            // If we haven't any name defined for the checkable, try to compute some
297
+            if (!is_string($label) and !is_array($name)) {
298
+                $label = $name;
299
+                $name  = $fallback;
300
+            }
301
+
302
+            // If we gave custom information on the item, add them
303
+            if (is_array($name)) {
304
+                $attributes = $name;
305
+                $name       = array_get($attributes, 'name', $fallback);
306
+                unset($attributes['name']);
307
+            }
308
+
309
+            // Store all informations we have in an array
310
+            $item = array(
311
+                'name'  => $name,
312
+                'label' => Helpers::translate($label),
313
+                'count' => $count,
314
+            );
315
+            if (isset($attributes)) {
316
+                $item['attributes'] = $attributes;
317
+            }
318
+
319
+            $this->items[] = $item;
320
+            $count++;
321
+        }
322
+    }
323
+
324
+    /**
325
+     * Renders a checkable
326
+     *
327
+     * @param string|array $item          A checkable item
328
+     * @param integer      $fallbackValue A fallback value if none is set
329
+     *
330
+     * @return string
331
+     */
332
+    protected function createCheckable($item, $fallbackValue = 1)
333
+    {
334
+        // Extract informations
335
+        extract($item);
336
+
337
+        // Set default values
338
+        if (!isset($attributes)) {
339
+            $attributes = array();
340
+        }
341
+        if (isset($attributes['value'])) {
342
+            $value = $attributes['value'];
343
+        }
344
+        if (!isset($value) or $value === $this->app['former']->getOption('unchecked_value')) {
345
+            $value = $fallbackValue;
346
+        }
347
+
348
+        // If inline items, add class
349
+        $isInline = $this->inline ? ' '.$this->app['former.framework']->getInlineLabelClass($this) : null;
350
+
351
+        // In Bootsrap 3, don't append the the checkable type (radio/checkbox) as a class if
352
+        // rendering inline.
353
+        $class = $this->app['former']->framework() == 'TwitterBootstrap3' ? trim($isInline) : $this->checkable.$isInline;
354
+
355
+        // Merge custom attributes with global attributes
356
+        $attributes = array_merge($this->attributes, $attributes);
357
+        if (!isset($attributes['id'])) {
358
+            $attributes['id'] = $name.$this->unique($name);
359
+        }
360
+
361
+        // Create field
362
+        $field = Input::create($this->checkable, $name, $value, $attributes);
363
+        if ($this->isChecked($item, $value)) {
364
+            $field->checked('checked');
365
+        }
366
+
367
+        // Add hidden checkbox if requested
368
+        if ($this->isOfType('checkbox', 'checkboxes')) {
369
+            if ($this->isPushed or ($this->app['former']->getOption('push_checkboxes') and $this->isPushed !== false)) {
370
+                $field = $this->app['former']->hidden($name)->forceValue($this->app['former']->getOption('unchecked_value')).$field->render();
371
+
372
+                // app['former.field'] was overwritten by Former::hidden() call in the line above, so here
373
+                // we reset it to $this to enable $this->app['former']->getErrors() to retrieve the correct object
374
+                $this->app->instance('former.field', $this);
375
+            }
376
+        }
377
+
378
+        // If no label to wrap, return plain checkable
379
+        if (!$label) {
380
+            $element = (is_object($field)) ? $field->render() : $field;
381
+        } else {
382
+            $element = Element::create('label', $field.$label)->for($attributes['id'])->class($class)->render();
383
+        }
384
+
385
+        // If BS3, if checkables are stacked, wrap them in a div with the checkable type
386
+        if (!$isInline && $this->app['former']->framework() == 'TwitterBootstrap3') {
387
+            $wrapper = Element::create('div', $element)->class($this->checkable);
388
+            if ($this->getAttribute('disabled')) {
389
+                $wrapper->addClass('disabled');
390
+            }
391
+            $element = $wrapper->render();
392
+        }
393
+
394
+        // Return the field
395
+        return $element;
396
+    }
397
+
398
+    ////////////////////////////////////////////////////////////////////
399
+    ///////////////////////////// HELPERS //////////////////////////////
400
+    ////////////////////////////////////////////////////////////////////
401
+
402
+    /**
403
+     * Generate an unique ID for a field
404
+     *
405
+     * @param string $name The field's name
406
+     *
407
+     * @return string A field number to use
408
+     */
409
+    protected function unique($name)
410
+    {
411
+        $this->app['former']->labels[] = $name;
412
+
413
+        // Count number of fields with the same ID
414
+        $where  = array_filter($this->app['former']->labels, function($label) use ($name) {
415
+            return $label == $name;
416
+        });
417
+        $unique = sizeof($where);
418
+
419
+        // In case the field doesn't need to be numbered
420
+        if ($unique < 2 or empty($this->items)) {
421
+            return false;
422
+        }
423
+
424
+        return $unique;
425
+    }
426
+
427
+    /**
428
+     * Set something on the currently focused checkable
429
+     *
430
+     * @param string $attribute The key to set
431
+     * @param string $value     Its value
432
+     *
433
+     * @return $this|bool
434
+     */
435
+    protected function setOnFocused($attribute, $value)
436
+    {
437
+        if (is_null($this->focus)) {
438
+            return false;
439
+        }
440
+
441
+        $this->items[$this->focus] = array_set($this->items[$this->focus], $attribute, $value);
442
+
443
+        return $this;
444
+    }
445
+
446
+    /**
447
+     * Check if a checkable is checked
448
+     *
449
+     * @return boolean Checked or not
450
+     */
451
+    protected function isChecked($item = null, $value = null)
452
+    {
453
+        if (isset($item['name'])) {
454
+            $name = $item['name'];
455
+        }
456
+        if (empty($name)) {
457
+            $name = $this->name;
458
+        }
459
+
460
+        // If it's a checkbox, see if we marqued that one as checked in the array
461
+        // Or if it's a single radio, simply see if we called check
462
+        if ($this->isCheckbox() or
463
+            !$this->isCheckbox() and !$this->items
464
+        ) {
465
+            $checked = array_get($this->checked, $name, false);
466
+
467
+            // If there are multiple, search for the value
468
+            // as the name are the same between radios
469
+        } else {
470
+            $checked = array_get($this->checked, $value, false);
471
+        }
472
+
473
+        // Check the values and POST array
474
+        if ($this->isGrouped()) {
475
+            // The group index. (e.g. 'bar' if the item name is foo[bar], or the item index for foo[])
476
+            $groupIndex = self::getGroupIndexFromItem($item);
477
+
478
+            // Search using the bare name, not the individual item name
479
+            $post   = $this->app['former']->getPost($this->name);
480
+            $static = $this->app['former']->getValue($this->bind ?: $this->name);
481
+
482
+            if (isset($post[$groupIndex])) {
483
+                $post = $post[$groupIndex];
484
+            }
485
+
486
+            /**
487
+             * Support for Laravel Collection repopulating for grouped checkboxes. Note that the groupIndex must
488
+             * match the value in order for the checkbox to be considered checked, e.g.:
489
+             *
490
+             *  array(
491
+             *    'name' = 'roles[foo]',
492
+             *    'value' => 'foo',
493
+             *  )
494
+             */
495
+            if ($static instanceof Collection) {
496
+                // If the repopulate value is a collection, search for an item matching the $groupIndex
497
+                foreach ($static as $staticItem) {
498
+                    $staticItemValue = method_exists($staticItem, 'getKey') ? $staticItem->getKey() : $staticItem;
499
+                    if ($staticItemValue == $groupIndex) {
500
+                        $static = $staticItemValue;
501
+                        break;
502
+                    }
503
+                }
504
+            } else if (isset($static[$groupIndex])) {
505
+                $static = $static[$groupIndex];
506
+            }
507
+        } else {
508
+            $post   = $this->app['former']->getPost($name);
509
+            $static = $this->app['former']->getValue($this->bind ?: $name);
510
+        }
511
+
512
+        if (!is_null($post) and $post !== $this->app['former']->getOption('unchecked_value')) {
513
+            $isChecked = ($post == $value);
514
+        } elseif (!is_null($static)) {
515
+            $isChecked = ($static == $value);
516
+        } else {
517
+            $isChecked = $checked;
518
+        }
519
+
520
+        return $isChecked ? true : false;
521
+    }
522
+
523
+    /**
524
+     * Check if the current element is a checkbox
525
+     *
526
+     * @return boolean Checkbox or radio
527
+     */
528
+    protected function isCheckbox()
529
+    {
530
+        return $this->checkable == 'checkbox';
531
+    }
532
+
533
+    /**
534
+     * Check if the checkables are grouped or not
535
+     *
536
+     * @return boolean
537
+     */
538
+    protected function isGrouped()
539
+    {
540
+        return
541
+            $this->grouped == true or
542
+            strpos($this->name, '[]') !== false;
543
+    }
544
+
545
+    /**
546
+     * @param array $item The item array, containing at least name and count keys.
547
+     *
548
+     * @return mixed The group index. (e.g. returns bar if the item name is foo[bar], or the item count for foo[])
549
+     */
550
+    public static function getGroupIndexFromItem($item)
551
+    {
552
+        $groupIndex = preg_replace('/^.*?\[(.*)\]$/', '$1', $item['name']);
553
+        if (empty($groupIndex) or $groupIndex == $item['name']) {
554
+            return $item['count'];
555
+        }
556
+
557
+        return $groupIndex;
558
+    }
559 559
 }
Please login to merge, or discard this patch.
src/Former/Traits/FormerObject.php 1 patch
Indentation   +143 added lines, -143 removed lines patch added patch discarded remove patch
@@ -10,147 +10,147 @@
 block discarded – undo
10 10
  */
11 11
 abstract class FormerObject extends Element
12 12
 {
13
-	/**
14
-	 * The field's name
15
-	 *
16
-	 * @var string
17
-	 */
18
-	protected $name;
19
-
20
-	/**
21
-	 * The field type
22
-	 *
23
-	 * @var string
24
-	 */
25
-	protected $type;
26
-
27
-	/**
28
-	 * A list of class properties to be added to attributes
29
-	 *
30
-	 * @var array
31
-	 */
32
-	protected $injectedProperties = array('name');
33
-
34
-	////////////////////////////////////////////////////////////////////
35
-	/////////////////////////// ID AND LABELS //////////////////////////
36
-	////////////////////////////////////////////////////////////////////
37
-
38
-	/**
39
-	 * Create an unique ID and return it
40
-	 *
41
-	 * @return string
42
-	 */
43
-	public function getCreatedId()
44
-	{
45
-		$this->setId();
46
-
47
-		return $this->attributes['id'];
48
-	}
49
-
50
-	/**
51
-	 * Set the matching ID on a field if possible
52
-	 */
53
-	protected function setId()
54
-	{
55
-		if (!array_key_exists('id', $this->attributes) and
56
-			in_array($this->name, $this->app['former']->labels)
57
-		) {
58
-			// Set and save the field's ID
59
-			$id                         = $this->getUniqueId($this->name);
60
-			$this->attributes['id']     = $id;
61
-			$this->app['former']->ids[] = $id;
62
-		}
63
-	}
64
-
65
-	/**
66
-	 * Get an unique ID for a field from its name
67
-	 *
68
-	 * @param string $name
69
-	 *
70
-	 * @return string
71
-	 */
72
-	protected function getUniqueId($name)
73
-	{
74
-		$names = &$this->app['former']->names;
75
-
76
-		if (array_key_exists($name, $names)) {
77
-			$count = $names[$name] + 1;
78
-			$names[$name] = $count;
79
-			return $name.'-'.$count;
80
-		}
81
-
82
-		$names[$name] = 1;
83
-		return $name;
84
-	}
85
-
86
-	/**
87
-	 * Render the FormerObject and set its id
88
-	 *
89
-	 * @return string
90
-	 */
91
-	public function render()
92
-	{
93
-		// Set the proper ID according to the label
94
-		$this->setId();
95
-
96
-		// Encode HTML value
97
-		$isButton = ($this instanceof Field) ? $this->isButton() : false;
98
-		if (!$isButton and is_string($this->value)) {
99
-			$this->value = Helpers::encode($this->value);
100
-		}
101
-
102
-		return parent::render();
103
-	}
104
-
105
-	////////////////////////////////////////////////////////////////////
106
-	////////////////////////////// GETTERS /////////////////////////////
107
-	////////////////////////////////////////////////////////////////////
108
-
109
-	/**
110
-	 * Get the object's name
111
-	 *
112
-	 * @return string
113
-	 */
114
-	public function getName()
115
-	{
116
-		return $this->name;
117
-	}
118
-
119
-	////////////////////////////////////////////////////////////////////
120
-	//////////////////////////// OBJECT TYPE ///////////////////////////
121
-	////////////////////////////////////////////////////////////////////
122
-
123
-	/**
124
-	 * Get the object's type
125
-	 *
126
-	 * @return string
127
-	 */
128
-	public function getType()
129
-	{
130
-		return $this->type;
131
-	}
132
-
133
-	/**
134
-	 * Change a object's type
135
-	 *
136
-	 * @param string $type
137
-	 */
138
-	public function setType($type)
139
-	{
140
-		$this->type = $type;
141
-
142
-		return $this;
143
-	}
144
-
145
-	/**
146
-	 * Check if an object is of a certain type
147
-	 *
148
-	 * @return boolean
149
-	 */
150
-	public function isOfType()
151
-	{
152
-		$types = func_get_args();
153
-
154
-		return in_array($this->type, $types);
155
-	}
13
+    /**
14
+     * The field's name
15
+     *
16
+     * @var string
17
+     */
18
+    protected $name;
19
+
20
+    /**
21
+     * The field type
22
+     *
23
+     * @var string
24
+     */
25
+    protected $type;
26
+
27
+    /**
28
+     * A list of class properties to be added to attributes
29
+     *
30
+     * @var array
31
+     */
32
+    protected $injectedProperties = array('name');
33
+
34
+    ////////////////////////////////////////////////////////////////////
35
+    /////////////////////////// ID AND LABELS //////////////////////////
36
+    ////////////////////////////////////////////////////////////////////
37
+
38
+    /**
39
+     * Create an unique ID and return it
40
+     *
41
+     * @return string
42
+     */
43
+    public function getCreatedId()
44
+    {
45
+        $this->setId();
46
+
47
+        return $this->attributes['id'];
48
+    }
49
+
50
+    /**
51
+     * Set the matching ID on a field if possible
52
+     */
53
+    protected function setId()
54
+    {
55
+        if (!array_key_exists('id', $this->attributes) and
56
+            in_array($this->name, $this->app['former']->labels)
57
+        ) {
58
+            // Set and save the field's ID
59
+            $id                         = $this->getUniqueId($this->name);
60
+            $this->attributes['id']     = $id;
61
+            $this->app['former']->ids[] = $id;
62
+        }
63
+    }
64
+
65
+    /**
66
+     * Get an unique ID for a field from its name
67
+     *
68
+     * @param string $name
69
+     *
70
+     * @return string
71
+     */
72
+    protected function getUniqueId($name)
73
+    {
74
+        $names = &$this->app['former']->names;
75
+
76
+        if (array_key_exists($name, $names)) {
77
+            $count = $names[$name] + 1;
78
+            $names[$name] = $count;
79
+            return $name.'-'.$count;
80
+        }
81
+
82
+        $names[$name] = 1;
83
+        return $name;
84
+    }
85
+
86
+    /**
87
+     * Render the FormerObject and set its id
88
+     *
89
+     * @return string
90
+     */
91
+    public function render()
92
+    {
93
+        // Set the proper ID according to the label
94
+        $this->setId();
95
+
96
+        // Encode HTML value
97
+        $isButton = ($this instanceof Field) ? $this->isButton() : false;
98
+        if (!$isButton and is_string($this->value)) {
99
+            $this->value = Helpers::encode($this->value);
100
+        }
101
+
102
+        return parent::render();
103
+    }
104
+
105
+    ////////////////////////////////////////////////////////////////////
106
+    ////////////////////////////// GETTERS /////////////////////////////
107
+    ////////////////////////////////////////////////////////////////////
108
+
109
+    /**
110
+     * Get the object's name
111
+     *
112
+     * @return string
113
+     */
114
+    public function getName()
115
+    {
116
+        return $this->name;
117
+    }
118
+
119
+    ////////////////////////////////////////////////////////////////////
120
+    //////////////////////////// OBJECT TYPE ///////////////////////////
121
+    ////////////////////////////////////////////////////////////////////
122
+
123
+    /**
124
+     * Get the object's type
125
+     *
126
+     * @return string
127
+     */
128
+    public function getType()
129
+    {
130
+        return $this->type;
131
+    }
132
+
133
+    /**
134
+     * Change a object's type
135
+     *
136
+     * @param string $type
137
+     */
138
+    public function setType($type)
139
+    {
140
+        $this->type = $type;
141
+
142
+        return $this;
143
+    }
144
+
145
+    /**
146
+     * Check if an object is of a certain type
147
+     *
148
+     * @return boolean
149
+     */
150
+    public function isOfType()
151
+    {
152
+        $types = func_get_args();
153
+
154
+        return in_array($this->type, $types);
155
+    }
156 156
 }
Please login to merge, or discard this patch.
src/Former/Form/Actions.php 1 patch
Indentation   +106 added lines, -106 removed lines patch added patch discarded remove patch
@@ -11,110 +11,110 @@
 block discarded – undo
11 11
  */
12 12
 class Actions extends FormerObject
13 13
 {
14
-	/**
15
-	 * The Container
16
-	 *
17
-	 * @var Container
18
-	 */
19
-	protected $app;
20
-
21
-	/**
22
-	 * The Actions element
23
-	 *
24
-	 * @var string
25
-	 */
26
-	protected $element = 'div';
27
-
28
-	////////////////////////////////////////////////////////////////////
29
-	/////////////////////////// CORE METHODS ///////////////////////////
30
-	////////////////////////////////////////////////////////////////////
31
-
32
-	/**
33
-	 * Constructs a new Actions block
34
-	 *
35
-	 * @param Container $app
36
-	 * @param array     $value The block content
37
-	 */
38
-	public function __construct(Container $app, $value)
39
-	{
40
-		$this->app   = $app;
41
-		$this->value = $value;
42
-
43
-		// Add specific actions classes to the actions block
44
-		$this->addClass($this->app['former.framework']->getActionClasses());
45
-	}
46
-
47
-	/**
48
-	 * Get the content of the Actions block
49
-	 *
50
-	 * @return string
51
-	 */
52
-	public function getContent()
53
-	{
54
-		$content = array_map(function($content) {
55
-			return method_exists($content, '__toString') ? (string) $content : $content;
56
-		}, $this->value);
57
-
58
-		return $this->app['former.framework']->wrapActions(implode(' ', $content));
59
-	}
60
-
61
-	/**
62
-	 * Dynamically append actions to the block
63
-	 *
64
-	 * @param string $method     The method
65
-	 * @param array  $parameters Its parameters
66
-	 *
67
-	 * @return Actions
68
-	 */
69
-	public function __call($method, $parameters)
70
-	{
71
-		// Dynamically add buttons to an actions block
72
-		if ($this->isButtonMethod($method)) {
73
-			$text       = array_get($parameters, 0);
74
-			$link       = array_get($parameters, 1);
75
-			$attributes = array_get($parameters, 2);
76
-			if (!$attributes and is_array($link)) {
77
-				$attributes = $link;
78
-			}
79
-
80
-			return $this->createButtonOfType($method, $text, $link, $attributes);
81
-		}
82
-
83
-		return parent::__call($method, $parameters);
84
-	}
85
-
86
-	////////////////////////////////////////////////////////////////////
87
-	////////////////////////////// HELPERS /////////////////////////////
88
-	////////////////////////////////////////////////////////////////////
89
-
90
-	/**
91
-	 * Create a new Button and add it to the actions
92
-	 *
93
-	 * @param string $type       The button type
94
-	 * @param string $name       Its name
95
-	 * @param string $link       A link to point to
96
-	 * @param array  $attributes Its attributes
97
-	 *
98
-	 * @return Actions
99
-	 */
100
-	private function createButtonOfType($type, $name, $link, $attributes)
101
-	{
102
-		$this->value[] = $this->app['former']->$type($name, $link, $attributes)->__toString();
103
-
104
-		return $this;
105
-	}
106
-
107
-	/**
108
-	 * Check if a given method calls a button or not
109
-	 *
110
-	 * @param string $method The method to check
111
-	 *
112
-	 * @return boolean
113
-	 */
114
-	private function isButtonMethod($method)
115
-	{
116
-		$buttons = array('button', 'submit', 'link', 'reset');
117
-
118
-		return (bool) Str::contains($method, $buttons);
119
-	}
14
+    /**
15
+     * The Container
16
+     *
17
+     * @var Container
18
+     */
19
+    protected $app;
20
+
21
+    /**
22
+     * The Actions element
23
+     *
24
+     * @var string
25
+     */
26
+    protected $element = 'div';
27
+
28
+    ////////////////////////////////////////////////////////////////////
29
+    /////////////////////////// CORE METHODS ///////////////////////////
30
+    ////////////////////////////////////////////////////////////////////
31
+
32
+    /**
33
+     * Constructs a new Actions block
34
+     *
35
+     * @param Container $app
36
+     * @param array     $value The block content
37
+     */
38
+    public function __construct(Container $app, $value)
39
+    {
40
+        $this->app   = $app;
41
+        $this->value = $value;
42
+
43
+        // Add specific actions classes to the actions block
44
+        $this->addClass($this->app['former.framework']->getActionClasses());
45
+    }
46
+
47
+    /**
48
+     * Get the content of the Actions block
49
+     *
50
+     * @return string
51
+     */
52
+    public function getContent()
53
+    {
54
+        $content = array_map(function($content) {
55
+            return method_exists($content, '__toString') ? (string) $content : $content;
56
+        }, $this->value);
57
+
58
+        return $this->app['former.framework']->wrapActions(implode(' ', $content));
59
+    }
60
+
61
+    /**
62
+     * Dynamically append actions to the block
63
+     *
64
+     * @param string $method     The method
65
+     * @param array  $parameters Its parameters
66
+     *
67
+     * @return Actions
68
+     */
69
+    public function __call($method, $parameters)
70
+    {
71
+        // Dynamically add buttons to an actions block
72
+        if ($this->isButtonMethod($method)) {
73
+            $text       = array_get($parameters, 0);
74
+            $link       = array_get($parameters, 1);
75
+            $attributes = array_get($parameters, 2);
76
+            if (!$attributes and is_array($link)) {
77
+                $attributes = $link;
78
+            }
79
+
80
+            return $this->createButtonOfType($method, $text, $link, $attributes);
81
+        }
82
+
83
+        return parent::__call($method, $parameters);
84
+    }
85
+
86
+    ////////////////////////////////////////////////////////////////////
87
+    ////////////////////////////// HELPERS /////////////////////////////
88
+    ////////////////////////////////////////////////////////////////////
89
+
90
+    /**
91
+     * Create a new Button and add it to the actions
92
+     *
93
+     * @param string $type       The button type
94
+     * @param string $name       Its name
95
+     * @param string $link       A link to point to
96
+     * @param array  $attributes Its attributes
97
+     *
98
+     * @return Actions
99
+     */
100
+    private function createButtonOfType($type, $name, $link, $attributes)
101
+    {
102
+        $this->value[] = $this->app['former']->$type($name, $link, $attributes)->__toString();
103
+
104
+        return $this;
105
+    }
106
+
107
+    /**
108
+     * Check if a given method calls a button or not
109
+     *
110
+     * @param string $method The method to check
111
+     *
112
+     * @return boolean
113
+     */
114
+    private function isButtonMethod($method)
115
+    {
116
+        $buttons = array('button', 'submit', 'link', 'reset');
117
+
118
+        return (bool) Str::contains($method, $buttons);
119
+    }
120 120
 }
Please login to merge, or discard this patch.
src/Former/Form/Group.php 1 patch
Indentation   +457 added lines, -457 removed lines patch added patch discarded remove patch
@@ -12,461 +12,461 @@
 block discarded – undo
12 12
  */
13 13
 class Group extends Tag
14 14
 {
15
-	/**
16
-	 * The Container
17
-	 *
18
-	 * @var Container
19
-	 */
20
-	protected $app;
21
-
22
-	/**
23
-	 * The current state of the group
24
-	 *
25
-	 * @var string
26
-	 */
27
-	protected $state = null;
28
-
29
-	/**
30
-	 * Whether the field should be displayed raw or not
31
-	 *
32
-	 * @var boolean
33
-	 */
34
-	protected $raw = false;
35
-
36
-	/**
37
-	 * The group label
38
-	 *
39
-	 * @var Element
40
-	 */
41
-	protected $label;
42
-
43
-	/**
44
-	 * The group help
45
-	 *
46
-	 * @var array
47
-	 */
48
-	protected $help = array();
49
-
50
-	/**
51
-	 * An array of elements to preprend the field
52
-	 *
53
-	 * @var array
54
-	 */
55
-	protected $prepend = array();
56
-
57
-	/**
58
-	 * An array of elements to append the field
59
-	 *
60
-	 * @var array
61
-	 */
62
-	protected $append = array();
63
-
64
-	/**
65
-	 * The field validations to be checked for errors
66
-	 *
67
-	 * @var array
68
-	 */
69
-	protected $validations = array();
70
-
71
-	/**
72
-	 * The group's element
73
-	 *
74
-	 * @var string
75
-	 */
76
-	protected $element = 'div';
77
-
78
-	/**
79
-	 * Whether a custom group is opened or not
80
-	 *
81
-	 * @var boolean
82
-	 */
83
-	public static $opened = false;
84
-
85
-	/**
86
-	 * The custom group that is open
87
-	 *
88
-	 * @var Former\Form\Group
89
-	 */
90
-	public static $openGroup = null;
91
-
92
-	////////////////////////////////////////////////////////////////////
93
-	/////////////////////////// CORE METHODS ///////////////////////////
94
-	////////////////////////////////////////////////////////////////////
95
-
96
-	/**
97
-	 * Creates a group
98
-	 *
99
-	 * @param string $label Its label
100
-	 */
101
-	public function __construct(Container $app, $label, $validations = null)
102
-	{
103
-		// Get special classes
104
-		$this->app = $app;
105
-		$this->addClass($this->app['former.framework']->getGroupClasses());
106
-
107
-		// Invisible if Nude
108
-		if ($this->app['former.framework']->is('Nude')) {
109
-			$this->element = '';
110
-		}
111
-
112
-		// Set group label
113
-		if ($label) {
114
-			$this->setLabel($label);
115
-		}
116
-
117
-		// Set validations used to override groups own conclusions
118
-		$this->validations = (array) $validations;
119
-	}
120
-
121
-	/**
122
-	 * Prints out the opening of the Control Group
123
-	 *
124
-	 * @return string A control group opening tag
125
-	 */
126
-	public function __toString()
127
-	{
128
-		return $this->open().$this->getFormattedLabel();
129
-	}
130
-
131
-	/**
132
-	 * Opens a group
133
-	 *
134
-	 * @return string Opening tag
135
-	 */
136
-	public function open()
137
-	{
138
-		if ($this->getErrors()) {
139
-			$this->state($this->app['former.framework']->errorState());
140
-		}
141
-
142
-		// Retrieve state and append it to classes
143
-		if ($this->state) {
144
-			$this->addClass($this->state);
145
-		}
146
-
147
-		// Required state
148
-		if ($this->app->bound('former.field') and $this->app['former.field']->isRequired()) {
149
-			$this->addClass($this->app['former']->getOption('required_class'));
150
-		}
151
-
152
-		return parent::open();
153
-	}
154
-
155
-	/**
156
-	 * Set the contents of the current group
157
-	 *
158
-	 * @param string $contents The group contents
159
-	 *
160
-	 * @return string A group
161
-	 */
162
-	public function contents($contents)
163
-	{
164
-		return $this->wrap($contents, $this->getFormattedLabel());
165
-	}
166
-
167
-	/**
168
-	 * Wrap a Field with the current group
169
-	 *
170
-	 * @param  \Former\Traits\Field $field A Field instance
171
-	 *
172
-	 * @return string        A group
173
-	 */
174
-	public function wrapField($field)
175
-	{
176
-		$label = $this->getLabel($field);
177
-		$field = $this->prependAppend($field);
178
-		$field .= $this->getHelp();
179
-
180
-		return $this->wrap($field, $label);
181
-	}
182
-
183
-	////////////////////////////////////////////////////////////////////
184
-	//////////////////////////// FIELD METHODS /////////////////////////
185
-	////////////////////////////////////////////////////////////////////
186
-
187
-	/**
188
-	 * Set the state of the group
189
-	 *
190
-	 * @param  string $state A Bootstrap state class
191
-	 */
192
-	public function state($state)
193
-	{
194
-		// Filter state
195
-		$state = $this->app['former.framework']->filterState($state);
196
-
197
-		$this->state = $state;
198
-	}
199
-
200
-	/**
201
-	 * Set a class on the Group
202
-	 *
203
-	 * @param string $class The class to add
204
-	 */
205
-	public function addGroupClass($class)
206
-	{
207
-		$this->addClass($class);
208
-	}
209
-
210
-	/**
211
-	 * Adds a label to the group
212
-	 *
213
-	 * @param  string $label A label
214
-	 */
215
-	public function setLabel($label)
216
-	{
217
-		if (!$label instanceof Element) {
218
-			$label = Helpers::translate($label);
219
-			$label = Element::create('label', $label)->for($label);
220
-		}
221
-
222
-		$this->label = $label;
223
-	}
224
-
225
-	/**
226
-	 * Get the formatted group label
227
-	 *
228
-	 * @return string|null
229
-	 */
230
-	public function getFormattedLabel()
231
-	{
232
-		if (!$this->label) {
233
-			return false;
234
-		}
235
-
236
-		return $this->label->addClass($this->app['former.framework']->getLabelClasses());
237
-	}
238
-
239
-	/**
240
-	 * Disables the control group for the current field
241
-	 */
242
-	public function raw()
243
-	{
244
-		$this->raw = true;
245
-	}
246
-
247
-	/**
248
-	 * Check if the current group is to be displayed or not
249
-	 *
250
-	 * @return boolean
251
-	 */
252
-	public function isRaw()
253
-	{
254
-		return (bool) $this->raw;
255
-	}
256
-
257
-	////////////////////////////////////////////////////////////////////
258
-	///////////////////////////// HELP BLOCKS //////////////////////////
259
-	////////////////////////////////////////////////////////////////////
260
-
261
-	/**
262
-	 * Alias for inlineHelp
263
-	 *
264
-	 * @param  string $help       The help text
265
-	 * @param  array  $attributes Facultative attributes
266
-	 */
267
-	public function help($help, $attributes = array())
268
-	{
269
-		return $this->inlineHelp($help, $attributes);
270
-	}
271
-
272
-	/**
273
-	 * Add an inline help
274
-	 *
275
-	 * @param  string $help       The help text
276
-	 * @param  array  $attributes Facultative attributes
277
-	 */
278
-	public function inlineHelp($help, $attributes = array())
279
-	{
280
-		// If no help text, do nothing
281
-		if (!$help) {
282
-			return false;
283
-		}
284
-
285
-		$this->help['inline'] = $this->app['former.framework']->createHelp($help, $attributes);
286
-	}
287
-
288
-	/**
289
-	 * Add an block help
290
-	 *
291
-	 * @param  string $help       The help text
292
-	 * @param  array  $attributes Facultative attributes
293
-	 */
294
-	public function blockHelp($help, $attributes = array())
295
-	{
296
-		// Reserved method
297
-		if ($this->app['former.framework']->isnt('TwitterBootstrap') && $this->app['former.framework']->isnt('TwitterBootstrap3')) {
298
-			throw new BadMethodCallException('This method is only available on the Bootstrap framework');
299
-		}
300
-
301
-		// If no help text, do nothing
302
-		if (!$help) {
303
-			return false;
304
-		}
305
-
306
-		$this->help['block'] = $this->app['former.framework']->createBlockHelp($help, $attributes);
307
-	}
308
-
309
-	////////////////////////////////////////////////////////////////////
310
-	///////////////////////// PREPEND/APPEND METHODS ///////////////////
311
-	////////////////////////////////////////////////////////////////////
312
-
313
-	/**
314
-	 * Prepend elements to the field
315
-	 */
316
-	public function prepend()
317
-	{
318
-		$this->placeAround(func_get_args(), 'prepend');
319
-	}
320
-
321
-	/**
322
-	 * Append elements to the field
323
-	 */
324
-	public function append()
325
-	{
326
-		$this->placeAround(func_get_args(), 'append');
327
-	}
328
-
329
-	/**
330
-	 * Prepends an icon to a field
331
-	 *
332
-	 * @param string $icon       The icon to prepend
333
-	 * @param array  $attributes Its attributes
334
-	 */
335
-	public function prependIcon($icon, $attributes = array(), $iconSettings = array())
336
-	{
337
-		$icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
338
-
339
-		$this->prepend($icon);
340
-	}
341
-
342
-	/**
343
-	 * Append an icon to a field
344
-	 *
345
-	 * @param string $icon       The icon to prepend
346
-	 * @param array  $attributes Its attributes
347
-	 */
348
-	public function appendIcon($icon, $attributes = array(), $iconSettings = array())
349
-	{
350
-		$icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
351
-
352
-		$this->append($icon);
353
-	}
354
-
355
-	////////////////////////////////////////////////////////////////////
356
-	//////////////////////////////// HELPERS ///////////////////////////
357
-	////////////////////////////////////////////////////////////////////
358
-
359
-	/**
360
-	 * Get the errors for the group
361
-	 *
362
-	 * @return string
363
-	 */
364
-	public function getErrors()
365
-	{
366
-		$errors = '';
367
-
368
-		if (!self::$opened) {
369
-
370
-			// for non-custom groups, normal error handling applies
371
-			$errors = $this->app['former']->getErrors();
372
-		} elseif (!empty($this->validations)) {
373
-
374
-			// error handling only when validations specified for custom groups
375
-			foreach ($this->validations as $validation) {
376
-				$errors .= $this->app['former']->getErrors($validation);
377
-			}
378
-		}
379
-
380
-		return $errors;
381
-	}
382
-
383
-	/**
384
-	 * Wraps content in a group
385
-	 *
386
-	 * @param string $contents The content
387
-	 * @param string $label    The label to add
388
-	 *
389
-	 * @return string A group
390
-	 */
391
-	public function wrap($contents, $label = null)
392
-	{
393
-		$group = $this->open();
394
-		$group .= $label;
395
-		$group .= $this->app['former.framework']->wrapField($contents);
396
-		$group .= $this->close();
397
-
398
-		return $group;
399
-	}
400
-
401
-	/**
402
-	 * Prints out the current label
403
-	 *
404
-	 * @param  string $field The field to create a label for
405
-	 *
406
-	 * @return string        A <label> tag
407
-	 */
408
-	protected function getLabel($field = null)
409
-	{
410
-		// Don't create a label if none exist
411
-		if (!$field or !$this->label) {
412
-			return null;
413
-		}
414
-
415
-		// Wrap label in framework classes
416
-		$this->label->addClass($this->app['former.framework']->getLabelClasses());
417
-		$this->label = $this->app['former.framework']->createLabelOf($field, $this->label);
418
-		$this->label = $this->app['former.framework']->wrapLabel($this->label);
419
-
420
-		return $this->label;
421
-	}
422
-
423
-	/**
424
-	 * Prints out the current help
425
-	 *
426
-	 * @return string A .help-block or .help-inline
427
-	 */
428
-	protected function getHelp()
429
-	{
430
-		$inline = array_get($this->help, 'inline');
431
-		$block  = array_get($this->help, 'block');
432
-
433
-		// Replace help text with error if any found
434
-		$errors = $this->app['former']->getErrors();
435
-		if ($errors and $this->app['former']->getOption('error_messages')) {
436
-			$inline = $this->app['former.framework']->createHelp($errors);
437
-		}
438
-
439
-		return join(null, array($inline, $block));
440
-	}
441
-
442
-	/**
443
-	 * Format the field with prepended/appended elements
444
-	 *
445
-	 * @param  \Former\Traits\Field $field The field to format
446
-	 *
447
-	 * @return string        Field plus supplementary elements
448
-	 */
449
-	protected function prependAppend($field)
450
-	{
451
-		if (!$this->prepend and !$this->append) {
452
-			return $field->render();
453
-		}
454
-
455
-		return $this->app['former.framework']->prependAppend($field, $this->prepend, $this->append);
456
-	}
457
-
458
-	/**
459
-	 * Place elements around the field
460
-	 *
461
-	 * @param  array  $items An array of items to place
462
-	 * @param  string $place Where they should end up (prepend|append)
463
-	 */
464
-	protected function placeAround($items, $place)
465
-	{
466
-		// Iterate over the items and place them where they should
467
-		foreach ((array) $items as $item) {
468
-			$item             = $this->app['former.framework']->placeAround($item);
469
-			$this->{$place}[] = $item;
470
-		}
471
-	}
15
+    /**
16
+     * The Container
17
+     *
18
+     * @var Container
19
+     */
20
+    protected $app;
21
+
22
+    /**
23
+     * The current state of the group
24
+     *
25
+     * @var string
26
+     */
27
+    protected $state = null;
28
+
29
+    /**
30
+     * Whether the field should be displayed raw or not
31
+     *
32
+     * @var boolean
33
+     */
34
+    protected $raw = false;
35
+
36
+    /**
37
+     * The group label
38
+     *
39
+     * @var Element
40
+     */
41
+    protected $label;
42
+
43
+    /**
44
+     * The group help
45
+     *
46
+     * @var array
47
+     */
48
+    protected $help = array();
49
+
50
+    /**
51
+     * An array of elements to preprend the field
52
+     *
53
+     * @var array
54
+     */
55
+    protected $prepend = array();
56
+
57
+    /**
58
+     * An array of elements to append the field
59
+     *
60
+     * @var array
61
+     */
62
+    protected $append = array();
63
+
64
+    /**
65
+     * The field validations to be checked for errors
66
+     *
67
+     * @var array
68
+     */
69
+    protected $validations = array();
70
+
71
+    /**
72
+     * The group's element
73
+     *
74
+     * @var string
75
+     */
76
+    protected $element = 'div';
77
+
78
+    /**
79
+     * Whether a custom group is opened or not
80
+     *
81
+     * @var boolean
82
+     */
83
+    public static $opened = false;
84
+
85
+    /**
86
+     * The custom group that is open
87
+     *
88
+     * @var Former\Form\Group
89
+     */
90
+    public static $openGroup = null;
91
+
92
+    ////////////////////////////////////////////////////////////////////
93
+    /////////////////////////// CORE METHODS ///////////////////////////
94
+    ////////////////////////////////////////////////////////////////////
95
+
96
+    /**
97
+     * Creates a group
98
+     *
99
+     * @param string $label Its label
100
+     */
101
+    public function __construct(Container $app, $label, $validations = null)
102
+    {
103
+        // Get special classes
104
+        $this->app = $app;
105
+        $this->addClass($this->app['former.framework']->getGroupClasses());
106
+
107
+        // Invisible if Nude
108
+        if ($this->app['former.framework']->is('Nude')) {
109
+            $this->element = '';
110
+        }
111
+
112
+        // Set group label
113
+        if ($label) {
114
+            $this->setLabel($label);
115
+        }
116
+
117
+        // Set validations used to override groups own conclusions
118
+        $this->validations = (array) $validations;
119
+    }
120
+
121
+    /**
122
+     * Prints out the opening of the Control Group
123
+     *
124
+     * @return string A control group opening tag
125
+     */
126
+    public function __toString()
127
+    {
128
+        return $this->open().$this->getFormattedLabel();
129
+    }
130
+
131
+    /**
132
+     * Opens a group
133
+     *
134
+     * @return string Opening tag
135
+     */
136
+    public function open()
137
+    {
138
+        if ($this->getErrors()) {
139
+            $this->state($this->app['former.framework']->errorState());
140
+        }
141
+
142
+        // Retrieve state and append it to classes
143
+        if ($this->state) {
144
+            $this->addClass($this->state);
145
+        }
146
+
147
+        // Required state
148
+        if ($this->app->bound('former.field') and $this->app['former.field']->isRequired()) {
149
+            $this->addClass($this->app['former']->getOption('required_class'));
150
+        }
151
+
152
+        return parent::open();
153
+    }
154
+
155
+    /**
156
+     * Set the contents of the current group
157
+     *
158
+     * @param string $contents The group contents
159
+     *
160
+     * @return string A group
161
+     */
162
+    public function contents($contents)
163
+    {
164
+        return $this->wrap($contents, $this->getFormattedLabel());
165
+    }
166
+
167
+    /**
168
+     * Wrap a Field with the current group
169
+     *
170
+     * @param  \Former\Traits\Field $field A Field instance
171
+     *
172
+     * @return string        A group
173
+     */
174
+    public function wrapField($field)
175
+    {
176
+        $label = $this->getLabel($field);
177
+        $field = $this->prependAppend($field);
178
+        $field .= $this->getHelp();
179
+
180
+        return $this->wrap($field, $label);
181
+    }
182
+
183
+    ////////////////////////////////////////////////////////////////////
184
+    //////////////////////////// FIELD METHODS /////////////////////////
185
+    ////////////////////////////////////////////////////////////////////
186
+
187
+    /**
188
+     * Set the state of the group
189
+     *
190
+     * @param  string $state A Bootstrap state class
191
+     */
192
+    public function state($state)
193
+    {
194
+        // Filter state
195
+        $state = $this->app['former.framework']->filterState($state);
196
+
197
+        $this->state = $state;
198
+    }
199
+
200
+    /**
201
+     * Set a class on the Group
202
+     *
203
+     * @param string $class The class to add
204
+     */
205
+    public function addGroupClass($class)
206
+    {
207
+        $this->addClass($class);
208
+    }
209
+
210
+    /**
211
+     * Adds a label to the group
212
+     *
213
+     * @param  string $label A label
214
+     */
215
+    public function setLabel($label)
216
+    {
217
+        if (!$label instanceof Element) {
218
+            $label = Helpers::translate($label);
219
+            $label = Element::create('label', $label)->for($label);
220
+        }
221
+
222
+        $this->label = $label;
223
+    }
224
+
225
+    /**
226
+     * Get the formatted group label
227
+     *
228
+     * @return string|null
229
+     */
230
+    public function getFormattedLabel()
231
+    {
232
+        if (!$this->label) {
233
+            return false;
234
+        }
235
+
236
+        return $this->label->addClass($this->app['former.framework']->getLabelClasses());
237
+    }
238
+
239
+    /**
240
+     * Disables the control group for the current field
241
+     */
242
+    public function raw()
243
+    {
244
+        $this->raw = true;
245
+    }
246
+
247
+    /**
248
+     * Check if the current group is to be displayed or not
249
+     *
250
+     * @return boolean
251
+     */
252
+    public function isRaw()
253
+    {
254
+        return (bool) $this->raw;
255
+    }
256
+
257
+    ////////////////////////////////////////////////////////////////////
258
+    ///////////////////////////// HELP BLOCKS //////////////////////////
259
+    ////////////////////////////////////////////////////////////////////
260
+
261
+    /**
262
+     * Alias for inlineHelp
263
+     *
264
+     * @param  string $help       The help text
265
+     * @param  array  $attributes Facultative attributes
266
+     */
267
+    public function help($help, $attributes = array())
268
+    {
269
+        return $this->inlineHelp($help, $attributes);
270
+    }
271
+
272
+    /**
273
+     * Add an inline help
274
+     *
275
+     * @param  string $help       The help text
276
+     * @param  array  $attributes Facultative attributes
277
+     */
278
+    public function inlineHelp($help, $attributes = array())
279
+    {
280
+        // If no help text, do nothing
281
+        if (!$help) {
282
+            return false;
283
+        }
284
+
285
+        $this->help['inline'] = $this->app['former.framework']->createHelp($help, $attributes);
286
+    }
287
+
288
+    /**
289
+     * Add an block help
290
+     *
291
+     * @param  string $help       The help text
292
+     * @param  array  $attributes Facultative attributes
293
+     */
294
+    public function blockHelp($help, $attributes = array())
295
+    {
296
+        // Reserved method
297
+        if ($this->app['former.framework']->isnt('TwitterBootstrap') && $this->app['former.framework']->isnt('TwitterBootstrap3')) {
298
+            throw new BadMethodCallException('This method is only available on the Bootstrap framework');
299
+        }
300
+
301
+        // If no help text, do nothing
302
+        if (!$help) {
303
+            return false;
304
+        }
305
+
306
+        $this->help['block'] = $this->app['former.framework']->createBlockHelp($help, $attributes);
307
+    }
308
+
309
+    ////////////////////////////////////////////////////////////////////
310
+    ///////////////////////// PREPEND/APPEND METHODS ///////////////////
311
+    ////////////////////////////////////////////////////////////////////
312
+
313
+    /**
314
+     * Prepend elements to the field
315
+     */
316
+    public function prepend()
317
+    {
318
+        $this->placeAround(func_get_args(), 'prepend');
319
+    }
320
+
321
+    /**
322
+     * Append elements to the field
323
+     */
324
+    public function append()
325
+    {
326
+        $this->placeAround(func_get_args(), 'append');
327
+    }
328
+
329
+    /**
330
+     * Prepends an icon to a field
331
+     *
332
+     * @param string $icon       The icon to prepend
333
+     * @param array  $attributes Its attributes
334
+     */
335
+    public function prependIcon($icon, $attributes = array(), $iconSettings = array())
336
+    {
337
+        $icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
338
+
339
+        $this->prepend($icon);
340
+    }
341
+
342
+    /**
343
+     * Append an icon to a field
344
+     *
345
+     * @param string $icon       The icon to prepend
346
+     * @param array  $attributes Its attributes
347
+     */
348
+    public function appendIcon($icon, $attributes = array(), $iconSettings = array())
349
+    {
350
+        $icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
351
+
352
+        $this->append($icon);
353
+    }
354
+
355
+    ////////////////////////////////////////////////////////////////////
356
+    //////////////////////////////// HELPERS ///////////////////////////
357
+    ////////////////////////////////////////////////////////////////////
358
+
359
+    /**
360
+     * Get the errors for the group
361
+     *
362
+     * @return string
363
+     */
364
+    public function getErrors()
365
+    {
366
+        $errors = '';
367
+
368
+        if (!self::$opened) {
369
+
370
+            // for non-custom groups, normal error handling applies
371
+            $errors = $this->app['former']->getErrors();
372
+        } elseif (!empty($this->validations)) {
373
+
374
+            // error handling only when validations specified for custom groups
375
+            foreach ($this->validations as $validation) {
376
+                $errors .= $this->app['former']->getErrors($validation);
377
+            }
378
+        }
379
+
380
+        return $errors;
381
+    }
382
+
383
+    /**
384
+     * Wraps content in a group
385
+     *
386
+     * @param string $contents The content
387
+     * @param string $label    The label to add
388
+     *
389
+     * @return string A group
390
+     */
391
+    public function wrap($contents, $label = null)
392
+    {
393
+        $group = $this->open();
394
+        $group .= $label;
395
+        $group .= $this->app['former.framework']->wrapField($contents);
396
+        $group .= $this->close();
397
+
398
+        return $group;
399
+    }
400
+
401
+    /**
402
+     * Prints out the current label
403
+     *
404
+     * @param  string $field The field to create a label for
405
+     *
406
+     * @return string        A <label> tag
407
+     */
408
+    protected function getLabel($field = null)
409
+    {
410
+        // Don't create a label if none exist
411
+        if (!$field or !$this->label) {
412
+            return null;
413
+        }
414
+
415
+        // Wrap label in framework classes
416
+        $this->label->addClass($this->app['former.framework']->getLabelClasses());
417
+        $this->label = $this->app['former.framework']->createLabelOf($field, $this->label);
418
+        $this->label = $this->app['former.framework']->wrapLabel($this->label);
419
+
420
+        return $this->label;
421
+    }
422
+
423
+    /**
424
+     * Prints out the current help
425
+     *
426
+     * @return string A .help-block or .help-inline
427
+     */
428
+    protected function getHelp()
429
+    {
430
+        $inline = array_get($this->help, 'inline');
431
+        $block  = array_get($this->help, 'block');
432
+
433
+        // Replace help text with error if any found
434
+        $errors = $this->app['former']->getErrors();
435
+        if ($errors and $this->app['former']->getOption('error_messages')) {
436
+            $inline = $this->app['former.framework']->createHelp($errors);
437
+        }
438
+
439
+        return join(null, array($inline, $block));
440
+    }
441
+
442
+    /**
443
+     * Format the field with prepended/appended elements
444
+     *
445
+     * @param  \Former\Traits\Field $field The field to format
446
+     *
447
+     * @return string        Field plus supplementary elements
448
+     */
449
+    protected function prependAppend($field)
450
+    {
451
+        if (!$this->prepend and !$this->append) {
452
+            return $field->render();
453
+        }
454
+
455
+        return $this->app['former.framework']->prependAppend($field, $this->prepend, $this->append);
456
+    }
457
+
458
+    /**
459
+     * Place elements around the field
460
+     *
461
+     * @param  array  $items An array of items to place
462
+     * @param  string $place Where they should end up (prepend|append)
463
+     */
464
+    protected function placeAround($items, $place)
465
+    {
466
+        // Iterate over the items and place them where they should
467
+        foreach ((array) $items as $item) {
468
+            $item             = $this->app['former.framework']->placeAround($item);
469
+            $this->{$place}[] = $item;
470
+        }
471
+    }
472 472
 }
Please login to merge, or discard this patch.
src/Former/Form/Form.php 1 patch
Indentation   +403 added lines, -403 removed lines patch added patch discarded remove patch
@@ -11,407 +11,407 @@
 block discarded – undo
11 11
  */
12 12
 class Form extends FormerObject
13 13
 {
14
-	/**
15
-	 * The IoC Container
16
-	 *
17
-	 * @var Container
18
-	 */
19
-	protected $app;
20
-
21
-	/**
22
-	 * The URL generator
23
-	 *
24
-	 * @var UrlGenerator
25
-	 */
26
-	protected $url;
27
-
28
-	/**
29
-	 * The Populator
30
-	 *
31
-	 * @var Populator
32
-	 */
33
-	protected $populator;
34
-
35
-	/**
36
-	 * The Form type
37
-	 *
38
-	 * @var string
39
-	 */
40
-	protected $type = null;
41
-
42
-	/**
43
-	 * The destination of the current form
44
-	 *
45
-	 * @var string
46
-	 */
47
-	protected $action;
48
-
49
-	/**
50
-	 * The form method
51
-	 *
52
-	 * @var string
53
-	 */
54
-	protected $method;
55
-
56
-	/**
57
-	 * Whether the form should be secured or not
58
-	 *
59
-	 * @var boolean
60
-	 */
61
-	protected $secure;
62
-
63
-	/**
64
-	 * The form element
65
-	 *
66
-	 * @var string
67
-	 */
68
-	protected $element = 'form';
69
-
70
-	/**
71
-	 * A list of injected properties
72
-	 *
73
-	 * @var array
74
-	 */
75
-	protected $injectedProperties = array('method', 'action');
76
-
77
-	/**
78
-	 * Whether a form is opened or not
79
-	 *
80
-	 * @var boolean
81
-	 */
82
-	protected static $opened = false;
83
-
84
-	////////////////////////////////////////////////////////////////////
85
-	/////////////////////////// CORE METHODS ///////////////////////////
86
-	////////////////////////////////////////////////////////////////////
87
-
88
-	/**
89
-	 * Build a new Form instance
90
-	 *
91
-	 * @param UrlGenerator $url
92
-	 */
93
-	public function __construct(Container $app, $url, Populator $populator)
94
-	{
95
-		$this->app       = $app;
96
-		$this->url       = $url;
97
-		$this->populator = $populator;
98
-
99
-		$this->app->singleton('former.form.framework', function($app) {
100
-			return clone $app['former.framework'];
101
-		});
102
-	}
103
-
104
-	/**
105
-	 * Opens up magically a form
106
-	 *
107
-	 * @param  string $type       The form type asked
108
-	 * @param  array  $parameters Parameters passed
109
-	 *
110
-	 * @return Form             A form opening tag
111
-	 */
112
-	public function openForm($type, $parameters)
113
-	{
114
-		$action     = array_get($parameters, 0);
115
-		$method     = array_get($parameters, 1, 'POST');
116
-		$attributes = array_get($parameters, 2, array());
117
-		$secure     = array_get($parameters, 3, null);
118
-
119
-		// Fetch errors if asked for
120
-		if ($this->app['former']->getOption('fetch_errors')) {
121
-			$this->app['former']->withErrors();
122
-		}
123
-
124
-		// Open the form
125
-		$this->action($action);
126
-		$this->attributes = $attributes;
127
-		$this->method     = strtoupper($method);
128
-		$this->secure     = $secure;
129
-
130
-		// Add any effect of the form type
131
-		$type       = Str::snake($type);
132
-		$this->type = $this->applyType($type);
133
-
134
-		// Add enctype
135
-		if (!array_key_exists('accept-charset', $attributes)) {
136
-			$this->attributes['accept-charset'] = 'utf-8';
137
-		}
138
-
139
-		// Add supplementary classes
140
-		if ($this->type !== 'raw') {
141
-			$this->addClass($this->app['former.form.framework']->getFormClasses($this->type));
142
-		}
143
-
144
-		return $this;
145
-	}
146
-
147
-	/**
148
-	 * Closes a Form
149
-	 *
150
-	 * @return string A closing <form> tag
151
-	 */
152
-	public function close()
153
-	{
154
-		static::$opened = false;
155
-
156
-		// Add token if necessary
157
-		$closing = '</form>';
158
-		if ($this->method != 'GET') {
159
-			$closing = $this->app['former']->token().$closing;
160
-		}
161
-
162
-		return $closing;
163
-	}
164
-
165
-	////////////////////////////////////////////////////////////////////
166
-	//////////////////////////// STATIC HELPERS ////////////////////////
167
-	////////////////////////////////////////////////////////////////////
168
-
169
-	/**
170
-	 * Whether a form is currently opened or not
171
-	 *
172
-	 * @return boolean
173
-	 */
174
-	public static function hasInstanceOpened()
175
-	{
176
-		return static::$opened;
177
-	}
178
-
179
-	////////////////////////////////////////////////////////////////////
180
-	/////////////////////////////// SETTER /////////////////////////////
181
-	////////////////////////////////////////////////////////////////////
182
-
183
-	/**
184
-	 * Change the form's action
185
-	 *
186
-	 * @param  string $action The new action
187
-	 *
188
-	 * @return $this
189
-	 */
190
-	public function action($action)
191
-	{
192
-		$this->action = $action ? $this->url->to($action, array(), $this->secure) : null;
193
-
194
-		return $this;
195
-	}
196
-
197
-	/**
198
-	 * Change the form's method
199
-	 *
200
-	 * @param  string $method The method to use
201
-	 *
202
-	 * @return $this
203
-	 */
204
-	public function method($method)
205
-	{
206
-		$this->method = strtoupper($method);
207
-
208
-		return $this;
209
-	}
210
-
211
-	/**
212
-	 * Whether the form should be secure
213
-	 *
214
-	 * @param  boolean $secure Secure or not
215
-	 *
216
-	 * @return $this
217
-	 */
218
-	public function secure($secure = true)
219
-	{
220
-		$this->secure = $secure;
221
-
222
-		return $this;
223
-	}
224
-
225
-	/**
226
-	 * Change the form's action and method to a route
227
-	 *
228
-	 * @param  string $name   The name of the route to use
229
-	 * @param  array  $params Any route parameters
230
-	 *
231
-	 * @return Form
232
-	 */
233
-	public function route($name, $params = array())
234
-	{
235
-		return $this->setRouteOrAction($name, $params, 'route');
236
-	}
237
-
238
-	/**
239
-	 * Change the form's action to a controller method
240
-	 *
241
-	 * @param  string $name   The controller and method
242
-	 * @param  array  $params Any method parameters
243
-	 *
244
-	 * @return Form
245
-	 */
246
-	public function controller($name, $params = array())
247
-	{
248
-		return $this->setRouteOrAction($name, $params, 'action');
249
-	}
250
-
251
-	/**
252
-	 * Outputs the current form opened
253
-	 *
254
-	 * @return string A <form> opening tag
255
-	 */
256
-	public function __toString()
257
-	{
258
-		// Mark the form as opened
259
-		static::$opened = true;
260
-
261
-		// Add name to attributes
262
-		$this->attributes['name'] = $this->name;
263
-
264
-		// Add spoof method
265
-		if (in_array($this->method, array('PUT', 'PATCH', 'DELETE'))) {
266
-			$spoof        = $this->app['former']->hidden('_method', $this->method);
267
-			$this->method = 'POST';
268
-		} else {
269
-			$spoof = null;
270
-		}
271
-
272
-		return $this->open().$spoof;
273
-	}
274
-
275
-	////////////////////////////////////////////////////////////////////
276
-	////////////////////////// PUBLIC HELPERS //////////////////////////
277
-	////////////////////////////////////////////////////////////////////
278
-
279
-	/**
280
-	 * Alias for $this->app['former']->withRules
281
-	 */
282
-	public function rules()
283
-	{
284
-		call_user_func_array(array($this->app['former'], 'withRules'), func_get_args());
285
-
286
-		return $this;
287
-	}
288
-
289
-	/**
290
-	 * Populate a form with specific values
291
-	 *
292
-	 * @param array|object $values
293
-	 *
294
-	 * @return $this
295
-	 */
296
-	public function populate($values)
297
-	{
298
-		$this->populator->replace($values);
299
-
300
-		return $this;
301
-	}
302
-
303
-	/**
304
-	 * Get the Populator binded to the Form
305
-	 *
306
-	 * @return Populator
307
-	 */
308
-	public function getPopulator()
309
-	{
310
-		return $this->populator;
311
-	}
312
-
313
-	////////////////////////////////////////////////////////////////////
314
-	////////////////////////////// HELPERS /////////////////////////////
315
-	////////////////////////////////////////////////////////////////////
316
-
317
-	/**
318
-	 * Find the method of a route by its _uses or name
319
-	 *
320
-	 * @param  string $name
321
-	 *
322
-	 * @return string
323
-	 */
324
-	protected function findRouteMethod($name)
325
-	{
326
-		if (!$this->app->bound('router')) {
327
-			return;
328
-		}
329
-
330
-		// Get string by name
331
-		if (!Str::contains($name, '@')) {
332
-			$routes = $this->app['router']->getRoutes();
333
-			$route  = method_exists($routes, 'getByName') ? $routes->getByName($name) : $routes->get($name);
334
-			// Get string by uses
335
-		} else {
336
-			foreach ($this->app['router']->getRoutes() as $route) {
337
-				$routeUses = method_exists($route, 'getOption') ? $route->getOption('_uses') : array_get($route->getAction(), 'controller');
338
-				if ($action = $routeUses) {
339
-					if ($action == $name) {
340
-						break;
341
-					}
342
-				}
343
-			}
344
-		}
345
-
346
-		// Get method
347
-		$methods = method_exists($route, 'getMethods') ? $route->getMethods() : $route->methods();
348
-		$method  = array_get($methods, 0);
349
-
350
-		return $method;
351
-	}
352
-
353
-	/**
354
-	 * @param string $name
355
-	 * @param $params
356
-	 * @param string $type
357
-	 *
358
-	 * @return $this
359
-	 */
360
-	protected function setRouteOrAction($name, $params, $type)
361
-	{
362
-		// Set the form action
363
-		$this->action = $this->url->$type($name, $params);
364
-
365
-		// Set the proper method
366
-		if ($method = $this->findRouteMethod($name)) {
367
-			$this->method($method);
368
-		}
369
-
370
-		return $this;
371
-	}
372
-
373
-	/**
374
-	 * Apply various parameters according to form type
375
-	 *
376
-	 * @param  string $type The original form type provided
377
-	 *
378
-	 * @return string The final form type
379
-	 */
380
-	private function applyType($type)
381
-	{
382
-		// If classic form
383
-		if ($type == 'open') {
384
-			return $this->app['former']->getOption('default_form_type');
385
-		}
386
-
387
-		// Look for HTTPS form
388
-		if (Str::contains($type, 'secure')) {
389
-			$type         = str_replace('secure', '', $type);
390
-			$this->secure = true;
391
-		}
392
-
393
-		// Look for file form
394
-		if (Str::contains($type, 'for_files')) {
395
-			$type                        = str_replace('for_files', '', $type);
396
-			$this->attributes['enctype'] = 'multipart/form-data';
397
-		}
398
-
399
-		// Calculate form type
400
-		$type = str_replace('open', '', $type);
401
-		$type = trim($type, '_');
402
-
403
-		// If raw form
404
-		if ($type == 'raw') {
405
-			$this->app->bind('former.form.framework', function($app) {
406
-				return $app['former']->getFrameworkInstance('Nude');
407
-			});
408
-		}
409
-
410
-		// Use default form type if the one provided is invalid
411
-		if ($type !== 'raw' and !in_array($type, $this->app['former.form.framework']->availableTypes())) {
412
-			$type = $this->app['former']->getOption('default_form_type');
413
-		}
414
-
415
-		return $type;
416
-	}
14
+    /**
15
+     * The IoC Container
16
+     *
17
+     * @var Container
18
+     */
19
+    protected $app;
20
+
21
+    /**
22
+     * The URL generator
23
+     *
24
+     * @var UrlGenerator
25
+     */
26
+    protected $url;
27
+
28
+    /**
29
+     * The Populator
30
+     *
31
+     * @var Populator
32
+     */
33
+    protected $populator;
34
+
35
+    /**
36
+     * The Form type
37
+     *
38
+     * @var string
39
+     */
40
+    protected $type = null;
41
+
42
+    /**
43
+     * The destination of the current form
44
+     *
45
+     * @var string
46
+     */
47
+    protected $action;
48
+
49
+    /**
50
+     * The form method
51
+     *
52
+     * @var string
53
+     */
54
+    protected $method;
55
+
56
+    /**
57
+     * Whether the form should be secured or not
58
+     *
59
+     * @var boolean
60
+     */
61
+    protected $secure;
62
+
63
+    /**
64
+     * The form element
65
+     *
66
+     * @var string
67
+     */
68
+    protected $element = 'form';
69
+
70
+    /**
71
+     * A list of injected properties
72
+     *
73
+     * @var array
74
+     */
75
+    protected $injectedProperties = array('method', 'action');
76
+
77
+    /**
78
+     * Whether a form is opened or not
79
+     *
80
+     * @var boolean
81
+     */
82
+    protected static $opened = false;
83
+
84
+    ////////////////////////////////////////////////////////////////////
85
+    /////////////////////////// CORE METHODS ///////////////////////////
86
+    ////////////////////////////////////////////////////////////////////
87
+
88
+    /**
89
+     * Build a new Form instance
90
+     *
91
+     * @param UrlGenerator $url
92
+     */
93
+    public function __construct(Container $app, $url, Populator $populator)
94
+    {
95
+        $this->app       = $app;
96
+        $this->url       = $url;
97
+        $this->populator = $populator;
98
+
99
+        $this->app->singleton('former.form.framework', function($app) {
100
+            return clone $app['former.framework'];
101
+        });
102
+    }
103
+
104
+    /**
105
+     * Opens up magically a form
106
+     *
107
+     * @param  string $type       The form type asked
108
+     * @param  array  $parameters Parameters passed
109
+     *
110
+     * @return Form             A form opening tag
111
+     */
112
+    public function openForm($type, $parameters)
113
+    {
114
+        $action     = array_get($parameters, 0);
115
+        $method     = array_get($parameters, 1, 'POST');
116
+        $attributes = array_get($parameters, 2, array());
117
+        $secure     = array_get($parameters, 3, null);
118
+
119
+        // Fetch errors if asked for
120
+        if ($this->app['former']->getOption('fetch_errors')) {
121
+            $this->app['former']->withErrors();
122
+        }
123
+
124
+        // Open the form
125
+        $this->action($action);
126
+        $this->attributes = $attributes;
127
+        $this->method     = strtoupper($method);
128
+        $this->secure     = $secure;
129
+
130
+        // Add any effect of the form type
131
+        $type       = Str::snake($type);
132
+        $this->type = $this->applyType($type);
133
+
134
+        // Add enctype
135
+        if (!array_key_exists('accept-charset', $attributes)) {
136
+            $this->attributes['accept-charset'] = 'utf-8';
137
+        }
138
+
139
+        // Add supplementary classes
140
+        if ($this->type !== 'raw') {
141
+            $this->addClass($this->app['former.form.framework']->getFormClasses($this->type));
142
+        }
143
+
144
+        return $this;
145
+    }
146
+
147
+    /**
148
+     * Closes a Form
149
+     *
150
+     * @return string A closing <form> tag
151
+     */
152
+    public function close()
153
+    {
154
+        static::$opened = false;
155
+
156
+        // Add token if necessary
157
+        $closing = '</form>';
158
+        if ($this->method != 'GET') {
159
+            $closing = $this->app['former']->token().$closing;
160
+        }
161
+
162
+        return $closing;
163
+    }
164
+
165
+    ////////////////////////////////////////////////////////////////////
166
+    //////////////////////////// STATIC HELPERS ////////////////////////
167
+    ////////////////////////////////////////////////////////////////////
168
+
169
+    /**
170
+     * Whether a form is currently opened or not
171
+     *
172
+     * @return boolean
173
+     */
174
+    public static function hasInstanceOpened()
175
+    {
176
+        return static::$opened;
177
+    }
178
+
179
+    ////////////////////////////////////////////////////////////////////
180
+    /////////////////////////////// SETTER /////////////////////////////
181
+    ////////////////////////////////////////////////////////////////////
182
+
183
+    /**
184
+     * Change the form's action
185
+     *
186
+     * @param  string $action The new action
187
+     *
188
+     * @return $this
189
+     */
190
+    public function action($action)
191
+    {
192
+        $this->action = $action ? $this->url->to($action, array(), $this->secure) : null;
193
+
194
+        return $this;
195
+    }
196
+
197
+    /**
198
+     * Change the form's method
199
+     *
200
+     * @param  string $method The method to use
201
+     *
202
+     * @return $this
203
+     */
204
+    public function method($method)
205
+    {
206
+        $this->method = strtoupper($method);
207
+
208
+        return $this;
209
+    }
210
+
211
+    /**
212
+     * Whether the form should be secure
213
+     *
214
+     * @param  boolean $secure Secure or not
215
+     *
216
+     * @return $this
217
+     */
218
+    public function secure($secure = true)
219
+    {
220
+        $this->secure = $secure;
221
+
222
+        return $this;
223
+    }
224
+
225
+    /**
226
+     * Change the form's action and method to a route
227
+     *
228
+     * @param  string $name   The name of the route to use
229
+     * @param  array  $params Any route parameters
230
+     *
231
+     * @return Form
232
+     */
233
+    public function route($name, $params = array())
234
+    {
235
+        return $this->setRouteOrAction($name, $params, 'route');
236
+    }
237
+
238
+    /**
239
+     * Change the form's action to a controller method
240
+     *
241
+     * @param  string $name   The controller and method
242
+     * @param  array  $params Any method parameters
243
+     *
244
+     * @return Form
245
+     */
246
+    public function controller($name, $params = array())
247
+    {
248
+        return $this->setRouteOrAction($name, $params, 'action');
249
+    }
250
+
251
+    /**
252
+     * Outputs the current form opened
253
+     *
254
+     * @return string A <form> opening tag
255
+     */
256
+    public function __toString()
257
+    {
258
+        // Mark the form as opened
259
+        static::$opened = true;
260
+
261
+        // Add name to attributes
262
+        $this->attributes['name'] = $this->name;
263
+
264
+        // Add spoof method
265
+        if (in_array($this->method, array('PUT', 'PATCH', 'DELETE'))) {
266
+            $spoof        = $this->app['former']->hidden('_method', $this->method);
267
+            $this->method = 'POST';
268
+        } else {
269
+            $spoof = null;
270
+        }
271
+
272
+        return $this->open().$spoof;
273
+    }
274
+
275
+    ////////////////////////////////////////////////////////////////////
276
+    ////////////////////////// PUBLIC HELPERS //////////////////////////
277
+    ////////////////////////////////////////////////////////////////////
278
+
279
+    /**
280
+     * Alias for $this->app['former']->withRules
281
+     */
282
+    public function rules()
283
+    {
284
+        call_user_func_array(array($this->app['former'], 'withRules'), func_get_args());
285
+
286
+        return $this;
287
+    }
288
+
289
+    /**
290
+     * Populate a form with specific values
291
+     *
292
+     * @param array|object $values
293
+     *
294
+     * @return $this
295
+     */
296
+    public function populate($values)
297
+    {
298
+        $this->populator->replace($values);
299
+
300
+        return $this;
301
+    }
302
+
303
+    /**
304
+     * Get the Populator binded to the Form
305
+     *
306
+     * @return Populator
307
+     */
308
+    public function getPopulator()
309
+    {
310
+        return $this->populator;
311
+    }
312
+
313
+    ////////////////////////////////////////////////////////////////////
314
+    ////////////////////////////// HELPERS /////////////////////////////
315
+    ////////////////////////////////////////////////////////////////////
316
+
317
+    /**
318
+     * Find the method of a route by its _uses or name
319
+     *
320
+     * @param  string $name
321
+     *
322
+     * @return string
323
+     */
324
+    protected function findRouteMethod($name)
325
+    {
326
+        if (!$this->app->bound('router')) {
327
+            return;
328
+        }
329
+
330
+        // Get string by name
331
+        if (!Str::contains($name, '@')) {
332
+            $routes = $this->app['router']->getRoutes();
333
+            $route  = method_exists($routes, 'getByName') ? $routes->getByName($name) : $routes->get($name);
334
+            // Get string by uses
335
+        } else {
336
+            foreach ($this->app['router']->getRoutes() as $route) {
337
+                $routeUses = method_exists($route, 'getOption') ? $route->getOption('_uses') : array_get($route->getAction(), 'controller');
338
+                if ($action = $routeUses) {
339
+                    if ($action == $name) {
340
+                        break;
341
+                    }
342
+                }
343
+            }
344
+        }
345
+
346
+        // Get method
347
+        $methods = method_exists($route, 'getMethods') ? $route->getMethods() : $route->methods();
348
+        $method  = array_get($methods, 0);
349
+
350
+        return $method;
351
+    }
352
+
353
+    /**
354
+     * @param string $name
355
+     * @param $params
356
+     * @param string $type
357
+     *
358
+     * @return $this
359
+     */
360
+    protected function setRouteOrAction($name, $params, $type)
361
+    {
362
+        // Set the form action
363
+        $this->action = $this->url->$type($name, $params);
364
+
365
+        // Set the proper method
366
+        if ($method = $this->findRouteMethod($name)) {
367
+            $this->method($method);
368
+        }
369
+
370
+        return $this;
371
+    }
372
+
373
+    /**
374
+     * Apply various parameters according to form type
375
+     *
376
+     * @param  string $type The original form type provided
377
+     *
378
+     * @return string The final form type
379
+     */
380
+    private function applyType($type)
381
+    {
382
+        // If classic form
383
+        if ($type == 'open') {
384
+            return $this->app['former']->getOption('default_form_type');
385
+        }
386
+
387
+        // Look for HTTPS form
388
+        if (Str::contains($type, 'secure')) {
389
+            $type         = str_replace('secure', '', $type);
390
+            $this->secure = true;
391
+        }
392
+
393
+        // Look for file form
394
+        if (Str::contains($type, 'for_files')) {
395
+            $type                        = str_replace('for_files', '', $type);
396
+            $this->attributes['enctype'] = 'multipart/form-data';
397
+        }
398
+
399
+        // Calculate form type
400
+        $type = str_replace('open', '', $type);
401
+        $type = trim($type, '_');
402
+
403
+        // If raw form
404
+        if ($type == 'raw') {
405
+            $this->app->bind('former.form.framework', function($app) {
406
+                return $app['former']->getFrameworkInstance('Nude');
407
+            });
408
+        }
409
+
410
+        // Use default form type if the one provided is invalid
411
+        if ($type !== 'raw' and !in_array($type, $this->app['former.form.framework']->availableTypes())) {
412
+            $type = $this->app['former']->getOption('default_form_type');
413
+        }
414
+
415
+        return $type;
416
+    }
417 417
 }
Please login to merge, or discard this patch.