Completed
Push — master ( 94378a...9f919b )
by Ben
01:25
created
src/Former/Traits/Checkable.php 1 patch
Indentation   +556 added lines, -556 removed lines patch added patch discarded remove patch
@@ -14,560 +14,560 @@
 block discarded – undo
14 14
  */
15 15
 abstract class Checkable extends Field
16 16
 {
17
-	/**
18
-	 * Renders the checkables as inline
19
-	 *
20
-	 * @var boolean
21
-	 */
22
-	protected $inline = false;
23
-
24
-	/**
25
-	 * Add a text to a single element
26
-	 *
27
-	 * @var string
28
-	 */
29
-	protected $text = null;
30
-
31
-	/**
32
-	 * Renders the checkables as grouped
33
-	 *
34
-	 * @var boolean
35
-	 */
36
-	protected $grouped = false;
37
-
38
-	/**
39
-	 * The checkable items currently stored
40
-	 *
41
-	 * @var array
42
-	 */
43
-	protected $items = array();
44
-
45
-	/**
46
-	 * The type of checkable item
47
-	 *
48
-	 * @var string
49
-	 */
50
-	protected $checkable = null;
51
-
52
-	/**
53
-	 * An array of checked items
54
-	 *
55
-	 * @var array
56
-	 */
57
-	protected $checked = array();
58
-
59
-	/**
60
-	 * The checkable currently being focused on
61
-	 *
62
-	 * @var integer
63
-	 */
64
-	protected $focus = null;
65
-
66
-	/**
67
-	 * Whether this particular checkable is to be pushed
68
-	 *
69
-	 * @var boolean
70
-	 */
71
-	protected $isPushed = null;
72
-
73
-	////////////////////////////////////////////////////////////////////
74
-	//////////////////////////// CORE METHODS //////////////////////////
75
-	////////////////////////////////////////////////////////////////////
76
-
77
-	/**
78
-	 * Build a new checkable
79
-	 *
80
-	 * @param Container $app
81
-	 * @param string    $type
82
-	 * @param array     $name
83
-	 * @param           $label
84
-	 * @param           $value
85
-	 * @param           $attributes
86
-	 */
87
-	public function __construct(Container $app, $type, $name, $label, $value, $attributes)
88
-	{
89
-		// Unify auto and chained methods of grouping checkboxes
90
-		if (Str::endsWith($name, '[]')) {
91
-			$name = substr($name, 0, -2);
92
-			$this->grouped();
93
-		}
94
-		parent::__construct($app, $type, $name, $label, $value, $attributes);
95
-
96
-		if (is_array($this->value)) {
97
-			$this->items($this->value);
98
-		}
99
-	}
100
-
101
-	/**
102
-	 * Apply methods to focused checkable
103
-	 *
104
-	 * @param string $method
105
-	 * @param array  $parameters
106
-	 *
107
-	 * @return $this
108
-	 */
109
-	public function __call($method, $parameters)
110
-	{
111
-		$focused = $this->setOnFocused('attributes.'.$method, Arr::get($parameters, 0));
112
-		if ($focused) {
113
-			return $this;
114
-		}
115
-
116
-		return parent::__call($method, $parameters);
117
-	}
118
-
119
-	/**
120
-	 * Prints out the currently stored checkables
121
-	 */
122
-	public function render()
123
-	{
124
-		$html = null;
125
-
126
-		$this->setFieldClasses();
127
-
128
-		// Multiple items
129
-		if ($this->items) {
130
-			unset($this->app['former']->labels[array_search($this->name, $this->app['former']->labels)]);
131
-			foreach ($this->items as $key => $item) {
132
-				$value = $this->isCheckbox() && !$this->isGrouped() ? 1 : $key;
133
-				$html .= $this->createCheckable($item, $value);
134
-			}
135
-
136
-			return $html;
137
-		}
138
-
139
-		// Single item
140
-		return $this->createCheckable(array(
141
-			'name'  => $this->name,
142
-			'label' => $this->text,
143
-			'value' => $this->value,
144
-			'attributes' => $this->attributes,
145
-		));
146
-	}
147
-
148
-	////////////////////////////////////////////////////////////////////
149
-	////////////////////////// FIELD METHODS ///////////////////////////
150
-	////////////////////////////////////////////////////////////////////
151
-
152
-	/**
153
-	 * Focus on a particular checkable
154
-	 *
155
-	 * @param integer $on The checkable to focus on
156
-	 *
157
-	 * @return $this
158
-	 */
159
-	public function on($on)
160
-	{
161
-		if (!isset($this->items[$on])) {
162
-			return $this;
163
-		} else {
164
-			$this->focus = $on;
165
-		}
166
-
167
-		return $this;
168
-	}
169
-
170
-	/**
171
-	 * Set the checkables as inline
172
-	 */
173
-	public function inline($isInline = true)
174
-	{
175
-		$this->inline = $isInline;
176
-
177
-		return $this;
178
-	}
179
-
180
-	/**
181
-	 * Set the checkables as stacked
182
-	 */
183
-	public function stacked($isStacked = true)
184
-	{
185
-		$this->inline = !$isStacked;
186
-
187
-		return $this;
188
-	}
189
-
190
-	/**
191
-	 * Set the checkables as grouped
192
-	 */
193
-	public function grouped($isGrouped = true)
194
-	{
195
-		$this->grouped = $isGrouped;
196
-
197
-		return $this;
198
-	}
199
-
200
-	/**
201
-	 * Add text to a single checkable
202
-	 *
203
-	 * @param  string $text The checkable label
204
-	 *
205
-	 * @return $this
206
-	 */
207
-	public function text($text)
208
-	{
209
-		// Translate and format
210
-		$text = Helpers::translate($text);
211
-
212
-		// Apply on focused if any
213
-		$focused = $this->setOnFocused('label', $text);
214
-		if ($focused) {
215
-			return $this;
216
-		}
217
-
218
-		$this->text = $text;
219
-
220
-		return $this;
221
-	}
222
-
223
-	/**
224
-	 * Push this particular checkbox
225
-	 *
226
-	 * @param boolean $pushed
227
-	 *
228
-	 * @return $this
229
-	 */
230
-	public function push($pushed = true)
231
-	{
232
-		$this->isPushed = $pushed;
233
-
234
-		return $this;
235
-	}
236
-
237
-	/**
238
-	 * Check a specific item
239
-	 *
240
-	 * @param bool|string $checked The checkable to check, or an array of checked items
241
-	 *
242
-	 * @return $this
243
-	 */
244
-	public function check($checked = true)
245
-	{
246
-		// If we're setting all the checked items at once
247
-		if (is_array($checked)) {
248
-			$this->checked = $checked;
249
-			// Checking an item in particular
250
-		} elseif (is_string($checked) or is_int($checked)) {
251
-			$this->checked[$checked] = true;
252
-			// Only setting a single item
253
-		} else {
254
-			$this->checked[$this->name] = (bool) $checked;
255
-		}
256
-
257
-		return $this;
258
-	}
259
-
260
-	////////////////////////////////////////////////////////////////////
261
-	////////////////////////// INTERNAL METHODS ////////////////////////
262
-	////////////////////////////////////////////////////////////////////
263
-
264
-	/**
265
-	 * Creates a series of checkable items
266
-	 *
267
-	 * @param array $_items Items to create
268
-	 */
269
-	protected function items($_items)
270
-	{
271
-		// If passing an array
272
-		if (sizeof($_items) == 1 and
273
-			isset($_items[0]) and
274
-			is_array($_items[0])
275
-		) {
276
-			$_items = $_items[0];
277
-		}
278
-
279
-		// Fetch models if that's what we were passed
280
-		if (isset($_items[0]) and is_object($_items[0])) {
281
-			$_items = Helpers::queryToArray($_items);
282
-			$_items = array_flip($_items);
283
-		}
284
-
285
-		// Iterate through items, assign a name and a label to each
286
-		$count = 0;
287
-		foreach ($_items as $label => $name) {
288
-
289
-			// Define a fallback name in case none is found
290
-			$fallback = $this->isCheckbox()
291
-				? $this->name.'_'.$count
292
-				: $this->name;
293
-
294
-			// Grouped fields
295
-			if ($this->isGrouped()) {
296
-				$attributes['id'] = str_replace('[]', null, $fallback);
297
-				$fallback         = str_replace('[]', null, $this->name).'[]';
298
-			}
299
-
300
-			// If we haven't any name defined for the checkable, try to compute some
301
-			if (!is_string($label) and !is_array($name)) {
302
-				$label = $name;
303
-				$name  = $fallback;
304
-			}
305
-
306
-			// If we gave custom information on the item, add them
307
-			if (is_array($name)) {
308
-				$attributes = $name;
309
-				$name       = Arr::get($attributes, 'name', $fallback);
310
-				unset($attributes['name']);
311
-			}
312
-
313
-			// Store all informations we have in an array
314
-			$item = array(
315
-				'name'  => $name,
316
-				'label' => Helpers::translate($label),
317
-				'count' => $count,
318
-			);
319
-			if (isset($attributes)) {
320
-				$item['attributes'] = $attributes;
321
-			}
322
-
323
-			$this->items[] = $item;
324
-			$count++;
325
-		}
326
-	}
327
-
328
-	/**
329
-	 * Renders a checkable
330
-	 *
331
-	 * @param string|array $item          A checkable item
332
-	 * @param integer      $fallbackValue A fallback value if none is set
333
-	 *
334
-	 * @return string
335
-	 */
336
-	protected function createCheckable($item, $fallbackValue = 1)
337
-	{
338
-		// Extract informations
339
-		extract($item);
340
-
341
-		// Set default values
342
-		if (!isset($attributes)) {
343
-			$attributes = array();
344
-		}
345
-		if (isset($attributes['value'])) {
346
-			$value = $attributes['value'];
347
-		}
348
-		if (!isset($value) or $value === $this->app['former']->getOption('unchecked_value')) {
349
-			$value = $fallbackValue;
350
-		}
351
-
352
-		// If inline items, add class
353
-		$isInline = $this->inline ? ' '.$this->app['former.framework']->getInlineLabelClass($this) : null;
354
-
355
-		// In Bootsrap 3 or 4, don't append the the checkable type (radio/checkbox) as a class if
356
-		// rendering inline.
357
-		$class =  ($this->app['former']->framework() == 'TwitterBootstrap3' ||
358
-			$this->app['former']->framework() == 'TwitterBootstrap4') ? trim($isInline) : $this->checkable.$isInline;
359
-
360
-		// Merge custom attributes with global attributes
361
-		$attributes = array_merge($this->attributes, $attributes);
362
-		if (!isset($attributes['id'])) {
363
-			$attributes['id'] = $name.$this->unique($name);
364
-		}
365
-
366
-		// Create field
367
-		$field = Input::create($this->checkable, $name, Helpers::encode($value), $attributes);
368
-		if ($this->isChecked($item, $value)) {
369
-			$field->checked('checked');
370
-		}
371
-
372
-		// Add hidden checkbox if requested
373
-		if ($this->isOfType('checkbox', 'checkboxes')) {
374
-			if ($this->isPushed or ($this->app['former']->getOption('push_checkboxes') and $this->isPushed !== false)) {
375
-				$field = $this->app['former']->hidden($name)->forceValue($this->app['former']->getOption('unchecked_value')).$field->render();
376
-
377
-				// app['former.field'] was overwritten by Former::hidden() call in the line above, so here
378
-				// we reset it to $this to enable $this->app['former']->getErrors() to retrieve the correct object
379
-				$this->app->instance('former.field', $this);
380
-			}
381
-		}
382
-
383
-		// If no label to wrap, return plain checkable
384
-		if (!$label) {
385
-			$element = (is_object($field)) ? $field->render() : $field;
386
-		} elseif ($this->app['former']->framework() == 'TwitterBootstrap4') {
387
-			// Revised for Bootstrap 4, move the 'input' outside of the 'label'
388
-			$element = $field . Element::create('label', $label)->for($attributes['id'])->class($class)->render();
389
-
390
-			$wrapper_class = $this->inline ? 'form-check form-check-inline' : 'form-check';
391
-
392
-			$element = Element::create('div', $element)->class($wrapper_class)->render();
393
-
394
-		} else {
395
-			// Original way is to add the 'input' inside the 'label'
396
-			$element = Element::create('label', $field.$label)->for($attributes['id'])->class($class)->render();
397
-		}
398
-
399
-		// If BS3, if checkables are stacked, wrap them in a div with the checkable type
400
-		if (!$isInline && $this->app['former']->framework() == 'TwitterBootstrap3') {
401
-			$wrapper = Element::create('div', $element)->class($this->checkable);
402
-			if ($this->getAttribute('disabled')) {
403
-				$wrapper->addClass('disabled');
404
-			}
405
-			$element = $wrapper->render();
406
-		}
407
-
408
-		// Return the field
409
-		return $element;
410
-	}
411
-
412
-	////////////////////////////////////////////////////////////////////
413
-	///////////////////////////// HELPERS //////////////////////////////
414
-	////////////////////////////////////////////////////////////////////
415
-
416
-	/**
417
-	 * Generate an unique ID for a field
418
-	 *
419
-	 * @param string $name The field's name
420
-	 *
421
-	 * @return string A field number to use
422
-	 */
423
-	protected function unique($name)
424
-	{
425
-		$this->app['former']->labels[] = $name;
426
-
427
-		// Count number of fields with the same ID
428
-		$where  = array_filter($this->app['former']->labels, function ($label) use ($name) {
429
-			return $label == $name;
430
-		});
431
-		$unique = sizeof($where);
432
-
433
-		// In case the field doesn't need to be numbered
434
-		if ($unique < 2 or empty($this->items)) {
435
-			return false;
436
-		}
437
-
438
-		return $unique;
439
-	}
440
-
441
-	/**
442
-	 * Set something on the currently focused checkable
443
-	 *
444
-	 * @param string $attribute The key to set
445
-	 * @param string $value     Its value
446
-	 *
447
-	 * @return $this|bool
448
-	 */
449
-	protected function setOnFocused($attribute, $value)
450
-	{
451
-		if (is_null($this->focus)) {
452
-			return false;
453
-		}
454
-
455
-		$this->items[$this->focus] = Arr::set($this->items[$this->focus], $attribute, $value);
456
-
457
-		return $this;
458
-	}
459
-
460
-	/**
461
-	 * Check if a checkable is checked
462
-	 *
463
-	 * @return boolean Checked or not
464
-	 */
465
-	protected function isChecked($item = null, $value = null)
466
-	{
467
-		if (isset($item['name'])) {
468
-			$name = $item['name'];
469
-		}
470
-		if (empty($name)) {
471
-			$name = $this->name;
472
-		}
473
-
474
-		// If it's a checkbox, see if we marqued that one as checked in the array
475
-		// Or if it's a single radio, simply see if we called check
476
-		if ($this->isCheckbox() or
477
-			!$this->isCheckbox() and !$this->items
478
-		) {
479
-			$checked = Arr::get($this->checked, $name, false);
480
-
481
-			// If there are multiple, search for the value
482
-			// as the name are the same between radios
483
-		} else {
484
-			$checked = Arr::get($this->checked, $value, false);
485
-		}
486
-
487
-		// Check the values and POST array
488
-		if ($this->isGrouped()) {
489
-			// The group index. (e.g. 'bar' if the item name is foo[bar], or the item index for foo[])
490
-			$groupIndex = self::getGroupIndexFromItem($item);
491
-
492
-			// Search using the bare name, not the individual item name
493
-			$post   = $this->app['former']->getPost($this->name);
494
-			$static = $this->app['former']->getValue($this->bind ?: $this->name);
495
-
496
-			if (isset($post[$groupIndex])) {
497
-				$post = $post[$groupIndex];
498
-			}
499
-
500
-			/**
501
-			 * Support for Laravel Collection repopulating for grouped checkboxes. Note that the groupIndex must
502
-			 * match the value in order for the checkbox to be considered checked, e.g.:
503
-			 *
504
-			 *  array(
505
-			 *    'name' = 'roles[foo]',
506
-			 *    'value' => 'foo',
507
-			 *  )
508
-			 */
509
-			if ($static instanceof Collection) {
510
-				// If the repopulate value is a collection, search for an item matching the $groupIndex
511
-				foreach ($static as $staticItem) {
512
-					$staticItemValue = method_exists($staticItem, 'getKey') ? $staticItem->getKey() : $staticItem;
513
-					if ($staticItemValue == $groupIndex) {
514
-						$static = $staticItemValue;
515
-						break;
516
-					}
517
-				}
518
-			} else if (isset($static[$groupIndex])) {
519
-				$static = $static[$groupIndex];
520
-			}
521
-		} else {
522
-			$post   = $this->app['former']->getPost($name);
523
-			$static = $this->app['former']->getValue($this->bind ?: $name);
524
-		}
525
-
526
-		if (!is_null($post) and $post !== $this->app['former']->getOption('unchecked_value')) {
527
-			$isChecked = ($post == $value);
528
-		} elseif (!is_null($static)) {
529
-			$isChecked = ($static == $value);
530
-		} else {
531
-			$isChecked = $checked;
532
-		}
533
-
534
-		return $isChecked ? true : false;
535
-	}
536
-
537
-	/**
538
-	 * Check if the current element is a checkbox
539
-	 *
540
-	 * @return boolean Checkbox or radio
541
-	 */
542
-	protected function isCheckbox()
543
-	{
544
-		return $this->checkable == 'checkbox';
545
-	}
546
-
547
-	/**
548
-	 * Check if the checkables are grouped or not
549
-	 *
550
-	 * @return boolean
551
-	 */
552
-	protected function isGrouped()
553
-	{
554
-		return
555
-			$this->grouped == true or
556
-			strpos($this->name, '[]') !== false;
557
-	}
558
-
559
-	/**
560
-	 * @param array $item The item array, containing at least name and count keys.
561
-	 *
562
-	 * @return mixed The group index. (e.g. returns bar if the item name is foo[bar], or the item count for foo[])
563
-	 */
564
-	public static function getGroupIndexFromItem($item)
565
-	{
566
-		$groupIndex = preg_replace('/^.*?\[(.*)\]$/', '$1', $item['name']);
567
-		if (empty($groupIndex) or $groupIndex == $item['name']) {
568
-			return $item['count'];
569
-		}
570
-
571
-		return $groupIndex;
572
-	}
17
+    /**
18
+     * Renders the checkables as inline
19
+     *
20
+     * @var boolean
21
+     */
22
+    protected $inline = false;
23
+
24
+    /**
25
+     * Add a text to a single element
26
+     *
27
+     * @var string
28
+     */
29
+    protected $text = null;
30
+
31
+    /**
32
+     * Renders the checkables as grouped
33
+     *
34
+     * @var boolean
35
+     */
36
+    protected $grouped = false;
37
+
38
+    /**
39
+     * The checkable items currently stored
40
+     *
41
+     * @var array
42
+     */
43
+    protected $items = array();
44
+
45
+    /**
46
+     * The type of checkable item
47
+     *
48
+     * @var string
49
+     */
50
+    protected $checkable = null;
51
+
52
+    /**
53
+     * An array of checked items
54
+     *
55
+     * @var array
56
+     */
57
+    protected $checked = array();
58
+
59
+    /**
60
+     * The checkable currently being focused on
61
+     *
62
+     * @var integer
63
+     */
64
+    protected $focus = null;
65
+
66
+    /**
67
+     * Whether this particular checkable is to be pushed
68
+     *
69
+     * @var boolean
70
+     */
71
+    protected $isPushed = null;
72
+
73
+    ////////////////////////////////////////////////////////////////////
74
+    //////////////////////////// CORE METHODS //////////////////////////
75
+    ////////////////////////////////////////////////////////////////////
76
+
77
+    /**
78
+     * Build a new checkable
79
+     *
80
+     * @param Container $app
81
+     * @param string    $type
82
+     * @param array     $name
83
+     * @param           $label
84
+     * @param           $value
85
+     * @param           $attributes
86
+     */
87
+    public function __construct(Container $app, $type, $name, $label, $value, $attributes)
88
+    {
89
+        // Unify auto and chained methods of grouping checkboxes
90
+        if (Str::endsWith($name, '[]')) {
91
+            $name = substr($name, 0, -2);
92
+            $this->grouped();
93
+        }
94
+        parent::__construct($app, $type, $name, $label, $value, $attributes);
95
+
96
+        if (is_array($this->value)) {
97
+            $this->items($this->value);
98
+        }
99
+    }
100
+
101
+    /**
102
+     * Apply methods to focused checkable
103
+     *
104
+     * @param string $method
105
+     * @param array  $parameters
106
+     *
107
+     * @return $this
108
+     */
109
+    public function __call($method, $parameters)
110
+    {
111
+        $focused = $this->setOnFocused('attributes.'.$method, Arr::get($parameters, 0));
112
+        if ($focused) {
113
+            return $this;
114
+        }
115
+
116
+        return parent::__call($method, $parameters);
117
+    }
118
+
119
+    /**
120
+     * Prints out the currently stored checkables
121
+     */
122
+    public function render()
123
+    {
124
+        $html = null;
125
+
126
+        $this->setFieldClasses();
127
+
128
+        // Multiple items
129
+        if ($this->items) {
130
+            unset($this->app['former']->labels[array_search($this->name, $this->app['former']->labels)]);
131
+            foreach ($this->items as $key => $item) {
132
+                $value = $this->isCheckbox() && !$this->isGrouped() ? 1 : $key;
133
+                $html .= $this->createCheckable($item, $value);
134
+            }
135
+
136
+            return $html;
137
+        }
138
+
139
+        // Single item
140
+        return $this->createCheckable(array(
141
+            'name'  => $this->name,
142
+            'label' => $this->text,
143
+            'value' => $this->value,
144
+            'attributes' => $this->attributes,
145
+        ));
146
+    }
147
+
148
+    ////////////////////////////////////////////////////////////////////
149
+    ////////////////////////// FIELD METHODS ///////////////////////////
150
+    ////////////////////////////////////////////////////////////////////
151
+
152
+    /**
153
+     * Focus on a particular checkable
154
+     *
155
+     * @param integer $on The checkable to focus on
156
+     *
157
+     * @return $this
158
+     */
159
+    public function on($on)
160
+    {
161
+        if (!isset($this->items[$on])) {
162
+            return $this;
163
+        } else {
164
+            $this->focus = $on;
165
+        }
166
+
167
+        return $this;
168
+    }
169
+
170
+    /**
171
+     * Set the checkables as inline
172
+     */
173
+    public function inline($isInline = true)
174
+    {
175
+        $this->inline = $isInline;
176
+
177
+        return $this;
178
+    }
179
+
180
+    /**
181
+     * Set the checkables as stacked
182
+     */
183
+    public function stacked($isStacked = true)
184
+    {
185
+        $this->inline = !$isStacked;
186
+
187
+        return $this;
188
+    }
189
+
190
+    /**
191
+     * Set the checkables as grouped
192
+     */
193
+    public function grouped($isGrouped = true)
194
+    {
195
+        $this->grouped = $isGrouped;
196
+
197
+        return $this;
198
+    }
199
+
200
+    /**
201
+     * Add text to a single checkable
202
+     *
203
+     * @param  string $text The checkable label
204
+     *
205
+     * @return $this
206
+     */
207
+    public function text($text)
208
+    {
209
+        // Translate and format
210
+        $text = Helpers::translate($text);
211
+
212
+        // Apply on focused if any
213
+        $focused = $this->setOnFocused('label', $text);
214
+        if ($focused) {
215
+            return $this;
216
+        }
217
+
218
+        $this->text = $text;
219
+
220
+        return $this;
221
+    }
222
+
223
+    /**
224
+     * Push this particular checkbox
225
+     *
226
+     * @param boolean $pushed
227
+     *
228
+     * @return $this
229
+     */
230
+    public function push($pushed = true)
231
+    {
232
+        $this->isPushed = $pushed;
233
+
234
+        return $this;
235
+    }
236
+
237
+    /**
238
+     * Check a specific item
239
+     *
240
+     * @param bool|string $checked The checkable to check, or an array of checked items
241
+     *
242
+     * @return $this
243
+     */
244
+    public function check($checked = true)
245
+    {
246
+        // If we're setting all the checked items at once
247
+        if (is_array($checked)) {
248
+            $this->checked = $checked;
249
+            // Checking an item in particular
250
+        } elseif (is_string($checked) or is_int($checked)) {
251
+            $this->checked[$checked] = true;
252
+            // Only setting a single item
253
+        } else {
254
+            $this->checked[$this->name] = (bool) $checked;
255
+        }
256
+
257
+        return $this;
258
+    }
259
+
260
+    ////////////////////////////////////////////////////////////////////
261
+    ////////////////////////// INTERNAL METHODS ////////////////////////
262
+    ////////////////////////////////////////////////////////////////////
263
+
264
+    /**
265
+     * Creates a series of checkable items
266
+     *
267
+     * @param array $_items Items to create
268
+     */
269
+    protected function items($_items)
270
+    {
271
+        // If passing an array
272
+        if (sizeof($_items) == 1 and
273
+            isset($_items[0]) and
274
+            is_array($_items[0])
275
+        ) {
276
+            $_items = $_items[0];
277
+        }
278
+
279
+        // Fetch models if that's what we were passed
280
+        if (isset($_items[0]) and is_object($_items[0])) {
281
+            $_items = Helpers::queryToArray($_items);
282
+            $_items = array_flip($_items);
283
+        }
284
+
285
+        // Iterate through items, assign a name and a label to each
286
+        $count = 0;
287
+        foreach ($_items as $label => $name) {
288
+
289
+            // Define a fallback name in case none is found
290
+            $fallback = $this->isCheckbox()
291
+                ? $this->name.'_'.$count
292
+                : $this->name;
293
+
294
+            // Grouped fields
295
+            if ($this->isGrouped()) {
296
+                $attributes['id'] = str_replace('[]', null, $fallback);
297
+                $fallback         = str_replace('[]', null, $this->name).'[]';
298
+            }
299
+
300
+            // If we haven't any name defined for the checkable, try to compute some
301
+            if (!is_string($label) and !is_array($name)) {
302
+                $label = $name;
303
+                $name  = $fallback;
304
+            }
305
+
306
+            // If we gave custom information on the item, add them
307
+            if (is_array($name)) {
308
+                $attributes = $name;
309
+                $name       = Arr::get($attributes, 'name', $fallback);
310
+                unset($attributes['name']);
311
+            }
312
+
313
+            // Store all informations we have in an array
314
+            $item = array(
315
+                'name'  => $name,
316
+                'label' => Helpers::translate($label),
317
+                'count' => $count,
318
+            );
319
+            if (isset($attributes)) {
320
+                $item['attributes'] = $attributes;
321
+            }
322
+
323
+            $this->items[] = $item;
324
+            $count++;
325
+        }
326
+    }
327
+
328
+    /**
329
+     * Renders a checkable
330
+     *
331
+     * @param string|array $item          A checkable item
332
+     * @param integer      $fallbackValue A fallback value if none is set
333
+     *
334
+     * @return string
335
+     */
336
+    protected function createCheckable($item, $fallbackValue = 1)
337
+    {
338
+        // Extract informations
339
+        extract($item);
340
+
341
+        // Set default values
342
+        if (!isset($attributes)) {
343
+            $attributes = array();
344
+        }
345
+        if (isset($attributes['value'])) {
346
+            $value = $attributes['value'];
347
+        }
348
+        if (!isset($value) or $value === $this->app['former']->getOption('unchecked_value')) {
349
+            $value = $fallbackValue;
350
+        }
351
+
352
+        // If inline items, add class
353
+        $isInline = $this->inline ? ' '.$this->app['former.framework']->getInlineLabelClass($this) : null;
354
+
355
+        // In Bootsrap 3 or 4, don't append the the checkable type (radio/checkbox) as a class if
356
+        // rendering inline.
357
+        $class =  ($this->app['former']->framework() == 'TwitterBootstrap3' ||
358
+            $this->app['former']->framework() == 'TwitterBootstrap4') ? trim($isInline) : $this->checkable.$isInline;
359
+
360
+        // Merge custom attributes with global attributes
361
+        $attributes = array_merge($this->attributes, $attributes);
362
+        if (!isset($attributes['id'])) {
363
+            $attributes['id'] = $name.$this->unique($name);
364
+        }
365
+
366
+        // Create field
367
+        $field = Input::create($this->checkable, $name, Helpers::encode($value), $attributes);
368
+        if ($this->isChecked($item, $value)) {
369
+            $field->checked('checked');
370
+        }
371
+
372
+        // Add hidden checkbox if requested
373
+        if ($this->isOfType('checkbox', 'checkboxes')) {
374
+            if ($this->isPushed or ($this->app['former']->getOption('push_checkboxes') and $this->isPushed !== false)) {
375
+                $field = $this->app['former']->hidden($name)->forceValue($this->app['former']->getOption('unchecked_value')).$field->render();
376
+
377
+                // app['former.field'] was overwritten by Former::hidden() call in the line above, so here
378
+                // we reset it to $this to enable $this->app['former']->getErrors() to retrieve the correct object
379
+                $this->app->instance('former.field', $this);
380
+            }
381
+        }
382
+
383
+        // If no label to wrap, return plain checkable
384
+        if (!$label) {
385
+            $element = (is_object($field)) ? $field->render() : $field;
386
+        } elseif ($this->app['former']->framework() == 'TwitterBootstrap4') {
387
+            // Revised for Bootstrap 4, move the 'input' outside of the 'label'
388
+            $element = $field . Element::create('label', $label)->for($attributes['id'])->class($class)->render();
389
+
390
+            $wrapper_class = $this->inline ? 'form-check form-check-inline' : 'form-check';
391
+
392
+            $element = Element::create('div', $element)->class($wrapper_class)->render();
393
+
394
+        } else {
395
+            // Original way is to add the 'input' inside the 'label'
396
+            $element = Element::create('label', $field.$label)->for($attributes['id'])->class($class)->render();
397
+        }
398
+
399
+        // If BS3, if checkables are stacked, wrap them in a div with the checkable type
400
+        if (!$isInline && $this->app['former']->framework() == 'TwitterBootstrap3') {
401
+            $wrapper = Element::create('div', $element)->class($this->checkable);
402
+            if ($this->getAttribute('disabled')) {
403
+                $wrapper->addClass('disabled');
404
+            }
405
+            $element = $wrapper->render();
406
+        }
407
+
408
+        // Return the field
409
+        return $element;
410
+    }
411
+
412
+    ////////////////////////////////////////////////////////////////////
413
+    ///////////////////////////// HELPERS //////////////////////////////
414
+    ////////////////////////////////////////////////////////////////////
415
+
416
+    /**
417
+     * Generate an unique ID for a field
418
+     *
419
+     * @param string $name The field's name
420
+     *
421
+     * @return string A field number to use
422
+     */
423
+    protected function unique($name)
424
+    {
425
+        $this->app['former']->labels[] = $name;
426
+
427
+        // Count number of fields with the same ID
428
+        $where  = array_filter($this->app['former']->labels, function ($label) use ($name) {
429
+            return $label == $name;
430
+        });
431
+        $unique = sizeof($where);
432
+
433
+        // In case the field doesn't need to be numbered
434
+        if ($unique < 2 or empty($this->items)) {
435
+            return false;
436
+        }
437
+
438
+        return $unique;
439
+    }
440
+
441
+    /**
442
+     * Set something on the currently focused checkable
443
+     *
444
+     * @param string $attribute The key to set
445
+     * @param string $value     Its value
446
+     *
447
+     * @return $this|bool
448
+     */
449
+    protected function setOnFocused($attribute, $value)
450
+    {
451
+        if (is_null($this->focus)) {
452
+            return false;
453
+        }
454
+
455
+        $this->items[$this->focus] = Arr::set($this->items[$this->focus], $attribute, $value);
456
+
457
+        return $this;
458
+    }
459
+
460
+    /**
461
+     * Check if a checkable is checked
462
+     *
463
+     * @return boolean Checked or not
464
+     */
465
+    protected function isChecked($item = null, $value = null)
466
+    {
467
+        if (isset($item['name'])) {
468
+            $name = $item['name'];
469
+        }
470
+        if (empty($name)) {
471
+            $name = $this->name;
472
+        }
473
+
474
+        // If it's a checkbox, see if we marqued that one as checked in the array
475
+        // Or if it's a single radio, simply see if we called check
476
+        if ($this->isCheckbox() or
477
+            !$this->isCheckbox() and !$this->items
478
+        ) {
479
+            $checked = Arr::get($this->checked, $name, false);
480
+
481
+            // If there are multiple, search for the value
482
+            // as the name are the same between radios
483
+        } else {
484
+            $checked = Arr::get($this->checked, $value, false);
485
+        }
486
+
487
+        // Check the values and POST array
488
+        if ($this->isGrouped()) {
489
+            // The group index. (e.g. 'bar' if the item name is foo[bar], or the item index for foo[])
490
+            $groupIndex = self::getGroupIndexFromItem($item);
491
+
492
+            // Search using the bare name, not the individual item name
493
+            $post   = $this->app['former']->getPost($this->name);
494
+            $static = $this->app['former']->getValue($this->bind ?: $this->name);
495
+
496
+            if (isset($post[$groupIndex])) {
497
+                $post = $post[$groupIndex];
498
+            }
499
+
500
+            /**
501
+             * Support for Laravel Collection repopulating for grouped checkboxes. Note that the groupIndex must
502
+             * match the value in order for the checkbox to be considered checked, e.g.:
503
+             *
504
+             *  array(
505
+             *    'name' = 'roles[foo]',
506
+             *    'value' => 'foo',
507
+             *  )
508
+             */
509
+            if ($static instanceof Collection) {
510
+                // If the repopulate value is a collection, search for an item matching the $groupIndex
511
+                foreach ($static as $staticItem) {
512
+                    $staticItemValue = method_exists($staticItem, 'getKey') ? $staticItem->getKey() : $staticItem;
513
+                    if ($staticItemValue == $groupIndex) {
514
+                        $static = $staticItemValue;
515
+                        break;
516
+                    }
517
+                }
518
+            } else if (isset($static[$groupIndex])) {
519
+                $static = $static[$groupIndex];
520
+            }
521
+        } else {
522
+            $post   = $this->app['former']->getPost($name);
523
+            $static = $this->app['former']->getValue($this->bind ?: $name);
524
+        }
525
+
526
+        if (!is_null($post) and $post !== $this->app['former']->getOption('unchecked_value')) {
527
+            $isChecked = ($post == $value);
528
+        } elseif (!is_null($static)) {
529
+            $isChecked = ($static == $value);
530
+        } else {
531
+            $isChecked = $checked;
532
+        }
533
+
534
+        return $isChecked ? true : false;
535
+    }
536
+
537
+    /**
538
+     * Check if the current element is a checkbox
539
+     *
540
+     * @return boolean Checkbox or radio
541
+     */
542
+    protected function isCheckbox()
543
+    {
544
+        return $this->checkable == 'checkbox';
545
+    }
546
+
547
+    /**
548
+     * Check if the checkables are grouped or not
549
+     *
550
+     * @return boolean
551
+     */
552
+    protected function isGrouped()
553
+    {
554
+        return
555
+            $this->grouped == true or
556
+            strpos($this->name, '[]') !== false;
557
+    }
558
+
559
+    /**
560
+     * @param array $item The item array, containing at least name and count keys.
561
+     *
562
+     * @return mixed The group index. (e.g. returns bar if the item name is foo[bar], or the item count for foo[])
563
+     */
564
+    public static function getGroupIndexFromItem($item)
565
+    {
566
+        $groupIndex = preg_replace('/^.*?\[(.*)\]$/', '$1', $item['name']);
567
+        if (empty($groupIndex) or $groupIndex == $item['name']) {
568
+            return $item['count'];
569
+        }
570
+
571
+        return $groupIndex;
572
+    }
573 573
 }
Please login to merge, or discard this patch.
src/Former/Traits/Framework.php 1 patch
Indentation   +318 added lines, -318 removed lines patch added patch discarded remove patch
@@ -10,322 +10,322 @@
 block discarded – undo
10 10
  */
11 11
 abstract class Framework implements FrameworkInterface
12 12
 {
13
-	/**
14
-	 * The Container
15
-	 *
16
-	 * @var Container
17
-	 */
18
-	protected $app;
19
-
20
-	/**
21
-	 * Form types that trigger special styling
22
-	 *
23
-	 * @var array
24
-	 */
25
-	protected $availableTypes = array();
26
-
27
-	/**
28
-	 * The field states available
29
-	 *
30
-	 * @var array
31
-	 */
32
-	protected $states = array();
33
-
34
-	/**
35
-	 * The default label width (for horizontal forms)
36
-	 *
37
-	 * @var string
38
-	 */
39
-	protected $labelWidth;
40
-
41
-	/**
42
-	 * The default field width (for horizontal forms)
43
-	 *
44
-	 * @var string
45
-	 */
46
-	protected $fieldWidth;
47
-
48
-	/**
49
-	 * The default offset for fields (for horizontal form fields
50
-	 * with no label, so usually equal to the default label width)
51
-	 *
52
-	 * @var string
53
-	 */
54
-	protected $fieldOffset;
55
-
56
-	/**
57
-	 * The default HTML tag used for icons
58
-	 *
59
-	 * @var string
60
-	 */
61
-	protected $iconTag;
62
-
63
-	/**
64
-	 * The default set for icon fonts
65
-	 *
66
-	 * @var string
67
-	 */
68
-	protected $iconSet;
69
-
70
-	/**
71
-	 * The default prefix icon names
72
-	 *
73
-	 * @var string
74
-	 */
75
-	protected $iconPrefix;
76
-
77
-	////////////////////////////////////////////////////////////////////
78
-	//////////////////////// CURRENT FRAMEWORK /////////////////////////
79
-	////////////////////////////////////////////////////////////////////
80
-
81
-	/**
82
-	 * Get the name of the current framework
83
-	 *
84
-	 * @return string
85
-	 */
86
-	public function current()
87
-	{
88
-		return basename(str_replace('\\', '/', get_class($this)));
89
-	}
90
-
91
-	/**
92
-	 * Check if the current framework matches something
93
-	 *
94
-	 * @param  string $framework
95
-	 *
96
-	 * @return boolean
97
-	 */
98
-	public function is($framework)
99
-	{
100
-		return $framework == $this->current();
101
-	}
102
-
103
-	/**
104
-	 * Check if the current framework doesn't match something
105
-	 *
106
-	 * @param  string $framework
107
-	 *
108
-	 * @return boolean
109
-	 */
110
-	public function isnt($framework)
111
-	{
112
-		return $framework != $this->current();
113
-	}
114
-
115
-	////////////////////////////////////////////////////////////////////
116
-	/////////////////////////// COMMON METHODS /////////////////////////
117
-	////////////////////////////////////////////////////////////////////
118
-
119
-	/**
120
-	 * List form types triggered special styling form current framework
121
-	 *
122
-	 * @return array
123
-	 */
124
-	public function availableTypes()
125
-	{
126
-		return $this->availableTypes;
127
-	}
128
-
129
-	/**
130
-	 * Filter a field state
131
-	 *
132
-	 * @param string $state
133
-	 *
134
-	 * @return string
135
-	 */
136
-	public function filterState($state)
137
-	{
138
-		// Filter out wrong states
139
-		return in_array($state, $this->states) ? $state : null;
140
-	}
141
-
142
-	/**
143
-	 * Framework error state
144
-	 *
145
-	 * @return string
146
-	 */
147
-	public function errorState()
148
-	{
149
-		return 'error';
150
-	}
151
-
152
-	/**
153
-	 * Returns corresponding inline class of a field
154
-	 *
155
-	 * @param Field $field
156
-	 *
157
-	 * @return string
158
-	 */
159
-	public function getInlineLabelClass($field)
160
-	{
161
-		return 'inline';
162
-	}
163
-
164
-	/**
165
-	 * Set framework defaults from its config file
166
-	 */
167
-	protected function setFrameworkDefaults()
168
-	{
169
-		$this->setFieldWidths($this->getFrameworkOption('labelWidths'));
170
-		$this->setIconDefaults();
171
-	}
172
-
173
-	/**
174
-	 * @param string $widths
175
-	 */
176
-	protected function setFieldWidths($widths)
177
-	{
178
-	}
179
-
180
-	/**
181
-	 * Override framework defaults for icons with config values where set
182
-	 */
183
-	protected function setIconDefaults()
184
-	{
185
-		$this->iconTag    = $this->getFrameworkOption('icon.tag');
186
-		$this->iconSet    = $this->getFrameworkOption('icon.set');
187
-		$this->iconPrefix = $this->getFrameworkOption('icon.prefix');
188
-	}
189
-
190
-	/**
191
-	 * Render an icon
192
-	 *
193
-	 * @param array $attributes Its general attributes
194
-	 *
195
-	 * @return string
196
-	 */
197
-	public function createIcon($iconType, $attributes = array(), $iconSettings = array())
198
-	{
199
-		// Check for empty icons
200
-		if (!$iconType) {
201
-			return false;
202
-		}
203
-
204
-		// icon settings can be overridden for a specific icon
205
-		$tag    = Arr::get($iconSettings, 'tag', $this->iconTag);
206
-		$set    = Arr::get($iconSettings, 'set', $this->iconSet);
207
-		$prefix = Arr::get($iconSettings, 'prefix', $this->iconPrefix);
208
-
209
-		return Element::create($tag, null, $attributes)->addClass("$set $prefix-$iconType");
210
-	}
211
-
212
-	////////////////////////////////////////////////////////////////////
213
-	///////////////////////////// HELPERS //////////////////////////////
214
-	////////////////////////////////////////////////////////////////////
215
-
216
-	/**
217
-	 * Add classes to a field
218
-	 *
219
-	 * @param Field $field
220
-	 * @param array $classes
221
-	 *
222
-	 * @return \Former\Traits\Field
223
-	 */
224
-	protected function addClassesToField($field, $classes)
225
-	{
226
-		// If we found any class, add them
227
-		if ($classes) {
228
-			$field->addClass(implode(' ', $classes));
229
-		}
230
-
231
-		return $field;
232
-	}
233
-
234
-	/**
235
-	 * Prepend an array of classes with a string
236
-	 *
237
-	 * @param array  $classes The classes to prepend
238
-	 * @param string $with    The string to prepend them with
239
-	 *
240
-	 * @return array A prepended array
241
-	 */
242
-	protected function prependWith($classes, $with)
243
-	{
244
-		return array_map(function ($class) use ($with) {
245
-			return $with.$class;
246
-		}, $classes);
247
-	}
248
-
249
-	/**
250
-	 * Create a label for a field
251
-	 *
252
-	 * @param Field   $field
253
-	 * @param Element $label The field label if non provided
254
-	 *
255
-	 * @return string A label
256
-	 */
257
-	public function createLabelOf(Field $field, Element $label = null)
258
-	{
259
-		// Get the label and its informations
260
-		if (!$label) {
261
-			$label = $field->getLabel();
262
-		}
263
-
264
-		// Get label "for"
265
-		$for = $field->id ?: $field->getName();
266
-
267
-		// Get label text
268
-		$text = $label->getValue();
269
-		if (!$text) {
270
-			return false;
271
-		}
272
-
273
-		// Append required text
274
-		if ($field->isRequired()) {
275
-			$text .= $this->app['former']->getOption('required_text');
276
-		}
277
-
278
-		// Render plain label if checkable, else a classic one
279
-		$label->setValue($text);
280
-		if (!$field->isCheckable()) {
281
-			$label->for($for);
282
-		}
283
-
284
-		return $label;
285
-	}
286
-
287
-	/**
288
-	 * Get an option for the current framework
289
-	 *
290
-	 * @param string $option
291
-	 *
292
-	 * @return string
293
-	 */
294
-	protected function getFrameworkOption($option)
295
-	{
296
-		return $this->app['config']->get("former.{$this->current()}.$option");
297
-	}
298
-
299
-	////////////////////////////////////////////////////////////////////
300
-	//////////////////////////// WRAP BLOCKS ///////////////////////////
301
-	////////////////////////////////////////////////////////////////////
302
-
303
-	/**
304
-	 * Wraps all label contents with potential additional tags.
305
-	 *
306
-	 * @param  string $label
307
-	 *
308
-	 * @return string A wrapped label
309
-	 */
310
-	public function wrapLabel($label)
311
-	{
312
-		return $label;
313
-	}
314
-
315
-	////////////////////////////////////////////////////////////////////
316
-	//////////////////////////// RENDER BLOCKS /////////////////////////
317
-	////////////////////////////////////////////////////////////////////
318
-
319
-	/**
320
-	 * Render an validation error text
321
-	 *
322
-	 * @param string $text
323
-	 * @param array  $attributes
324
-	 *
325
-	 * @return string
326
-	 */
327
-	public function createValidationError($text, $attributes = array())
328
-	{
329
-		return $this->createHelp($text, $attributes);
330
-	}
13
+    /**
14
+     * The Container
15
+     *
16
+     * @var Container
17
+     */
18
+    protected $app;
19
+
20
+    /**
21
+     * Form types that trigger special styling
22
+     *
23
+     * @var array
24
+     */
25
+    protected $availableTypes = array();
26
+
27
+    /**
28
+     * The field states available
29
+     *
30
+     * @var array
31
+     */
32
+    protected $states = array();
33
+
34
+    /**
35
+     * The default label width (for horizontal forms)
36
+     *
37
+     * @var string
38
+     */
39
+    protected $labelWidth;
40
+
41
+    /**
42
+     * The default field width (for horizontal forms)
43
+     *
44
+     * @var string
45
+     */
46
+    protected $fieldWidth;
47
+
48
+    /**
49
+     * The default offset for fields (for horizontal form fields
50
+     * with no label, so usually equal to the default label width)
51
+     *
52
+     * @var string
53
+     */
54
+    protected $fieldOffset;
55
+
56
+    /**
57
+     * The default HTML tag used for icons
58
+     *
59
+     * @var string
60
+     */
61
+    protected $iconTag;
62
+
63
+    /**
64
+     * The default set for icon fonts
65
+     *
66
+     * @var string
67
+     */
68
+    protected $iconSet;
69
+
70
+    /**
71
+     * The default prefix icon names
72
+     *
73
+     * @var string
74
+     */
75
+    protected $iconPrefix;
76
+
77
+    ////////////////////////////////////////////////////////////////////
78
+    //////////////////////// CURRENT FRAMEWORK /////////////////////////
79
+    ////////////////////////////////////////////////////////////////////
80
+
81
+    /**
82
+     * Get the name of the current framework
83
+     *
84
+     * @return string
85
+     */
86
+    public function current()
87
+    {
88
+        return basename(str_replace('\\', '/', get_class($this)));
89
+    }
90
+
91
+    /**
92
+     * Check if the current framework matches something
93
+     *
94
+     * @param  string $framework
95
+     *
96
+     * @return boolean
97
+     */
98
+    public function is($framework)
99
+    {
100
+        return $framework == $this->current();
101
+    }
102
+
103
+    /**
104
+     * Check if the current framework doesn't match something
105
+     *
106
+     * @param  string $framework
107
+     *
108
+     * @return boolean
109
+     */
110
+    public function isnt($framework)
111
+    {
112
+        return $framework != $this->current();
113
+    }
114
+
115
+    ////////////////////////////////////////////////////////////////////
116
+    /////////////////////////// COMMON METHODS /////////////////////////
117
+    ////////////////////////////////////////////////////////////////////
118
+
119
+    /**
120
+     * List form types triggered special styling form current framework
121
+     *
122
+     * @return array
123
+     */
124
+    public function availableTypes()
125
+    {
126
+        return $this->availableTypes;
127
+    }
128
+
129
+    /**
130
+     * Filter a field state
131
+     *
132
+     * @param string $state
133
+     *
134
+     * @return string
135
+     */
136
+    public function filterState($state)
137
+    {
138
+        // Filter out wrong states
139
+        return in_array($state, $this->states) ? $state : null;
140
+    }
141
+
142
+    /**
143
+     * Framework error state
144
+     *
145
+     * @return string
146
+     */
147
+    public function errorState()
148
+    {
149
+        return 'error';
150
+    }
151
+
152
+    /**
153
+     * Returns corresponding inline class of a field
154
+     *
155
+     * @param Field $field
156
+     *
157
+     * @return string
158
+     */
159
+    public function getInlineLabelClass($field)
160
+    {
161
+        return 'inline';
162
+    }
163
+
164
+    /**
165
+     * Set framework defaults from its config file
166
+     */
167
+    protected function setFrameworkDefaults()
168
+    {
169
+        $this->setFieldWidths($this->getFrameworkOption('labelWidths'));
170
+        $this->setIconDefaults();
171
+    }
172
+
173
+    /**
174
+     * @param string $widths
175
+     */
176
+    protected function setFieldWidths($widths)
177
+    {
178
+    }
179
+
180
+    /**
181
+     * Override framework defaults for icons with config values where set
182
+     */
183
+    protected function setIconDefaults()
184
+    {
185
+        $this->iconTag    = $this->getFrameworkOption('icon.tag');
186
+        $this->iconSet    = $this->getFrameworkOption('icon.set');
187
+        $this->iconPrefix = $this->getFrameworkOption('icon.prefix');
188
+    }
189
+
190
+    /**
191
+     * Render an icon
192
+     *
193
+     * @param array $attributes Its general attributes
194
+     *
195
+     * @return string
196
+     */
197
+    public function createIcon($iconType, $attributes = array(), $iconSettings = array())
198
+    {
199
+        // Check for empty icons
200
+        if (!$iconType) {
201
+            return false;
202
+        }
203
+
204
+        // icon settings can be overridden for a specific icon
205
+        $tag    = Arr::get($iconSettings, 'tag', $this->iconTag);
206
+        $set    = Arr::get($iconSettings, 'set', $this->iconSet);
207
+        $prefix = Arr::get($iconSettings, 'prefix', $this->iconPrefix);
208
+
209
+        return Element::create($tag, null, $attributes)->addClass("$set $prefix-$iconType");
210
+    }
211
+
212
+    ////////////////////////////////////////////////////////////////////
213
+    ///////////////////////////// HELPERS //////////////////////////////
214
+    ////////////////////////////////////////////////////////////////////
215
+
216
+    /**
217
+     * Add classes to a field
218
+     *
219
+     * @param Field $field
220
+     * @param array $classes
221
+     *
222
+     * @return \Former\Traits\Field
223
+     */
224
+    protected function addClassesToField($field, $classes)
225
+    {
226
+        // If we found any class, add them
227
+        if ($classes) {
228
+            $field->addClass(implode(' ', $classes));
229
+        }
230
+
231
+        return $field;
232
+    }
233
+
234
+    /**
235
+     * Prepend an array of classes with a string
236
+     *
237
+     * @param array  $classes The classes to prepend
238
+     * @param string $with    The string to prepend them with
239
+     *
240
+     * @return array A prepended array
241
+     */
242
+    protected function prependWith($classes, $with)
243
+    {
244
+        return array_map(function ($class) use ($with) {
245
+            return $with.$class;
246
+        }, $classes);
247
+    }
248
+
249
+    /**
250
+     * Create a label for a field
251
+     *
252
+     * @param Field   $field
253
+     * @param Element $label The field label if non provided
254
+     *
255
+     * @return string A label
256
+     */
257
+    public function createLabelOf(Field $field, Element $label = null)
258
+    {
259
+        // Get the label and its informations
260
+        if (!$label) {
261
+            $label = $field->getLabel();
262
+        }
263
+
264
+        // Get label "for"
265
+        $for = $field->id ?: $field->getName();
266
+
267
+        // Get label text
268
+        $text = $label->getValue();
269
+        if (!$text) {
270
+            return false;
271
+        }
272
+
273
+        // Append required text
274
+        if ($field->isRequired()) {
275
+            $text .= $this->app['former']->getOption('required_text');
276
+        }
277
+
278
+        // Render plain label if checkable, else a classic one
279
+        $label->setValue($text);
280
+        if (!$field->isCheckable()) {
281
+            $label->for($for);
282
+        }
283
+
284
+        return $label;
285
+    }
286
+
287
+    /**
288
+     * Get an option for the current framework
289
+     *
290
+     * @param string $option
291
+     *
292
+     * @return string
293
+     */
294
+    protected function getFrameworkOption($option)
295
+    {
296
+        return $this->app['config']->get("former.{$this->current()}.$option");
297
+    }
298
+
299
+    ////////////////////////////////////////////////////////////////////
300
+    //////////////////////////// WRAP BLOCKS ///////////////////////////
301
+    ////////////////////////////////////////////////////////////////////
302
+
303
+    /**
304
+     * Wraps all label contents with potential additional tags.
305
+     *
306
+     * @param  string $label
307
+     *
308
+     * @return string A wrapped label
309
+     */
310
+    public function wrapLabel($label)
311
+    {
312
+        return $label;
313
+    }
314
+
315
+    ////////////////////////////////////////////////////////////////////
316
+    //////////////////////////// RENDER BLOCKS /////////////////////////
317
+    ////////////////////////////////////////////////////////////////////
318
+
319
+    /**
320
+     * Render an validation error text
321
+     *
322
+     * @param string $text
323
+     * @param array  $attributes
324
+     *
325
+     * @return string
326
+     */
327
+    public function createValidationError($text, $attributes = array())
328
+    {
329
+        return $this->createHelp($text, $attributes);
330
+    }
331 331
 }
Please login to merge, or discard this patch.
src/Former/Framework/TwitterBootstrap.php 1 patch
Indentation   +370 added lines, -370 removed lines patch added patch discarded remove patch
@@ -14,374 +14,374 @@
 block discarded – undo
14 14
  */
15 15
 class TwitterBootstrap extends Framework implements FrameworkInterface
16 16
 {
17
-	/**
18
-	 * Form types that trigger special styling for this Framework
19
-	 *
20
-	 * @var array
21
-	 */
22
-	protected $availableTypes = array('horizontal', 'vertical', 'inline', 'search');
23
-
24
-	/**
25
-	 * The button types available
26
-	 *
27
-	 * @var array
28
-	 */
29
-	private $buttons = array(
30
-		'large',
31
-		'small',
32
-		'mini',
33
-		'block',
34
-		'danger',
35
-		'info',
36
-		'inverse',
37
-		'link',
38
-		'primary',
39
-		'success',
40
-		'warning',
41
-	);
42
-
43
-	/**
44
-	 * The field sizes available
45
-	 *
46
-	 * @var array
47
-	 */
48
-	private $fields = array(
49
-		'mini',
50
-		'small',
51
-		'medium',
52
-		'large',
53
-		'xlarge',
54
-		'xxlarge',
55
-		'span1',
56
-		'span2',
57
-		'span3',
58
-		'span4',
59
-		'span5',
60
-		'span6',
61
-		'span7',
62
-		'span8',
63
-		'span9',
64
-		'span10',
65
-		'span11',
66
-		'span12',
67
-	);
68
-
69
-	/**
70
-	 * The field states available
71
-	 *
72
-	 * @var array
73
-	 */
74
-	protected $states = array(
75
-		'success',
76
-		'warning',
77
-		'error',
78
-		'info',
79
-	);
80
-
81
-	/**
82
-	 * Create a new TwitterBootstrap instance
83
-	 *
84
-	 * @param \Illuminate\Container\Container $app
85
-	 */
86
-	public function __construct(Container $app)
87
-	{
88
-		$this->app = $app;
89
-		$this->setFrameworkDefaults();
90
-	}
91
-
92
-	////////////////////////////////////////////////////////////////////
93
-	/////////////////////////// FILTER ARRAYS //////////////////////////
94
-	////////////////////////////////////////////////////////////////////
95
-
96
-	/**
97
-	 * Filter buttons classes
98
-	 *
99
-	 * @param  array $classes An array of classes
100
-	 *
101
-	 * @return string[] A filtered array
102
-	 */
103
-	public function filterButtonClasses($classes)
104
-	{
105
-		// Filter classes
106
-		// $classes = array_intersect($classes, $this->buttons);
107
-
108
-		// Prepend button type
109
-		$classes   = $this->prependWith($classes, 'btn-');
110
-		$classes[] = 'btn';
111
-
112
-		return $classes;
113
-	}
114
-
115
-	/**
116
-	 * Filter field classes
117
-	 *
118
-	 * @param  array $classes An array of classes
119
-	 *
120
-	 * @return array A filtered array
121
-	 */
122
-	public function filterFieldClasses($classes)
123
-	{
124
-		// Filter classes
125
-		$classes = array_intersect($classes, $this->fields);
126
-
127
-		// Prepend field type
128
-		$classes = array_map(function ($class) {
129
-			return Str::startsWith($class, 'span') ? $class : 'input-'.$class;
130
-		}, $classes);
131
-
132
-		return $classes;
133
-	}
134
-
135
-	////////////////////////////////////////////////////////////////////
136
-	///////////////////////////// ADD CLASSES //////////////////////////
137
-	////////////////////////////////////////////////////////////////////
138
-
139
-	/**
140
-	 * Add classes to a field
141
-	 *
142
-	 * @param Field $field
143
-	 * @param array $classes The possible classes to add
144
-	 *
145
-	 * @return Field
146
-	 */
147
-	public function getFieldClasses(Field $field, $classes)
148
-	{
149
-		// Add inline class for checkables
150
-		if ($field->isCheckable() and in_array('inline', $classes)) {
151
-			$field->inline();
152
-		}
153
-
154
-		// Filter classes according to field type
155
-		if ($field->isButton()) {
156
-			$classes = $this->filterButtonClasses($classes);
157
-		} else {
158
-			$classes = $this->filterFieldClasses($classes);
159
-		}
160
-
161
-		return $this->addClassesToField($field, $classes);
162
-	}
163
-
164
-	/**
165
-	 * Add group classes
166
-	 *
167
-	 * @return string A list of group classes
168
-	 */
169
-	public function getGroupClasses()
170
-	{
171
-		return 'control-group';
172
-	}
173
-
174
-	/**
175
-	 * Add label classes
176
-	 *
177
-	 * @return string An array of attributes with the label class
178
-	 */
179
-	public function getLabelClasses()
180
-	{
181
-		return 'control-label';
182
-	}
183
-
184
-	/**
185
-	 * Add uneditable field classes
186
-	 *
187
-	 * @return string An array of attributes with the uneditable class
188
-	 */
189
-	public function getUneditableClasses()
190
-	{
191
-		return 'uneditable-input';
192
-	}
193
-
194
-	public function getPlainTextClasses()
195
-	{
196
-		return null;
197
-	}
198
-
199
-	/**
200
-	 * Add form class
201
-	 *
202
-	 * @param  string $type The type of form to add
203
-	 *
204
-	 * @return string|null
205
-	 */
206
-	public function getFormClasses($type)
207
-	{
208
-		return $type ? 'form-'.$type : null;
209
-	}
210
-
211
-	/**
212
-	 * Add actions block class
213
-	 *
214
-	 * @return string
215
-	 */
216
-	public function getActionClasses()
217
-	{
218
-		return 'form-actions';
219
-	}
220
-
221
-	////////////////////////////////////////////////////////////////////
222
-	//////////////////////////// RENDER BLOCKS /////////////////////////
223
-	////////////////////////////////////////////////////////////////////
224
-
225
-	/**
226
-	 * Render an help text
227
-	 *
228
-	 * @param string $text
229
-	 * @param array  $attributes
230
-	 *
231
-	 * @return Element
232
-	 */
233
-	public function createHelp($text, $attributes = array())
234
-	{
235
-		return Element::create('span', $text, $attributes)->addClass('help-inline');
236
-	}
237
-
238
-	/**
239
-	 * Render a block help text
240
-	 *
241
-	 * @param string $text
242
-	 * @param array  $attributes
243
-	 *
244
-	 * @return Element
245
-	 */
246
-	public function createBlockHelp($text, $attributes = array())
247
-	{
248
-		return Element::create('p', $text, $attributes)->addClass('help-block');
249
-	}
250
-
251
-	/**
252
-	 * Render a disabled field
253
-	 *
254
-	 * @param Field $field
255
-	 *
256
-	 * @return Element
257
-	 */
258
-	public function createDisabledField(Field $field)
259
-	{
260
-		return Element::create('span', $field->getValue(), $field->getAttributes());
261
-	}
262
-
263
-	/**
264
-	 * Render a plain text field
265
-	 * Which fallback to a disabled field
266
-	 *
267
-	 * @param Field $field
268
-	 *
269
-	 * @return Element
270
-	 */
271
-	public function createPlainTextField(Field $field)
272
-	{
273
-		return $this->createDisabledField($field);
274
-	}
275
-
276
-	/**
277
-	 * Render an icon
278
-	 *
279
-	 * @param array $attributes Its general attributes
280
-	 *
281
-	 * @return string
282
-	 */
283
-	public function createIcon($iconType, $attributes = array(), $iconSettings = array())
284
-	{
285
-		// Check for empty icons
286
-		if (!$iconType) {
287
-			return false;
288
-		}
289
-
290
-		// Create tag
291
-		$tag  = Arr::get($iconSettings, 'tag', $this->iconTag);
292
-		$icon = Element::create($tag, null, $attributes);
293
-
294
-		// White icons ignore user overrides to use legacy Bootstrap styling
295
-		if (Str::contains($iconType, 'white')) {
296
-			$iconType = str_replace('white', '', $iconType);
297
-			$iconType = trim($iconType, '-');
298
-			$icon->addClass('icon-white');
299
-			$set    = null;
300
-			$prefix = 'icon';
301
-		} else {
302
-			$set    = Arr::get($iconSettings, 'set', $this->iconSet);
303
-			$prefix = Arr::get($iconSettings, 'prefix', $this->iconPrefix);
304
-		}
305
-		$icon->addClass("$set $prefix-$iconType");
306
-
307
-		return $icon;
308
-	}
309
-
310
-	////////////////////////////////////////////////////////////////////
311
-	//////////////////////////// WRAP BLOCKS ///////////////////////////
312
-	////////////////////////////////////////////////////////////////////
313
-
314
-	/**
315
-	 * Wrap an item to be prepended or appended to the current field
316
-	 *
317
-	 * @param  string $item
318
-	 *
319
-	 * @return string A wrapped item
320
-	 */
321
-	public function placeAround($item)
322
-	{
323
-		// Render object
324
-		if (is_object($item) and method_exists($item, '__toString')) {
325
-			$item = $item->__toString();
326
-		}
327
-
328
-		// Return unwrapped if button
329
-		if (strpos($item, '<button') !== false) {
330
-			return $item;
331
-		}
332
-
333
-		return Element::create('span', $item)->addClass('add-on');
334
-	}
335
-
336
-	/**
337
-	 * Wrap a field with prepended and appended items
338
-	 *
339
-	 * @param  Field $field
340
-	 * @param  array $prepend
341
-	 * @param  array $append
342
-	 *
343
-	 * @return string A field concatented with prepended and/or appended items
344
-	 */
345
-	public function prependAppend($field, $prepend, $append)
346
-	{
347
-		$class = array();
348
-		if ($prepend) {
349
-			$class[] = 'input-prepend';
350
-		}
351
-		if ($append) {
352
-			$class[] = 'input-append';
353
-		}
354
-
355
-		$return = '<div class="'.join(' ', $class).'">';
356
-		$return .= join(null, $prepend);
357
-		$return .= $field->render();
358
-		$return .= join(null, $append);
359
-		$return .= '</div>';
360
-
361
-		return $return;
362
-	}
363
-
364
-	/**
365
-	 * Wrap a field with potential additional tags
366
-	 *
367
-	 * @param  Field $field
368
-	 *
369
-	 * @return Element A wrapped field
370
-	 */
371
-	public function wrapField($field)
372
-	{
373
-		return Element::create('div', $field)->addClass('controls');
374
-	}
375
-
376
-	/**
377
-	 * Wrap actions block with potential additional tags
378
-	 *
379
-	 * @param  Actions $actions
380
-	 *
381
-	 * @return string A wrapped actions block
382
-	 */
383
-	public function wrapActions($actions)
384
-	{
385
-		return $actions;
386
-	}
17
+    /**
18
+     * Form types that trigger special styling for this Framework
19
+     *
20
+     * @var array
21
+     */
22
+    protected $availableTypes = array('horizontal', 'vertical', 'inline', 'search');
23
+
24
+    /**
25
+     * The button types available
26
+     *
27
+     * @var array
28
+     */
29
+    private $buttons = array(
30
+        'large',
31
+        'small',
32
+        'mini',
33
+        'block',
34
+        'danger',
35
+        'info',
36
+        'inverse',
37
+        'link',
38
+        'primary',
39
+        'success',
40
+        'warning',
41
+    );
42
+
43
+    /**
44
+     * The field sizes available
45
+     *
46
+     * @var array
47
+     */
48
+    private $fields = array(
49
+        'mini',
50
+        'small',
51
+        'medium',
52
+        'large',
53
+        'xlarge',
54
+        'xxlarge',
55
+        'span1',
56
+        'span2',
57
+        'span3',
58
+        'span4',
59
+        'span5',
60
+        'span6',
61
+        'span7',
62
+        'span8',
63
+        'span9',
64
+        'span10',
65
+        'span11',
66
+        'span12',
67
+    );
68
+
69
+    /**
70
+     * The field states available
71
+     *
72
+     * @var array
73
+     */
74
+    protected $states = array(
75
+        'success',
76
+        'warning',
77
+        'error',
78
+        'info',
79
+    );
80
+
81
+    /**
82
+     * Create a new TwitterBootstrap instance
83
+     *
84
+     * @param \Illuminate\Container\Container $app
85
+     */
86
+    public function __construct(Container $app)
87
+    {
88
+        $this->app = $app;
89
+        $this->setFrameworkDefaults();
90
+    }
91
+
92
+    ////////////////////////////////////////////////////////////////////
93
+    /////////////////////////// FILTER ARRAYS //////////////////////////
94
+    ////////////////////////////////////////////////////////////////////
95
+
96
+    /**
97
+     * Filter buttons classes
98
+     *
99
+     * @param  array $classes An array of classes
100
+     *
101
+     * @return string[] A filtered array
102
+     */
103
+    public function filterButtonClasses($classes)
104
+    {
105
+        // Filter classes
106
+        // $classes = array_intersect($classes, $this->buttons);
107
+
108
+        // Prepend button type
109
+        $classes   = $this->prependWith($classes, 'btn-');
110
+        $classes[] = 'btn';
111
+
112
+        return $classes;
113
+    }
114
+
115
+    /**
116
+     * Filter field classes
117
+     *
118
+     * @param  array $classes An array of classes
119
+     *
120
+     * @return array A filtered array
121
+     */
122
+    public function filterFieldClasses($classes)
123
+    {
124
+        // Filter classes
125
+        $classes = array_intersect($classes, $this->fields);
126
+
127
+        // Prepend field type
128
+        $classes = array_map(function ($class) {
129
+            return Str::startsWith($class, 'span') ? $class : 'input-'.$class;
130
+        }, $classes);
131
+
132
+        return $classes;
133
+    }
134
+
135
+    ////////////////////////////////////////////////////////////////////
136
+    ///////////////////////////// ADD CLASSES //////////////////////////
137
+    ////////////////////////////////////////////////////////////////////
138
+
139
+    /**
140
+     * Add classes to a field
141
+     *
142
+     * @param Field $field
143
+     * @param array $classes The possible classes to add
144
+     *
145
+     * @return Field
146
+     */
147
+    public function getFieldClasses(Field $field, $classes)
148
+    {
149
+        // Add inline class for checkables
150
+        if ($field->isCheckable() and in_array('inline', $classes)) {
151
+            $field->inline();
152
+        }
153
+
154
+        // Filter classes according to field type
155
+        if ($field->isButton()) {
156
+            $classes = $this->filterButtonClasses($classes);
157
+        } else {
158
+            $classes = $this->filterFieldClasses($classes);
159
+        }
160
+
161
+        return $this->addClassesToField($field, $classes);
162
+    }
163
+
164
+    /**
165
+     * Add group classes
166
+     *
167
+     * @return string A list of group classes
168
+     */
169
+    public function getGroupClasses()
170
+    {
171
+        return 'control-group';
172
+    }
173
+
174
+    /**
175
+     * Add label classes
176
+     *
177
+     * @return string An array of attributes with the label class
178
+     */
179
+    public function getLabelClasses()
180
+    {
181
+        return 'control-label';
182
+    }
183
+
184
+    /**
185
+     * Add uneditable field classes
186
+     *
187
+     * @return string An array of attributes with the uneditable class
188
+     */
189
+    public function getUneditableClasses()
190
+    {
191
+        return 'uneditable-input';
192
+    }
193
+
194
+    public function getPlainTextClasses()
195
+    {
196
+        return null;
197
+    }
198
+
199
+    /**
200
+     * Add form class
201
+     *
202
+     * @param  string $type The type of form to add
203
+     *
204
+     * @return string|null
205
+     */
206
+    public function getFormClasses($type)
207
+    {
208
+        return $type ? 'form-'.$type : null;
209
+    }
210
+
211
+    /**
212
+     * Add actions block class
213
+     *
214
+     * @return string
215
+     */
216
+    public function getActionClasses()
217
+    {
218
+        return 'form-actions';
219
+    }
220
+
221
+    ////////////////////////////////////////////////////////////////////
222
+    //////////////////////////// RENDER BLOCKS /////////////////////////
223
+    ////////////////////////////////////////////////////////////////////
224
+
225
+    /**
226
+     * Render an help text
227
+     *
228
+     * @param string $text
229
+     * @param array  $attributes
230
+     *
231
+     * @return Element
232
+     */
233
+    public function createHelp($text, $attributes = array())
234
+    {
235
+        return Element::create('span', $text, $attributes)->addClass('help-inline');
236
+    }
237
+
238
+    /**
239
+     * Render a block help text
240
+     *
241
+     * @param string $text
242
+     * @param array  $attributes
243
+     *
244
+     * @return Element
245
+     */
246
+    public function createBlockHelp($text, $attributes = array())
247
+    {
248
+        return Element::create('p', $text, $attributes)->addClass('help-block');
249
+    }
250
+
251
+    /**
252
+     * Render a disabled field
253
+     *
254
+     * @param Field $field
255
+     *
256
+     * @return Element
257
+     */
258
+    public function createDisabledField(Field $field)
259
+    {
260
+        return Element::create('span', $field->getValue(), $field->getAttributes());
261
+    }
262
+
263
+    /**
264
+     * Render a plain text field
265
+     * Which fallback to a disabled field
266
+     *
267
+     * @param Field $field
268
+     *
269
+     * @return Element
270
+     */
271
+    public function createPlainTextField(Field $field)
272
+    {
273
+        return $this->createDisabledField($field);
274
+    }
275
+
276
+    /**
277
+     * Render an icon
278
+     *
279
+     * @param array $attributes Its general attributes
280
+     *
281
+     * @return string
282
+     */
283
+    public function createIcon($iconType, $attributes = array(), $iconSettings = array())
284
+    {
285
+        // Check for empty icons
286
+        if (!$iconType) {
287
+            return false;
288
+        }
289
+
290
+        // Create tag
291
+        $tag  = Arr::get($iconSettings, 'tag', $this->iconTag);
292
+        $icon = Element::create($tag, null, $attributes);
293
+
294
+        // White icons ignore user overrides to use legacy Bootstrap styling
295
+        if (Str::contains($iconType, 'white')) {
296
+            $iconType = str_replace('white', '', $iconType);
297
+            $iconType = trim($iconType, '-');
298
+            $icon->addClass('icon-white');
299
+            $set    = null;
300
+            $prefix = 'icon';
301
+        } else {
302
+            $set    = Arr::get($iconSettings, 'set', $this->iconSet);
303
+            $prefix = Arr::get($iconSettings, 'prefix', $this->iconPrefix);
304
+        }
305
+        $icon->addClass("$set $prefix-$iconType");
306
+
307
+        return $icon;
308
+    }
309
+
310
+    ////////////////////////////////////////////////////////////////////
311
+    //////////////////////////// WRAP BLOCKS ///////////////////////////
312
+    ////////////////////////////////////////////////////////////////////
313
+
314
+    /**
315
+     * Wrap an item to be prepended or appended to the current field
316
+     *
317
+     * @param  string $item
318
+     *
319
+     * @return string A wrapped item
320
+     */
321
+    public function placeAround($item)
322
+    {
323
+        // Render object
324
+        if (is_object($item) and method_exists($item, '__toString')) {
325
+            $item = $item->__toString();
326
+        }
327
+
328
+        // Return unwrapped if button
329
+        if (strpos($item, '<button') !== false) {
330
+            return $item;
331
+        }
332
+
333
+        return Element::create('span', $item)->addClass('add-on');
334
+    }
335
+
336
+    /**
337
+     * Wrap a field with prepended and appended items
338
+     *
339
+     * @param  Field $field
340
+     * @param  array $prepend
341
+     * @param  array $append
342
+     *
343
+     * @return string A field concatented with prepended and/or appended items
344
+     */
345
+    public function prependAppend($field, $prepend, $append)
346
+    {
347
+        $class = array();
348
+        if ($prepend) {
349
+            $class[] = 'input-prepend';
350
+        }
351
+        if ($append) {
352
+            $class[] = 'input-append';
353
+        }
354
+
355
+        $return = '<div class="'.join(' ', $class).'">';
356
+        $return .= join(null, $prepend);
357
+        $return .= $field->render();
358
+        $return .= join(null, $append);
359
+        $return .= '</div>';
360
+
361
+        return $return;
362
+    }
363
+
364
+    /**
365
+     * Wrap a field with potential additional tags
366
+     *
367
+     * @param  Field $field
368
+     *
369
+     * @return Element A wrapped field
370
+     */
371
+    public function wrapField($field)
372
+    {
373
+        return Element::create('div', $field)->addClass('controls');
374
+    }
375
+
376
+    /**
377
+     * Wrap actions block with potential additional tags
378
+     *
379
+     * @param  Actions $actions
380
+     *
381
+     * @return string A wrapped actions block
382
+     */
383
+    public function wrapActions($actions)
384
+    {
385
+        return $actions;
386
+    }
387 387
 }
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
@@ -12,110 +12,110 @@
 block discarded – undo
12 12
  */
13 13
 class Actions extends FormerObject
14 14
 {
15
-	/**
16
-	 * The Container
17
-	 *
18
-	 * @var Container
19
-	 */
20
-	protected $app;
21
-
22
-	/**
23
-	 * The Actions element
24
-	 *
25
-	 * @var string
26
-	 */
27
-	protected $element = 'div';
28
-
29
-	////////////////////////////////////////////////////////////////////
30
-	/////////////////////////// CORE METHODS ///////////////////////////
31
-	////////////////////////////////////////////////////////////////////
32
-
33
-	/**
34
-	 * Constructs a new Actions block
35
-	 *
36
-	 * @param Container $app
37
-	 * @param array     $value The block content
38
-	 */
39
-	public function __construct(Container $app, $value)
40
-	{
41
-		$this->app   = $app;
42
-		$this->value = $value;
43
-
44
-		// Add specific actions classes to the actions block
45
-		$this->addClass($this->app['former.framework']->getActionClasses());
46
-	}
47
-
48
-	/**
49
-	 * Get the content of the Actions block
50
-	 *
51
-	 * @return string
52
-	 */
53
-	public function getContent()
54
-	{
55
-		$content = array_map(function ($content) {
56
-			return method_exists($content, '__toString') ? (string) $content : $content;
57
-		}, $this->value);
58
-
59
-		return $this->app['former.framework']->wrapActions(implode(' ', $content));
60
-	}
61
-
62
-	/**
63
-	 * Dynamically append actions to the block
64
-	 *
65
-	 * @param string $method     The method
66
-	 * @param array  $parameters Its parameters
67
-	 *
68
-	 * @return Actions
69
-	 */
70
-	public function __call($method, $parameters)
71
-	{
72
-		// Dynamically add buttons to an actions block
73
-		if ($this->isButtonMethod($method)) {
74
-			$text       = Arr::get($parameters, 0);
75
-			$link       = Arr::get($parameters, 1);
76
-			$attributes = Arr::get($parameters, 2);
77
-			if (!$attributes and is_array($link)) {
78
-				$attributes = $link;
79
-			}
80
-
81
-			return $this->createButtonOfType($method, $text, $link, $attributes);
82
-		}
83
-
84
-		return parent::__call($method, $parameters);
85
-	}
86
-
87
-	////////////////////////////////////////////////////////////////////
88
-	////////////////////////////// HELPERS /////////////////////////////
89
-	////////////////////////////////////////////////////////////////////
90
-
91
-	/**
92
-	 * Create a new Button and add it to the actions
93
-	 *
94
-	 * @param string $type       The button type
95
-	 * @param string $name       Its name
96
-	 * @param string $link       A link to point to
97
-	 * @param array  $attributes Its attributes
98
-	 *
99
-	 * @return Actions
100
-	 */
101
-	private function createButtonOfType($type, $name, $link, $attributes)
102
-	{
103
-		$this->value[] = $this->app['former']->$type($name, $link, $attributes)->__toString();
104
-
105
-		return $this;
106
-	}
107
-
108
-	/**
109
-	 * Check if a given method calls a button or not
110
-	 *
111
-	 * @param string $method The method to check
112
-	 *
113
-	 * @return boolean
114
-	 */
115
-	private function isButtonMethod($method)
116
-	{
117
-		$buttons = array('button', 'submit', 'link', 'reset');
118
-
119
-		return (bool) Str::contains($method, $buttons);
120
-	}
15
+    /**
16
+     * The Container
17
+     *
18
+     * @var Container
19
+     */
20
+    protected $app;
21
+
22
+    /**
23
+     * The Actions element
24
+     *
25
+     * @var string
26
+     */
27
+    protected $element = 'div';
28
+
29
+    ////////////////////////////////////////////////////////////////////
30
+    /////////////////////////// CORE METHODS ///////////////////////////
31
+    ////////////////////////////////////////////////////////////////////
32
+
33
+    /**
34
+     * Constructs a new Actions block
35
+     *
36
+     * @param Container $app
37
+     * @param array     $value The block content
38
+     */
39
+    public function __construct(Container $app, $value)
40
+    {
41
+        $this->app   = $app;
42
+        $this->value = $value;
43
+
44
+        // Add specific actions classes to the actions block
45
+        $this->addClass($this->app['former.framework']->getActionClasses());
46
+    }
47
+
48
+    /**
49
+     * Get the content of the Actions block
50
+     *
51
+     * @return string
52
+     */
53
+    public function getContent()
54
+    {
55
+        $content = array_map(function ($content) {
56
+            return method_exists($content, '__toString') ? (string) $content : $content;
57
+        }, $this->value);
58
+
59
+        return $this->app['former.framework']->wrapActions(implode(' ', $content));
60
+    }
61
+
62
+    /**
63
+     * Dynamically append actions to the block
64
+     *
65
+     * @param string $method     The method
66
+     * @param array  $parameters Its parameters
67
+     *
68
+     * @return Actions
69
+     */
70
+    public function __call($method, $parameters)
71
+    {
72
+        // Dynamically add buttons to an actions block
73
+        if ($this->isButtonMethod($method)) {
74
+            $text       = Arr::get($parameters, 0);
75
+            $link       = Arr::get($parameters, 1);
76
+            $attributes = Arr::get($parameters, 2);
77
+            if (!$attributes and is_array($link)) {
78
+                $attributes = $link;
79
+            }
80
+
81
+            return $this->createButtonOfType($method, $text, $link, $attributes);
82
+        }
83
+
84
+        return parent::__call($method, $parameters);
85
+    }
86
+
87
+    ////////////////////////////////////////////////////////////////////
88
+    ////////////////////////////// HELPERS /////////////////////////////
89
+    ////////////////////////////////////////////////////////////////////
90
+
91
+    /**
92
+     * Create a new Button and add it to the actions
93
+     *
94
+     * @param string $type       The button type
95
+     * @param string $name       Its name
96
+     * @param string $link       A link to point to
97
+     * @param array  $attributes Its attributes
98
+     *
99
+     * @return Actions
100
+     */
101
+    private function createButtonOfType($type, $name, $link, $attributes)
102
+    {
103
+        $this->value[] = $this->app['former']->$type($name, $link, $attributes)->__toString();
104
+
105
+        return $this;
106
+    }
107
+
108
+    /**
109
+     * Check if a given method calls a button or not
110
+     *
111
+     * @param string $method The method to check
112
+     *
113
+     * @return boolean
114
+     */
115
+    private function isButtonMethod($method)
116
+    {
117
+        $buttons = array('button', 'submit', 'link', 'reset');
118
+
119
+        return (bool) Str::contains($method, $buttons);
120
+    }
121 121
 }
Please login to merge, or discard this patch.
src/Former/Form/Fields/Choice.php 1 patch
Indentation   +468 added lines, -468 removed lines patch added patch discarded remove patch
@@ -13,477 +13,477 @@
 block discarded – undo
13 13
  */
14 14
 class Choice extends Field
15 15
 {
16
-	/**
17
-	 * Renders the checkables as inline
18
-	 *
19
-	 * @var boolean
20
-	 */
21
-	protected $inline = false;
22
-
23
-	/**
24
-	 * The choice's placeholder
25
-	 *
26
-	 * @var string
27
-	 */
28
-	private $placeholder = null;
29
-
30
-	/**
31
-	 * The choice's options
32
-	 *
33
-	 * @var array
34
-	 */
35
-	protected $options = [
16
+    /**
17
+     * Renders the checkables as inline
18
+     *
19
+     * @var boolean
20
+     */
21
+    protected $inline = false;
22
+
23
+    /**
24
+     * The choice's placeholder
25
+     *
26
+     * @var string
27
+     */
28
+    private $placeholder = null;
29
+
30
+    /**
31
+     * The choice's options
32
+     *
33
+     * @var array
34
+     */
35
+    protected $options = [
36 36
         'isMultiple' => false,
37 37
         'isExpanded' => false,
38 38
     ];
39 39
 
40
-	/**
41
-	 * The choice's choices
42
-	 *
43
-	 * @var array
44
-	 */
45
-	protected $choices = [];
46
-
47
-	/**
48
-	 * The choice's element
49
-	 *
50
-	 * @var string
51
-	 */
52
-	protected $element = 'choice';
53
-
54
-	/**
55
-	 * The choice's self-closing state
56
-	 *
57
-	 * @var boolean
58
-	 */
59
-	protected $isSelfClosing = false;
60
-
61
-	////////////////////////////////////////////////////////////////////
62
-	/////////////////////////// CORE METHODS ///////////////////////////
63
-	////////////////////////////////////////////////////////////////////
64
-
65
-	/**
66
-	 * Easier arguments order for selects
67
-	 *
68
-	 * @param Container $app        The Container instance
69
-	 * @param string    $type       select
70
-	 * @param string    $name       Field name
71
-	 * @param string    $label      Its label
72
-	 * @param array     $choices    The choice's choices
73
-	 * @param string    $selected   The selected choice(s)
74
-	 * @param array     $attributes Attributes
75
-	 */
76
-	public function __construct(Container $app, $type, $name, $label, $choices, $selected, $attributes)
77
-	{
78
-		if ($selected) {
79
-			$this->value = $selected;
80
-		}
81
-		if ($choices) {
82
-			$this->choices($choices);
83
-		}
84
-
85
-		parent::__construct($app, $type, $name, $label, $selected, $attributes);
86
-
87
-		$this->setChoiceType();
88
-
89
-		// Nested models population
90
-		if (Str::contains($this->name, '.') and is_array($this->value) and !empty($this->value) and is_string($this->value[key($this->value)])) {
91
-			$this->fromQuery($this->value);
92
-			$this->value = $selected ?: null;
93
-		}
94
-	}
95
-
96
-	/**
97
-	 * Renders the choice
98
-	 *
99
-	 * @return string A <select> tag
100
-	 */
101
-	public function render()
102
-	{
103
-		$choiceType = $this->getType();
104
-		$this->setFieldClasses();
105
-
106
-		if (!isset($this->attributes['id'])) {
107
-			$this->setAttribute('id', $this->name);
108
-		}
109
-
110
-		switch ($choiceType) {
111
-			case 'select':
112
-				$field = $this->getSelect();
113
-				break;
114
-			case 'checkbox':
115
-			case 'radio':
116
-				$field = $this->getCheckables($choiceType);
117
-				break;
118
-		}
119
-		$this->value = null;
120
-		$content = $field->render();
121
-		return $content;
122
-	}
123
-
124
-	public function getSelect()
125
-	{
126
-		$field = Element::create('select', null, $this->attributes);
127
-
128
-		$name = $this->name;
129
-		if ($this->options['isMultiple']) {
130
-			$field->multiple();
131
-			$name .= '[]';
132
-		}
133
-
134
-		$field->setAttribute('name', $name);
135
-
136
-		$field->nest($this->getOptions());
137
-
138
-		return $field;
139
-	}
140
-
141
-	public function getOptions()
142
-	{
143
-		$children = [];
144
-
145
-		// Add placeholder text if any
146
-		if ($placeholder = $this->getPlaceholder()) {
147
-			$children[] = $placeholder;
148
-		}
149
-
150
-		foreach ($this->choices as $key => $value) {
151
-			if (is_array($value) and !isset($value['value'])) {
152
-				$children[] = $this->getOptGroup($key, $value);
153
-			} else {
154
-				$children[] = $this->getOption($key, $value);
155
-			}
156
-		}
157
-		return $children;
158
-	}
159
-
160
-	public function getOptGroup($label, $options)
161
-	{
162
-		$element = Element::create('optgroup')->label($label);
163
-		$children = [];
164
-		foreach ($options as $key => $value) {
165
-			$option = $this->getOption($key, $value);
166
-			$children[] = $option;
167
-		}
168
-		$element->nest($children);
169
-
170
-		return $element;
171
-	}
172
-
173
-	public function getOption($key, $value)
174
-	{
175
-		if (is_array($value) and isset($value['value'])) {
176
-			$attributes = $value;
177
-			$text = $key;
178
-			$key = null;
179
-		} else {
180
-			$attributes = array('value' => $key);
181
-			$text = $value;
182
-		}
183
-
184
-		$element = Element::create('option', $text, $attributes);
185
-		if ($this->hasValue($attributes['value'])) {
186
-			$element->selected('selected');
187
-		}
188
-
189
-		return $element;
190
-	}
191
-
192
-	public function getCheckables($choiceType)
193
-	{
194
-		if (!(is_array($this->value) || $this->value instanceof \ArrayAccess)) {
195
-			$this->value = explode(',', $this->value);
196
-		}
197
-
198
-		$disabled = isset($this->attributes['disabled']);
199
-		unset($this->attributes['disabled']);
200
-
201
-		$field = Element::create('div', null, $this->attributes);
202
-
203
-		$children = [];
204
-		foreach ($this->choices as $key => $value) {
205
-			$attributes = [];
206
-
207
-			if (is_array($value) and isset($value['value'])) {
208
-				$attributes = $value;
209
-				$label = $key;
210
-				$inputValue = $value['value'];
211
-			} else {
212
-				$attributes = [];
213
-				$label = $value;
214
-				$inputValue = $key;
215
-			}
216
-
217
-			if ($disabled) {
218
-				$attributes['disabled'] = true;
219
-			}
220
-
221
-			if(isset($attributes['name'])) {
222
-				$name = $attributes['name'];
223
-				unset($attributes['name']);
224
-			} else {
225
-				$name = $this->name;
226
-			}
227
-			if ($this->options['isMultiple']) {
228
-				$name .= '[]';
229
-			}
230
-
231
-			if(!isset($attributes['id'])) {
232
-				$attributes['id'] = $this->id.'_'.count($children);
233
-			}
234
-
235
-			// If inline items, add class
236
-			$isInline = $this->inline ? ' '.$this->app['former.framework']->getInlineLabelClass($this) : null;
237
-
238
-			// In Bootsrap 3, don't append the the checkable type (radio/checkbox) as a class if
239
-			// rendering inline.
240
-			$class = $this->app['former']->framework() == 'TwitterBootstrap3' ? trim($isInline) : $choiceType.$isInline;
241
-
242
-			$element = Input::create($choiceType, $name, $inputValue, $attributes);
243
-
244
-			// $element->setAttribute('name', $name);
245
-
246
-			if ($this->hasValue($inputValue)) {
247
-				$element->checked('checked');
248
-			}
249
-			// $attributes['value'] = $key;
250
-			if (!$label) {
251
-				$element = (is_object($field)) ? $field->render() : $field;
252
-			} else {
253
-				$rendered = $element->render();
254
-				$labelElement = Element::create('label', $rendered.$label);
255
-				$element = $labelElement->for($attributes['id'])->class($class);
256
-			}
257
-
258
-			// If BS3, if checkables are stacked, wrap them in a div with the checkable type
259
-			if (!$isInline && $this->app['former']->framework() == 'TwitterBootstrap3') {
260
-				$wrapper = Element::create('div', $element->render())->class($choiceType);
261
-				if ($disabled) {
262
-					$wrapper->addClass('disabled');
263
-				}
264
-				$element = $wrapper;
265
-			}
266
-
267
-			$children[] = $element;
268
-		}
269
-		$field->nest($children);
270
-
271
-		return $field;
272
-	}
273
-
274
-	/**
275
-	 * Get the choice's placeholder
276
-	 *
277
-	 * @return Element
278
-	 */
279
-	protected function getPlaceholder()
280
-	{
281
-		if (!$this->placeholder) {
282
-			return false;
283
-		}
284
-
285
-		$attributes = array('value' => '', 'disabled' => 'disabled');
286
-		if (!(array)$this->value) {
287
-			$attributes['selected'] = 'selected';
288
-		}
289
-
290
-		return Element::create('option', $this->placeholder, $attributes);
291
-	}
292
-
293
-	/**
294
-	 * Sets the element's type based on options
295
-	 *
296
-	 * @return this
297
-	 */
298
-	protected function setChoiceType()
299
-	{
300
-		if ($this->options['isExpanded'] && !$this->options['isMultiple']) {
301
-			$this->setType('radio');
302
-		} elseif ($this->options['isExpanded'] && $this->options['isMultiple']) {
303
-			$this->setType('checkbox');
304
-		} else {
305
-			$this->setType('select');
306
-		}
307
-		return $this;
308
-	}
309
-
310
-	/**
311
-	 * Select a value in the field's children
312
-	 *
313
-	 * @param mixed   $value
314
-	 *
315
-	 * @return bool
316
-	 */
317
-	protected function hasValue($choiceValue)
318
-	{
319
-		foreach ((array)$this->value as $key => $value) {
320
-			if (is_object($value) && method_exists($value, 'getKey')) {
321
-				$value = $value->getKey();
322
-			}
323
-			if ($choiceValue === $value || is_numeric($value) && $choiceValue === (int)$value) {
324
-				return true;
325
-			}
326
-		}
327
-		return false;
328
-	}
329
-
330
-	////////////////////////////////////////////////////////////////////
331
-	////////////////////////// FIELD METHODS ///////////////////////////
332
-	////////////////////////////////////////////////////////////////////
333
-
334
-	/**
335
-	 * Set the choices
336
-	 *
337
-	 * @param  array   $_choices     The choices as an array
338
-	 * @param  mixed   $selected     Facultative selected entry
339
-	 * @param  boolean $valuesAsKeys Whether the array's values should be used as
340
-	 *                               the option's values instead of the array's keys
341
-	 */
342
-	public function addChoice($value, $key = null)
343
-	{
344
-		$this->choices[$key ?? $value] = $value;
345
-
346
-		return $this;
347
-	}
348
-
349
-	/**
350
-	 * Set the choices
351
-	 *
352
-	 * @param  array   $_choices     The choices as an array
353
-	 * @param  mixed   $selected     Facultative selected entry
354
-	 * @param  boolean $valuesAsKeys Whether the array's values should be used as
355
-	 *                               the option's values instead of the array's keys
356
-	 */
357
-	public function choices($_choices, $valuesAsKeys = false)
358
-	{
359
-		$choices = (array) $_choices;
360
-
361
-		// If valuesAsKeys is true, use the values as keys
362
-		if ($valuesAsKeys) {
363
-			foreach ($choices as $value) {
364
-				$this->addChoice($value, $value);
365
-			}
366
-		} else {
367
-			foreach ($choices as $key => $value) {
368
-				$this->addChoice($value, $key);
369
-			}
370
-		}
371
-
372
-		return $this;
373
-	}
374
-
375
-	/**
376
-	 * Creates a list of choices from a range
377
-	 *
378
-	 * @param  integer $from
379
-	 * @param  integer $to
380
-	 * @param  integer $step
381
-	 */
382
-	public function range($from, $to, $step = 1)
383
-	{
384
-		$range = range($from, $to, $step);
385
-		$this->choices($range, true);
386
-
387
-		return $this;
388
-	}
389
-
390
-	/**
391
-	 * Use the results from a Fluent/Eloquent query as choices
392
-	 *
393
-	 * @param  array           $results    An array of Eloquent models
394
-	 * @param  string|function $text       The value to use as text
395
-	 * @param  string|array    $attributes The data to use as attributes
396
-	 * @param  string	       $selected   The default selected item
397
-	 */
398
-	public function fromQuery($results, $text = null, $attributes = null, $selected = null)
399
-	{
400
-		$this->choices(Helpers::queryToArray($results, $text, $attributes))->value($selected);
401
-
402
-		return $this;
403
-	}
404
-
405
-	/**
406
-	 * Add a placeholder to the current select
407
-	 *
408
-	 * @param  string $placeholder The placeholder text
409
-	 */
410
-	public function placeholder($placeholder)
411
-	{
412
-		$this->placeholder = Helpers::translate($placeholder);
413
-
414
-		return $this;
415
-	}
416
-
417
-	/**
418
-	 * Set isMultiple
419
-	 *
420
-	 * @param boolean $isMultiple
421
-	 * @return $this
422
-	 */
423
-	public function multiple($isMultiple = true)
424
-	{
425
-		$this->options['isMultiple'] = $isMultiple;
426
-		$this->setChoiceType();
427
-
428
-		return $this;
429
-	}
430
-
431
-	/**
432
-	 * Set isExpanded
433
-	 *
434
-	 * @param boolean $isExpanded
435
-	 * @return $this
436
-	 */
437
-	public function expanded($isExpanded = true)
438
-	{
439
-		$this->options['isExpanded'] = $isExpanded;
440
-		$this->setChoiceType();
441
-
442
-		return $this;
443
-	}
444
-
445
-	/**
446
-	 * Set the choices as inline (for expanded items)
447
-	 */
448
-	public function inline($isInline = true)
449
-	{
450
-		$this->inline = $isInline;
451
-
452
-		return $this;
453
-	}
454
-
455
-	/**
456
-	 * Set the choices as stacked (for expanded items)
457
-	 */
458
-	public function stacked($isStacked = true)
459
-	{
460
-		$this->inline = !$isStacked;
461
-
462
-		return $this;
463
-	}
464
-
465
-	/**
466
-	 * Check if field is a checkbox or a radio
467
-	 *
468
-	 * @return boolean
469
-	 */
470
-	public function isCheckable()
471
-	{
472
-		return $this->options['isExpanded'];
473
-	}
474
-
475
-	////////////////////////////////////////////////////////////////////
476
-	////////////////////////////// HELPERS /////////////////////////////
477
-	////////////////////////////////////////////////////////////////////
478
-
479
-	/**
480
-	 * Returns the current choices in memory for manipulations
481
-	 *
482
-	 * @return array The current choices array
483
-	 */
484
-	public function getChoices()
485
-	{
486
-		return $this->choices;
487
-	}
40
+    /**
41
+     * The choice's choices
42
+     *
43
+     * @var array
44
+     */
45
+    protected $choices = [];
46
+
47
+    /**
48
+     * The choice's element
49
+     *
50
+     * @var string
51
+     */
52
+    protected $element = 'choice';
53
+
54
+    /**
55
+     * The choice's self-closing state
56
+     *
57
+     * @var boolean
58
+     */
59
+    protected $isSelfClosing = false;
60
+
61
+    ////////////////////////////////////////////////////////////////////
62
+    /////////////////////////// CORE METHODS ///////////////////////////
63
+    ////////////////////////////////////////////////////////////////////
64
+
65
+    /**
66
+     * Easier arguments order for selects
67
+     *
68
+     * @param Container $app        The Container instance
69
+     * @param string    $type       select
70
+     * @param string    $name       Field name
71
+     * @param string    $label      Its label
72
+     * @param array     $choices    The choice's choices
73
+     * @param string    $selected   The selected choice(s)
74
+     * @param array     $attributes Attributes
75
+     */
76
+    public function __construct(Container $app, $type, $name, $label, $choices, $selected, $attributes)
77
+    {
78
+        if ($selected) {
79
+            $this->value = $selected;
80
+        }
81
+        if ($choices) {
82
+            $this->choices($choices);
83
+        }
84
+
85
+        parent::__construct($app, $type, $name, $label, $selected, $attributes);
86
+
87
+        $this->setChoiceType();
88
+
89
+        // Nested models population
90
+        if (Str::contains($this->name, '.') and is_array($this->value) and !empty($this->value) and is_string($this->value[key($this->value)])) {
91
+            $this->fromQuery($this->value);
92
+            $this->value = $selected ?: null;
93
+        }
94
+    }
95
+
96
+    /**
97
+     * Renders the choice
98
+     *
99
+     * @return string A <select> tag
100
+     */
101
+    public function render()
102
+    {
103
+        $choiceType = $this->getType();
104
+        $this->setFieldClasses();
105
+
106
+        if (!isset($this->attributes['id'])) {
107
+            $this->setAttribute('id', $this->name);
108
+        }
109
+
110
+        switch ($choiceType) {
111
+            case 'select':
112
+                $field = $this->getSelect();
113
+                break;
114
+            case 'checkbox':
115
+            case 'radio':
116
+                $field = $this->getCheckables($choiceType);
117
+                break;
118
+        }
119
+        $this->value = null;
120
+        $content = $field->render();
121
+        return $content;
122
+    }
123
+
124
+    public function getSelect()
125
+    {
126
+        $field = Element::create('select', null, $this->attributes);
127
+
128
+        $name = $this->name;
129
+        if ($this->options['isMultiple']) {
130
+            $field->multiple();
131
+            $name .= '[]';
132
+        }
133
+
134
+        $field->setAttribute('name', $name);
135
+
136
+        $field->nest($this->getOptions());
137
+
138
+        return $field;
139
+    }
140
+
141
+    public function getOptions()
142
+    {
143
+        $children = [];
144
+
145
+        // Add placeholder text if any
146
+        if ($placeholder = $this->getPlaceholder()) {
147
+            $children[] = $placeholder;
148
+        }
149
+
150
+        foreach ($this->choices as $key => $value) {
151
+            if (is_array($value) and !isset($value['value'])) {
152
+                $children[] = $this->getOptGroup($key, $value);
153
+            } else {
154
+                $children[] = $this->getOption($key, $value);
155
+            }
156
+        }
157
+        return $children;
158
+    }
159
+
160
+    public function getOptGroup($label, $options)
161
+    {
162
+        $element = Element::create('optgroup')->label($label);
163
+        $children = [];
164
+        foreach ($options as $key => $value) {
165
+            $option = $this->getOption($key, $value);
166
+            $children[] = $option;
167
+        }
168
+        $element->nest($children);
169
+
170
+        return $element;
171
+    }
172
+
173
+    public function getOption($key, $value)
174
+    {
175
+        if (is_array($value) and isset($value['value'])) {
176
+            $attributes = $value;
177
+            $text = $key;
178
+            $key = null;
179
+        } else {
180
+            $attributes = array('value' => $key);
181
+            $text = $value;
182
+        }
183
+
184
+        $element = Element::create('option', $text, $attributes);
185
+        if ($this->hasValue($attributes['value'])) {
186
+            $element->selected('selected');
187
+        }
188
+
189
+        return $element;
190
+    }
191
+
192
+    public function getCheckables($choiceType)
193
+    {
194
+        if (!(is_array($this->value) || $this->value instanceof \ArrayAccess)) {
195
+            $this->value = explode(',', $this->value);
196
+        }
197
+
198
+        $disabled = isset($this->attributes['disabled']);
199
+        unset($this->attributes['disabled']);
200
+
201
+        $field = Element::create('div', null, $this->attributes);
202
+
203
+        $children = [];
204
+        foreach ($this->choices as $key => $value) {
205
+            $attributes = [];
206
+
207
+            if (is_array($value) and isset($value['value'])) {
208
+                $attributes = $value;
209
+                $label = $key;
210
+                $inputValue = $value['value'];
211
+            } else {
212
+                $attributes = [];
213
+                $label = $value;
214
+                $inputValue = $key;
215
+            }
216
+
217
+            if ($disabled) {
218
+                $attributes['disabled'] = true;
219
+            }
220
+
221
+            if(isset($attributes['name'])) {
222
+                $name = $attributes['name'];
223
+                unset($attributes['name']);
224
+            } else {
225
+                $name = $this->name;
226
+            }
227
+            if ($this->options['isMultiple']) {
228
+                $name .= '[]';
229
+            }
230
+
231
+            if(!isset($attributes['id'])) {
232
+                $attributes['id'] = $this->id.'_'.count($children);
233
+            }
234
+
235
+            // If inline items, add class
236
+            $isInline = $this->inline ? ' '.$this->app['former.framework']->getInlineLabelClass($this) : null;
237
+
238
+            // In Bootsrap 3, don't append the the checkable type (radio/checkbox) as a class if
239
+            // rendering inline.
240
+            $class = $this->app['former']->framework() == 'TwitterBootstrap3' ? trim($isInline) : $choiceType.$isInline;
241
+
242
+            $element = Input::create($choiceType, $name, $inputValue, $attributes);
243
+
244
+            // $element->setAttribute('name', $name);
245
+
246
+            if ($this->hasValue($inputValue)) {
247
+                $element->checked('checked');
248
+            }
249
+            // $attributes['value'] = $key;
250
+            if (!$label) {
251
+                $element = (is_object($field)) ? $field->render() : $field;
252
+            } else {
253
+                $rendered = $element->render();
254
+                $labelElement = Element::create('label', $rendered.$label);
255
+                $element = $labelElement->for($attributes['id'])->class($class);
256
+            }
257
+
258
+            // If BS3, if checkables are stacked, wrap them in a div with the checkable type
259
+            if (!$isInline && $this->app['former']->framework() == 'TwitterBootstrap3') {
260
+                $wrapper = Element::create('div', $element->render())->class($choiceType);
261
+                if ($disabled) {
262
+                    $wrapper->addClass('disabled');
263
+                }
264
+                $element = $wrapper;
265
+            }
266
+
267
+            $children[] = $element;
268
+        }
269
+        $field->nest($children);
270
+
271
+        return $field;
272
+    }
273
+
274
+    /**
275
+     * Get the choice's placeholder
276
+     *
277
+     * @return Element
278
+     */
279
+    protected function getPlaceholder()
280
+    {
281
+        if (!$this->placeholder) {
282
+            return false;
283
+        }
284
+
285
+        $attributes = array('value' => '', 'disabled' => 'disabled');
286
+        if (!(array)$this->value) {
287
+            $attributes['selected'] = 'selected';
288
+        }
289
+
290
+        return Element::create('option', $this->placeholder, $attributes);
291
+    }
292
+
293
+    /**
294
+     * Sets the element's type based on options
295
+     *
296
+     * @return this
297
+     */
298
+    protected function setChoiceType()
299
+    {
300
+        if ($this->options['isExpanded'] && !$this->options['isMultiple']) {
301
+            $this->setType('radio');
302
+        } elseif ($this->options['isExpanded'] && $this->options['isMultiple']) {
303
+            $this->setType('checkbox');
304
+        } else {
305
+            $this->setType('select');
306
+        }
307
+        return $this;
308
+    }
309
+
310
+    /**
311
+     * Select a value in the field's children
312
+     *
313
+     * @param mixed   $value
314
+     *
315
+     * @return bool
316
+     */
317
+    protected function hasValue($choiceValue)
318
+    {
319
+        foreach ((array)$this->value as $key => $value) {
320
+            if (is_object($value) && method_exists($value, 'getKey')) {
321
+                $value = $value->getKey();
322
+            }
323
+            if ($choiceValue === $value || is_numeric($value) && $choiceValue === (int)$value) {
324
+                return true;
325
+            }
326
+        }
327
+        return false;
328
+    }
329
+
330
+    ////////////////////////////////////////////////////////////////////
331
+    ////////////////////////// FIELD METHODS ///////////////////////////
332
+    ////////////////////////////////////////////////////////////////////
333
+
334
+    /**
335
+     * Set the choices
336
+     *
337
+     * @param  array   $_choices     The choices as an array
338
+     * @param  mixed   $selected     Facultative selected entry
339
+     * @param  boolean $valuesAsKeys Whether the array's values should be used as
340
+     *                               the option's values instead of the array's keys
341
+     */
342
+    public function addChoice($value, $key = null)
343
+    {
344
+        $this->choices[$key ?? $value] = $value;
345
+
346
+        return $this;
347
+    }
348
+
349
+    /**
350
+     * Set the choices
351
+     *
352
+     * @param  array   $_choices     The choices as an array
353
+     * @param  mixed   $selected     Facultative selected entry
354
+     * @param  boolean $valuesAsKeys Whether the array's values should be used as
355
+     *                               the option's values instead of the array's keys
356
+     */
357
+    public function choices($_choices, $valuesAsKeys = false)
358
+    {
359
+        $choices = (array) $_choices;
360
+
361
+        // If valuesAsKeys is true, use the values as keys
362
+        if ($valuesAsKeys) {
363
+            foreach ($choices as $value) {
364
+                $this->addChoice($value, $value);
365
+            }
366
+        } else {
367
+            foreach ($choices as $key => $value) {
368
+                $this->addChoice($value, $key);
369
+            }
370
+        }
371
+
372
+        return $this;
373
+    }
374
+
375
+    /**
376
+     * Creates a list of choices from a range
377
+     *
378
+     * @param  integer $from
379
+     * @param  integer $to
380
+     * @param  integer $step
381
+     */
382
+    public function range($from, $to, $step = 1)
383
+    {
384
+        $range = range($from, $to, $step);
385
+        $this->choices($range, true);
386
+
387
+        return $this;
388
+    }
389
+
390
+    /**
391
+     * Use the results from a Fluent/Eloquent query as choices
392
+     *
393
+     * @param  array           $results    An array of Eloquent models
394
+     * @param  string|function $text       The value to use as text
395
+     * @param  string|array    $attributes The data to use as attributes
396
+     * @param  string	       $selected   The default selected item
397
+     */
398
+    public function fromQuery($results, $text = null, $attributes = null, $selected = null)
399
+    {
400
+        $this->choices(Helpers::queryToArray($results, $text, $attributes))->value($selected);
401
+
402
+        return $this;
403
+    }
404
+
405
+    /**
406
+     * Add a placeholder to the current select
407
+     *
408
+     * @param  string $placeholder The placeholder text
409
+     */
410
+    public function placeholder($placeholder)
411
+    {
412
+        $this->placeholder = Helpers::translate($placeholder);
413
+
414
+        return $this;
415
+    }
416
+
417
+    /**
418
+     * Set isMultiple
419
+     *
420
+     * @param boolean $isMultiple
421
+     * @return $this
422
+     */
423
+    public function multiple($isMultiple = true)
424
+    {
425
+        $this->options['isMultiple'] = $isMultiple;
426
+        $this->setChoiceType();
427
+
428
+        return $this;
429
+    }
430
+
431
+    /**
432
+     * Set isExpanded
433
+     *
434
+     * @param boolean $isExpanded
435
+     * @return $this
436
+     */
437
+    public function expanded($isExpanded = true)
438
+    {
439
+        $this->options['isExpanded'] = $isExpanded;
440
+        $this->setChoiceType();
441
+
442
+        return $this;
443
+    }
444
+
445
+    /**
446
+     * Set the choices as inline (for expanded items)
447
+     */
448
+    public function inline($isInline = true)
449
+    {
450
+        $this->inline = $isInline;
451
+
452
+        return $this;
453
+    }
454
+
455
+    /**
456
+     * Set the choices as stacked (for expanded items)
457
+     */
458
+    public function stacked($isStacked = true)
459
+    {
460
+        $this->inline = !$isStacked;
461
+
462
+        return $this;
463
+    }
464
+
465
+    /**
466
+     * Check if field is a checkbox or a radio
467
+     *
468
+     * @return boolean
469
+     */
470
+    public function isCheckable()
471
+    {
472
+        return $this->options['isExpanded'];
473
+    }
474
+
475
+    ////////////////////////////////////////////////////////////////////
476
+    ////////////////////////////// HELPERS /////////////////////////////
477
+    ////////////////////////////////////////////////////////////////////
478
+
479
+    /**
480
+     * Returns the current choices in memory for manipulations
481
+     *
482
+     * @return array The current choices array
483
+     */
484
+    public function getChoices()
485
+    {
486
+        return $this->choices;
487
+    }
488 488
 
489 489
 }
Please login to merge, or discard this patch.
src/Former/Form/Fields/Select.php 1 patch
Indentation   +293 added lines, -293 removed lines patch added patch discarded remove patch
@@ -13,297 +13,297 @@
 block discarded – undo
13 13
 class Select extends Field
14 14
 {
15 15
 
16
-	/**
17
-	 * The select's placeholder
18
-	 *
19
-	 * @var string
20
-	 */
21
-	private $placeholder = null;
22
-
23
-	/**
24
-	 * The Select's options
25
-	 *
26
-	 * @var array
27
-	 */
28
-	protected $options;
29
-
30
-	/**
31
-	 * The select's element
32
-	 *
33
-	 * @var string
34
-	 */
35
-	protected $element = 'select';
36
-
37
-	/**
38
-	 * The select's self-closing state
39
-	 *
40
-	 * @var boolean
41
-	 */
42
-	protected $isSelfClosing = false;
43
-
44
-	////////////////////////////////////////////////////////////////////
45
-	/////////////////////////// CORE METHODS ///////////////////////////
46
-	////////////////////////////////////////////////////////////////////
47
-
48
-	/**
49
-	 * Easier arguments order for selects
50
-	 *
51
-	 * @param Container $app        The Container instance
52
-	 * @param string    $type       select
53
-	 * @param string    $name       Field name
54
-	 * @param string    $label      Its label
55
-	 * @param array     $options    The select's options
56
-	 * @param string    $selected   The selected option
57
-	 * @param array     $attributes Attributes
58
-	 */
59
-	public function __construct(Container $app, $type, $name, $label, $options, $selected, $attributes)
60
-	{
61
-		if ($selected) {
62
-			$this->value = $selected;
63
-		}
64
-		if ($options) {
65
-			$this->options($options);
66
-		}
67
-
68
-		parent::__construct($app, $type, $name, $label, $selected, $attributes);
69
-
70
-		// Nested models population
71
-		if (Str::contains($this->name, '.') and is_array($this->value) and !empty($this->value) and is_string($this->value[key($this->value)])) {
72
-			$this->fromQuery($this->value);
73
-			$this->value = $selected ?: null;
74
-		}
75
-	}
76
-
77
-	/**
78
-	 * Renders the select
79
-	 *
80
-	 * @return string A <select> tag
81
-	 */
82
-	public function render()
83
-	{
84
-		// Multiselects
85
-		if ($this->isOfType('multiselect')) {
86
-			if (!isset($this->attributes['id'])) {
87
-				$this->setAttribute('id', $this->name);
88
-			}
89
-
90
-			$this->multiple();
91
-			$this->name .= '[]';
92
-		}
93
-
94
-		if ( ! $this->value instanceOf \ArrayAccess) {
95
-			$this->value = (array) $this->value;
96
-		}
97
-
98
-		// Mark selected values as selected
99
-		if ($this->hasChildren() and !empty($this->value)) {
100
-			foreach ($this->value as $value) {
101
-				if (is_object($value) && method_exists($value, 'getKey')) {
102
-					$value = $value->getKey();
103
-				}
104
-				$this->selectValue($value);
105
-			}
106
-		}
107
-
108
-		// Add placeholder text if any
109
-		if ($placeholder = $this->getPlaceholder()) {
110
-			array_unshift($this->children, $placeholder);
111
-		}
112
-
113
-		$this->value = null;
114
-
115
-		return parent::render();
116
-	}
117
-
118
-	/**
119
-	 * Select a value in the field's children
120
-	 *
121
-	 * @param mixed   $value
122
-	 * @param Element $parent
123
-	 *
124
-	 * @return void
125
-	 */
126
-	protected function selectValue($value, $parent = null)
127
-	{
128
-		// If no parent element defined, use direct children
129
-		if (!$parent) {
130
-			$parent = $this;
131
-		}
132
-
133
-		foreach ($parent->getChildren() as $child) {
134
-			// Search by value
135
-
136
-			if ($child->getAttribute('value') === $value || is_numeric($value) && $child->getAttribute('value') === (int)$value ) {
137
-				$child->selected('selected');
138
-			}
139
-
140
-			// Else iterate over subchilds
141
-			if ($child->hasChildren()) {
142
-				$this->selectValue($value, $child);
143
-			}
144
-		}
145
-	}
146
-
147
-	/**
148
-	 * Get the Select's placeholder
149
-	 *
150
-	 * @return Element
151
-	 */
152
-	protected function getPlaceholder()
153
-	{
154
-		if (!$this->placeholder) {
155
-			return false;
156
-		}
157
-
158
-		$attributes = array('value' => '', 'disabled' => 'disabled');
159
-		if (!$this->value) {
160
-			$attributes['selected'] = 'selected';
161
-		}
162
-
163
-		return Element::create('option', $this->placeholder, $attributes);
164
-	}
165
-
166
-	////////////////////////////////////////////////////////////////////
167
-	////////////////////////// FIELD METHODS ///////////////////////////
168
-	////////////////////////////////////////////////////////////////////
169
-
170
-	/**
171
-	 * Set the select options
172
-	 *
173
-	 * @param  array   $_options     The options as an array
174
-	 * @param  mixed   $selected     Facultative selected entry
175
-	 * @param  boolean $valuesAsKeys Whether the array's values should be used as
176
-	 *                               the option's values instead of the array's keys
177
-	 */
178
-	public function options($_options, $selected = null, $valuesAsKeys = false)
179
-	{
180
-		$options = array();
181
-
182
-		// If valuesAsKeys is true, use the values as keys
183
-		if ($valuesAsKeys) {
184
-			foreach ($_options as $v) {
185
-				$options[$v] = $v;
186
-			}
187
-		} else {
188
-			$options = $_options;
189
-		}
190
-
191
-		// Add the various options
192
-		foreach ($options as $value => $text) {
193
-			if (is_array($text) and isset($text['value'])) {
194
-				$attributes = $text;
195
-				$text       = $value;
196
-				$value      = null;
197
-			} else {
198
-				$attributes = array();
199
-			}
200
-			$this->addOption($text, $value, $attributes);
201
-		}
202
-
203
-		// Set the selected value
204
-		if (!is_null($selected)) {
205
-			$this->select($selected);
206
-		}
207
-
208
-		return $this;
209
-	}
210
-
211
-	/**
212
-	 * Creates a list of options from a range
213
-	 *
214
-	 * @param  integer $from
215
-	 * @param  integer $to
216
-	 * @param  integer $step
217
-	 */
218
-	public function range($from, $to, $step = 1)
219
-	{
220
-		$range = range($from, $to, $step);
221
-		$this->options($range, null, true);
222
-
223
-		return $this;
224
-	}
225
-
226
-	/**
227
-	 * Add an option to the Select's options
228
-	 *
229
-	 * @param array|string $text       It's value or an array of values
230
-	 * @param string       $value      It's text
231
-	 * @param array        $attributes The option's attributes
232
-	 */
233
-	public function addOption($text = null, $value = null, $attributes = array())
234
-	{
235
-		// Get the option's value
236
-		$childrenKey = !is_null($value) ? $value : sizeof($this->children);
237
-
238
-		// If we passed an options group
239
-		if (is_array($text)) {
240
-			$this->children[$childrenKey] = Element::create('optgroup')->label($value);
241
-			foreach ($text as $key => $value) {
242
-				$option = Element::create('option', $value)->setAttribute('value', $key);
243
-				$this->children[$childrenKey]->nest($option);
244
-			}
245
-			// Else if it's a simple option
246
-		} else {
247
-			if (!isset($attributes['value'])) {
248
-				$attributes['value'] = $value;
249
-			}
250
-
251
-			$this->children[$attributes['value']] = Element::create('option', $text)->setAttributes($attributes);
252
-		}
253
-
254
-		return $this;
255
-	}
256
-
257
-	/**
258
-	 * Use the results from a Fluent/Eloquent query as options
259
-	 *
260
-	 * @param  array           $results    An array of Eloquent models
261
-	 * @param  string|function $text       The value to use as text
262
-	 * @param  string|array    $attributes The data to use as attributes
263
-	 * @param  string	   $selected   The default selected item
264
-	 */
265
-	public function fromQuery($results, $text = null, $attributes = null, $selected = null)
266
-	{
267
-		$this->options(Helpers::queryToArray($results, $text, $attributes), $selected);
268
-
269
-		return $this;
270
-	}
271
-
272
-	/**
273
-	 * Select a particular list item
274
-	 *
275
-	 * @param  mixed $selected Selected item
276
-	 */
277
-	public function select($selected)
278
-	{
279
-		$this->value = $selected;
280
-
281
-		return $this;
282
-	}
283
-
284
-	/**
285
-	 * Add a placeholder to the current select
286
-	 *
287
-	 * @param  string $placeholder The placeholder text
288
-	 */
289
-	public function placeholder($placeholder)
290
-	{
291
-		$this->placeholder = Helpers::translate($placeholder);
292
-
293
-		return $this;
294
-	}
295
-
296
-	////////////////////////////////////////////////////////////////////
297
-	////////////////////////////// HELPERS /////////////////////////////
298
-	////////////////////////////////////////////////////////////////////
299
-
300
-	/**
301
-	 * Returns the current options in memory for manipulations
302
-	 *
303
-	 * @return array The current options array
304
-	 */
305
-	public function getOptions()
306
-	{
307
-		return $this->children;
308
-	}
16
+    /**
17
+     * The select's placeholder
18
+     *
19
+     * @var string
20
+     */
21
+    private $placeholder = null;
22
+
23
+    /**
24
+     * The Select's options
25
+     *
26
+     * @var array
27
+     */
28
+    protected $options;
29
+
30
+    /**
31
+     * The select's element
32
+     *
33
+     * @var string
34
+     */
35
+    protected $element = 'select';
36
+
37
+    /**
38
+     * The select's self-closing state
39
+     *
40
+     * @var boolean
41
+     */
42
+    protected $isSelfClosing = false;
43
+
44
+    ////////////////////////////////////////////////////////////////////
45
+    /////////////////////////// CORE METHODS ///////////////////////////
46
+    ////////////////////////////////////////////////////////////////////
47
+
48
+    /**
49
+     * Easier arguments order for selects
50
+     *
51
+     * @param Container $app        The Container instance
52
+     * @param string    $type       select
53
+     * @param string    $name       Field name
54
+     * @param string    $label      Its label
55
+     * @param array     $options    The select's options
56
+     * @param string    $selected   The selected option
57
+     * @param array     $attributes Attributes
58
+     */
59
+    public function __construct(Container $app, $type, $name, $label, $options, $selected, $attributes)
60
+    {
61
+        if ($selected) {
62
+            $this->value = $selected;
63
+        }
64
+        if ($options) {
65
+            $this->options($options);
66
+        }
67
+
68
+        parent::__construct($app, $type, $name, $label, $selected, $attributes);
69
+
70
+        // Nested models population
71
+        if (Str::contains($this->name, '.') and is_array($this->value) and !empty($this->value) and is_string($this->value[key($this->value)])) {
72
+            $this->fromQuery($this->value);
73
+            $this->value = $selected ?: null;
74
+        }
75
+    }
76
+
77
+    /**
78
+     * Renders the select
79
+     *
80
+     * @return string A <select> tag
81
+     */
82
+    public function render()
83
+    {
84
+        // Multiselects
85
+        if ($this->isOfType('multiselect')) {
86
+            if (!isset($this->attributes['id'])) {
87
+                $this->setAttribute('id', $this->name);
88
+            }
89
+
90
+            $this->multiple();
91
+            $this->name .= '[]';
92
+        }
93
+
94
+        if ( ! $this->value instanceOf \ArrayAccess) {
95
+            $this->value = (array) $this->value;
96
+        }
97
+
98
+        // Mark selected values as selected
99
+        if ($this->hasChildren() and !empty($this->value)) {
100
+            foreach ($this->value as $value) {
101
+                if (is_object($value) && method_exists($value, 'getKey')) {
102
+                    $value = $value->getKey();
103
+                }
104
+                $this->selectValue($value);
105
+            }
106
+        }
107
+
108
+        // Add placeholder text if any
109
+        if ($placeholder = $this->getPlaceholder()) {
110
+            array_unshift($this->children, $placeholder);
111
+        }
112
+
113
+        $this->value = null;
114
+
115
+        return parent::render();
116
+    }
117
+
118
+    /**
119
+     * Select a value in the field's children
120
+     *
121
+     * @param mixed   $value
122
+     * @param Element $parent
123
+     *
124
+     * @return void
125
+     */
126
+    protected function selectValue($value, $parent = null)
127
+    {
128
+        // If no parent element defined, use direct children
129
+        if (!$parent) {
130
+            $parent = $this;
131
+        }
132
+
133
+        foreach ($parent->getChildren() as $child) {
134
+            // Search by value
135
+
136
+            if ($child->getAttribute('value') === $value || is_numeric($value) && $child->getAttribute('value') === (int)$value ) {
137
+                $child->selected('selected');
138
+            }
139
+
140
+            // Else iterate over subchilds
141
+            if ($child->hasChildren()) {
142
+                $this->selectValue($value, $child);
143
+            }
144
+        }
145
+    }
146
+
147
+    /**
148
+     * Get the Select's placeholder
149
+     *
150
+     * @return Element
151
+     */
152
+    protected function getPlaceholder()
153
+    {
154
+        if (!$this->placeholder) {
155
+            return false;
156
+        }
157
+
158
+        $attributes = array('value' => '', 'disabled' => 'disabled');
159
+        if (!$this->value) {
160
+            $attributes['selected'] = 'selected';
161
+        }
162
+
163
+        return Element::create('option', $this->placeholder, $attributes);
164
+    }
165
+
166
+    ////////////////////////////////////////////////////////////////////
167
+    ////////////////////////// FIELD METHODS ///////////////////////////
168
+    ////////////////////////////////////////////////////////////////////
169
+
170
+    /**
171
+     * Set the select options
172
+     *
173
+     * @param  array   $_options     The options as an array
174
+     * @param  mixed   $selected     Facultative selected entry
175
+     * @param  boolean $valuesAsKeys Whether the array's values should be used as
176
+     *                               the option's values instead of the array's keys
177
+     */
178
+    public function options($_options, $selected = null, $valuesAsKeys = false)
179
+    {
180
+        $options = array();
181
+
182
+        // If valuesAsKeys is true, use the values as keys
183
+        if ($valuesAsKeys) {
184
+            foreach ($_options as $v) {
185
+                $options[$v] = $v;
186
+            }
187
+        } else {
188
+            $options = $_options;
189
+        }
190
+
191
+        // Add the various options
192
+        foreach ($options as $value => $text) {
193
+            if (is_array($text) and isset($text['value'])) {
194
+                $attributes = $text;
195
+                $text       = $value;
196
+                $value      = null;
197
+            } else {
198
+                $attributes = array();
199
+            }
200
+            $this->addOption($text, $value, $attributes);
201
+        }
202
+
203
+        // Set the selected value
204
+        if (!is_null($selected)) {
205
+            $this->select($selected);
206
+        }
207
+
208
+        return $this;
209
+    }
210
+
211
+    /**
212
+     * Creates a list of options from a range
213
+     *
214
+     * @param  integer $from
215
+     * @param  integer $to
216
+     * @param  integer $step
217
+     */
218
+    public function range($from, $to, $step = 1)
219
+    {
220
+        $range = range($from, $to, $step);
221
+        $this->options($range, null, true);
222
+
223
+        return $this;
224
+    }
225
+
226
+    /**
227
+     * Add an option to the Select's options
228
+     *
229
+     * @param array|string $text       It's value or an array of values
230
+     * @param string       $value      It's text
231
+     * @param array        $attributes The option's attributes
232
+     */
233
+    public function addOption($text = null, $value = null, $attributes = array())
234
+    {
235
+        // Get the option's value
236
+        $childrenKey = !is_null($value) ? $value : sizeof($this->children);
237
+
238
+        // If we passed an options group
239
+        if (is_array($text)) {
240
+            $this->children[$childrenKey] = Element::create('optgroup')->label($value);
241
+            foreach ($text as $key => $value) {
242
+                $option = Element::create('option', $value)->setAttribute('value', $key);
243
+                $this->children[$childrenKey]->nest($option);
244
+            }
245
+            // Else if it's a simple option
246
+        } else {
247
+            if (!isset($attributes['value'])) {
248
+                $attributes['value'] = $value;
249
+            }
250
+
251
+            $this->children[$attributes['value']] = Element::create('option', $text)->setAttributes($attributes);
252
+        }
253
+
254
+        return $this;
255
+    }
256
+
257
+    /**
258
+     * Use the results from a Fluent/Eloquent query as options
259
+     *
260
+     * @param  array           $results    An array of Eloquent models
261
+     * @param  string|function $text       The value to use as text
262
+     * @param  string|array    $attributes The data to use as attributes
263
+     * @param  string	   $selected   The default selected item
264
+     */
265
+    public function fromQuery($results, $text = null, $attributes = null, $selected = null)
266
+    {
267
+        $this->options(Helpers::queryToArray($results, $text, $attributes), $selected);
268
+
269
+        return $this;
270
+    }
271
+
272
+    /**
273
+     * Select a particular list item
274
+     *
275
+     * @param  mixed $selected Selected item
276
+     */
277
+    public function select($selected)
278
+    {
279
+        $this->value = $selected;
280
+
281
+        return $this;
282
+    }
283
+
284
+    /**
285
+     * Add a placeholder to the current select
286
+     *
287
+     * @param  string $placeholder The placeholder text
288
+     */
289
+    public function placeholder($placeholder)
290
+    {
291
+        $this->placeholder = Helpers::translate($placeholder);
292
+
293
+        return $this;
294
+    }
295
+
296
+    ////////////////////////////////////////////////////////////////////
297
+    ////////////////////////////// HELPERS /////////////////////////////
298
+    ////////////////////////////////////////////////////////////////////
299
+
300
+    /**
301
+     * Returns the current options in memory for manipulations
302
+     *
303
+     * @return array The current options array
304
+     */
305
+    public function getOptions()
306
+    {
307
+        return $this->children;
308
+    }
309 309
 }
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
@@ -12,407 +12,407 @@
 block discarded – undo
12 12
  */
13 13
 class Form extends FormerObject
14 14
 {
15
-	/**
16
-	 * The IoC Container
17
-	 *
18
-	 * @var Container
19
-	 */
20
-	protected $app;
21
-
22
-	/**
23
-	 * The URL generator
24
-	 *
25
-	 * @var UrlGenerator
26
-	 */
27
-	protected $url;
28
-
29
-	/**
30
-	 * The Populator
31
-	 *
32
-	 * @var Populator
33
-	 */
34
-	protected $populator;
35
-
36
-	/**
37
-	 * The Form type
38
-	 *
39
-	 * @var string
40
-	 */
41
-	protected $type = null;
42
-
43
-	/**
44
-	 * The destination of the current form
45
-	 *
46
-	 * @var string
47
-	 */
48
-	protected $action;
49
-
50
-	/**
51
-	 * The form method
52
-	 *
53
-	 * @var string
54
-	 */
55
-	protected $method;
56
-
57
-	/**
58
-	 * Whether the form should be secured or not
59
-	 *
60
-	 * @var boolean
61
-	 */
62
-	protected $secure;
63
-
64
-	/**
65
-	 * The form element
66
-	 *
67
-	 * @var string
68
-	 */
69
-	protected $element = 'form';
70
-
71
-	/**
72
-	 * A list of injected properties
73
-	 *
74
-	 * @var array
75
-	 */
76
-	protected $injectedProperties = array('method', 'action');
77
-
78
-	/**
79
-	 * Whether a form is opened or not
80
-	 *
81
-	 * @var boolean
82
-	 */
83
-	protected static $opened = false;
84
-
85
-	////////////////////////////////////////////////////////////////////
86
-	/////////////////////////// CORE METHODS ///////////////////////////
87
-	////////////////////////////////////////////////////////////////////
88
-
89
-	/**
90
-	 * Build a new Form instance
91
-	 *
92
-	 * @param UrlGenerator $url
93
-	 */
94
-	public function __construct(Container $app, $url, Populator $populator)
95
-	{
96
-		$this->app       = $app;
97
-		$this->url       = $url;
98
-		$this->populator = $populator;
99
-
100
-		$this->app->singleton('former.form.framework', function ($app) {
101
-			return clone $app['former.framework'];
102
-		});
103
-	}
104
-
105
-	/**
106
-	 * Opens up magically a form
107
-	 *
108
-	 * @param  string $type       The form type asked
109
-	 * @param  array  $parameters Parameters passed
110
-	 *
111
-	 * @return Form             A form opening tag
112
-	 */
113
-	public function openForm($type, $parameters)
114
-	{
115
-		$action     = Arr::get($parameters, 0);
116
-		$method     = Arr::get($parameters, 1, 'POST');
117
-		$attributes = Arr::get($parameters, 2, array());
118
-		$secure     = Arr::get($parameters, 3, null);
119
-
120
-		// Fetch errors if asked for
121
-		if ($this->app['former']->getOption('fetch_errors')) {
122
-			$this->app['former']->withErrors();
123
-		}
124
-
125
-		// Open the form
126
-		$this->action($action);
127
-		$this->attributes = $attributes;
128
-		$this->method     = strtoupper($method);
129
-		$this->secure     = $secure;
130
-
131
-		// Add any effect of the form type
132
-		$type       = Str::snake($type);
133
-		$this->type = $this->applyType($type);
134
-
135
-		// Add enctype
136
-		if (!array_key_exists('accept-charset', $attributes)) {
137
-			$this->attributes['accept-charset'] = 'utf-8';
138
-		}
139
-
140
-		// Add supplementary classes
141
-		if ($this->type !== 'raw') {
142
-			$this->addClass($this->app['former.form.framework']->getFormClasses($this->type));
143
-		}
144
-
145
-		return $this;
146
-	}
147
-
148
-	/**
149
-	 * Closes a Form
150
-	 *
151
-	 * @return string A closing <form> tag
152
-	 */
153
-	public function close()
154
-	{
155
-		static::$opened = false;
156
-
157
-		// Add token if necessary
158
-		$closing = '</form>';
159
-		if ($this->method != 'GET') {
160
-			$closing = $this->app['former']->token().$closing;
161
-		}
162
-
163
-		return $closing;
164
-	}
165
-
166
-	////////////////////////////////////////////////////////////////////
167
-	//////////////////////////// STATIC HELPERS ////////////////////////
168
-	////////////////////////////////////////////////////////////////////
169
-
170
-	/**
171
-	 * Whether a form is currently opened or not
172
-	 *
173
-	 * @return boolean
174
-	 */
175
-	public static function hasInstanceOpened()
176
-	{
177
-		return static::$opened;
178
-	}
179
-
180
-	////////////////////////////////////////////////////////////////////
181
-	/////////////////////////////// SETTER /////////////////////////////
182
-	////////////////////////////////////////////////////////////////////
183
-
184
-	/**
185
-	 * Change the form's action
186
-	 *
187
-	 * @param  string $action The new action
188
-	 *
189
-	 * @return $this
190
-	 */
191
-	public function action($action)
192
-	{
193
-		$this->action = $action ? $this->url->to($action, array(), $this->secure) : null;
194
-
195
-		return $this;
196
-	}
197
-
198
-	/**
199
-	 * Change the form's method
200
-	 *
201
-	 * @param  string $method The method to use
202
-	 *
203
-	 * @return $this
204
-	 */
205
-	public function method($method)
206
-	{
207
-		$this->method = strtoupper($method);
208
-
209
-		return $this;
210
-	}
211
-
212
-	/**
213
-	 * Whether the form should be secure
214
-	 *
215
-	 * @param  boolean $secure Secure or not
216
-	 *
217
-	 * @return $this
218
-	 */
219
-	public function secure($secure = true)
220
-	{
221
-		$this->secure = $secure;
222
-
223
-		return $this;
224
-	}
225
-
226
-	/**
227
-	 * Change the form's action and method to a route
228
-	 *
229
-	 * @param  string $name   The name of the route to use
230
-	 * @param  array  $params Any route parameters
231
-	 *
232
-	 * @return Form
233
-	 */
234
-	public function route($name, $params = array())
235
-	{
236
-		return $this->setRouteOrAction($name, $params, 'route');
237
-	}
238
-
239
-	/**
240
-	 * Change the form's action to a controller method
241
-	 *
242
-	 * @param  string $name   The controller and method
243
-	 * @param  array  $params Any method parameters
244
-	 *
245
-	 * @return Form
246
-	 */
247
-	public function controller($name, $params = array())
248
-	{
249
-		return $this->setRouteOrAction($name, $params, 'action');
250
-	}
251
-
252
-	/**
253
-	 * Outputs the current form opened
254
-	 *
255
-	 * @return string A <form> opening tag
256
-	 */
257
-	public function __toString()
258
-	{
259
-		// Mark the form as opened
260
-		static::$opened = true;
261
-
262
-		// Add name to attributes
263
-		$this->attributes['name'] = $this->name;
264
-
265
-		// Add spoof method
266
-		if (in_array($this->method, array('PUT', 'PATCH', 'DELETE'))) {
267
-			$spoof        = $this->app['former']->hidden('_method', $this->method);
268
-			$this->method = 'POST';
269
-		} else {
270
-			$spoof = null;
271
-		}
272
-
273
-		return $this->open().$spoof;
274
-	}
275
-
276
-	////////////////////////////////////////////////////////////////////
277
-	////////////////////////// PUBLIC HELPERS //////////////////////////
278
-	////////////////////////////////////////////////////////////////////
279
-
280
-	/**
281
-	 * Alias for $this->app['former']->withRules
282
-	 */
283
-	public function rules()
284
-	{
285
-		call_user_func_array(array($this->app['former'], 'withRules'), func_get_args());
286
-
287
-		return $this;
288
-	}
289
-
290
-	/**
291
-	 * Populate a form with specific values
292
-	 *
293
-	 * @param array|object $values
294
-	 *
295
-	 * @return $this
296
-	 */
297
-	public function populate($values)
298
-	{
299
-		$this->populator->replace($values);
300
-
301
-		return $this;
302
-	}
303
-
304
-	/**
305
-	 * Get the Populator binded to the Form
306
-	 *
307
-	 * @return Populator
308
-	 */
309
-	public function getPopulator()
310
-	{
311
-		return $this->populator;
312
-	}
313
-
314
-	////////////////////////////////////////////////////////////////////
315
-	////////////////////////////// HELPERS /////////////////////////////
316
-	////////////////////////////////////////////////////////////////////
317
-
318
-	/**
319
-	 * Find the method of a route by its _uses or name
320
-	 *
321
-	 * @param  string $name
322
-	 *
323
-	 * @return string
324
-	 */
325
-	protected function findRouteMethod($name)
326
-	{
327
-		if (!$this->app->bound('router')) {
328
-			return;
329
-		}
330
-
331
-		// Get string by name
332
-		if (!Str::contains($name, '@')) {
333
-			$routes = $this->app['router']->getRoutes();
334
-			$route  = method_exists($routes, 'getByName') ? $routes->getByName($name) : $routes->get($name);
335
-			// Get string by uses
336
-		} else {
337
-			foreach ($this->app['router']->getRoutes() as $route) {
338
-				$routeUses = method_exists($route, 'getOption') ? $route->getOption('_uses') : Arr::get($route->getAction(), 'controller');
339
-				if ($action = $routeUses) {
340
-					if ($action == $name) {
341
-						break;
342
-					}
343
-				}
344
-			}
345
-		}
346
-
347
-		// Get method
348
-		$methods = method_exists($route, 'getMethods') ? $route->getMethods() : $route->methods();
349
-		$method  = Arr::get($methods, 0);
350
-
351
-		return $method;
352
-	}
353
-
354
-	/**
355
-	 * @param $name
356
-	 * @param $params
357
-	 * @param $type
358
-	 *
359
-	 * @return $this
360
-	 */
361
-	protected function setRouteOrAction($name, $params, $type)
362
-	{
363
-		// Set the form action
364
-		$this->action = $this->url->$type($name, $params);
365
-
366
-		// Set the proper method
367
-		if ($method = $this->findRouteMethod($name)) {
368
-			$this->method($method);
369
-		}
370
-
371
-		return $this;
372
-	}
373
-
374
-	/**
375
-	 * Apply various parameters according to form type
376
-	 *
377
-	 * @param  string $type The original form type provided
378
-	 *
379
-	 * @return string The final form type
380
-	 */
381
-	private function applyType($type)
382
-	{
383
-		// If classic form
384
-		if ($type == 'open') {
385
-			return $this->app['former']->getOption('default_form_type');
386
-		}
387
-
388
-		// Look for HTTPS form
389
-		if (Str::contains($type, 'secure')) {
390
-			$type         = str_replace('secure', '', $type);
391
-			$this->secure = true;
392
-		}
393
-
394
-		// Look for file form
395
-		if (Str::contains($type, 'for_files')) {
396
-			$type                        = str_replace('for_files', '', $type);
397
-			$this->attributes['enctype'] = 'multipart/form-data';
398
-		}
399
-
400
-		// Calculate form type
401
-		$type = str_replace('open', '', $type);
402
-		$type = trim($type, '_');
403
-
404
-		// If raw form
405
-		if ($type == 'raw') {
406
-			$this->app->bind('former.form.framework', function ($app) {
407
-				return $app['former']->getFrameworkInstance('Nude');
408
-			});
409
-		}
410
-
411
-		// Use default form type if the one provided is invalid
412
-		if ($type !== 'raw' and !in_array($type, $this->app['former.form.framework']->availableTypes())) {
413
-			$type = $this->app['former']->getOption('default_form_type');
414
-		}
415
-
416
-		return $type;
417
-	}
15
+    /**
16
+     * The IoC Container
17
+     *
18
+     * @var Container
19
+     */
20
+    protected $app;
21
+
22
+    /**
23
+     * The URL generator
24
+     *
25
+     * @var UrlGenerator
26
+     */
27
+    protected $url;
28
+
29
+    /**
30
+     * The Populator
31
+     *
32
+     * @var Populator
33
+     */
34
+    protected $populator;
35
+
36
+    /**
37
+     * The Form type
38
+     *
39
+     * @var string
40
+     */
41
+    protected $type = null;
42
+
43
+    /**
44
+     * The destination of the current form
45
+     *
46
+     * @var string
47
+     */
48
+    protected $action;
49
+
50
+    /**
51
+     * The form method
52
+     *
53
+     * @var string
54
+     */
55
+    protected $method;
56
+
57
+    /**
58
+     * Whether the form should be secured or not
59
+     *
60
+     * @var boolean
61
+     */
62
+    protected $secure;
63
+
64
+    /**
65
+     * The form element
66
+     *
67
+     * @var string
68
+     */
69
+    protected $element = 'form';
70
+
71
+    /**
72
+     * A list of injected properties
73
+     *
74
+     * @var array
75
+     */
76
+    protected $injectedProperties = array('method', 'action');
77
+
78
+    /**
79
+     * Whether a form is opened or not
80
+     *
81
+     * @var boolean
82
+     */
83
+    protected static $opened = false;
84
+
85
+    ////////////////////////////////////////////////////////////////////
86
+    /////////////////////////// CORE METHODS ///////////////////////////
87
+    ////////////////////////////////////////////////////////////////////
88
+
89
+    /**
90
+     * Build a new Form instance
91
+     *
92
+     * @param UrlGenerator $url
93
+     */
94
+    public function __construct(Container $app, $url, Populator $populator)
95
+    {
96
+        $this->app       = $app;
97
+        $this->url       = $url;
98
+        $this->populator = $populator;
99
+
100
+        $this->app->singleton('former.form.framework', function ($app) {
101
+            return clone $app['former.framework'];
102
+        });
103
+    }
104
+
105
+    /**
106
+     * Opens up magically a form
107
+     *
108
+     * @param  string $type       The form type asked
109
+     * @param  array  $parameters Parameters passed
110
+     *
111
+     * @return Form             A form opening tag
112
+     */
113
+    public function openForm($type, $parameters)
114
+    {
115
+        $action     = Arr::get($parameters, 0);
116
+        $method     = Arr::get($parameters, 1, 'POST');
117
+        $attributes = Arr::get($parameters, 2, array());
118
+        $secure     = Arr::get($parameters, 3, null);
119
+
120
+        // Fetch errors if asked for
121
+        if ($this->app['former']->getOption('fetch_errors')) {
122
+            $this->app['former']->withErrors();
123
+        }
124
+
125
+        // Open the form
126
+        $this->action($action);
127
+        $this->attributes = $attributes;
128
+        $this->method     = strtoupper($method);
129
+        $this->secure     = $secure;
130
+
131
+        // Add any effect of the form type
132
+        $type       = Str::snake($type);
133
+        $this->type = $this->applyType($type);
134
+
135
+        // Add enctype
136
+        if (!array_key_exists('accept-charset', $attributes)) {
137
+            $this->attributes['accept-charset'] = 'utf-8';
138
+        }
139
+
140
+        // Add supplementary classes
141
+        if ($this->type !== 'raw') {
142
+            $this->addClass($this->app['former.form.framework']->getFormClasses($this->type));
143
+        }
144
+
145
+        return $this;
146
+    }
147
+
148
+    /**
149
+     * Closes a Form
150
+     *
151
+     * @return string A closing <form> tag
152
+     */
153
+    public function close()
154
+    {
155
+        static::$opened = false;
156
+
157
+        // Add token if necessary
158
+        $closing = '</form>';
159
+        if ($this->method != 'GET') {
160
+            $closing = $this->app['former']->token().$closing;
161
+        }
162
+
163
+        return $closing;
164
+    }
165
+
166
+    ////////////////////////////////////////////////////////////////////
167
+    //////////////////////////// STATIC HELPERS ////////////////////////
168
+    ////////////////////////////////////////////////////////////////////
169
+
170
+    /**
171
+     * Whether a form is currently opened or not
172
+     *
173
+     * @return boolean
174
+     */
175
+    public static function hasInstanceOpened()
176
+    {
177
+        return static::$opened;
178
+    }
179
+
180
+    ////////////////////////////////////////////////////////////////////
181
+    /////////////////////////////// SETTER /////////////////////////////
182
+    ////////////////////////////////////////////////////////////////////
183
+
184
+    /**
185
+     * Change the form's action
186
+     *
187
+     * @param  string $action The new action
188
+     *
189
+     * @return $this
190
+     */
191
+    public function action($action)
192
+    {
193
+        $this->action = $action ? $this->url->to($action, array(), $this->secure) : null;
194
+
195
+        return $this;
196
+    }
197
+
198
+    /**
199
+     * Change the form's method
200
+     *
201
+     * @param  string $method The method to use
202
+     *
203
+     * @return $this
204
+     */
205
+    public function method($method)
206
+    {
207
+        $this->method = strtoupper($method);
208
+
209
+        return $this;
210
+    }
211
+
212
+    /**
213
+     * Whether the form should be secure
214
+     *
215
+     * @param  boolean $secure Secure or not
216
+     *
217
+     * @return $this
218
+     */
219
+    public function secure($secure = true)
220
+    {
221
+        $this->secure = $secure;
222
+
223
+        return $this;
224
+    }
225
+
226
+    /**
227
+     * Change the form's action and method to a route
228
+     *
229
+     * @param  string $name   The name of the route to use
230
+     * @param  array  $params Any route parameters
231
+     *
232
+     * @return Form
233
+     */
234
+    public function route($name, $params = array())
235
+    {
236
+        return $this->setRouteOrAction($name, $params, 'route');
237
+    }
238
+
239
+    /**
240
+     * Change the form's action to a controller method
241
+     *
242
+     * @param  string $name   The controller and method
243
+     * @param  array  $params Any method parameters
244
+     *
245
+     * @return Form
246
+     */
247
+    public function controller($name, $params = array())
248
+    {
249
+        return $this->setRouteOrAction($name, $params, 'action');
250
+    }
251
+
252
+    /**
253
+     * Outputs the current form opened
254
+     *
255
+     * @return string A <form> opening tag
256
+     */
257
+    public function __toString()
258
+    {
259
+        // Mark the form as opened
260
+        static::$opened = true;
261
+
262
+        // Add name to attributes
263
+        $this->attributes['name'] = $this->name;
264
+
265
+        // Add spoof method
266
+        if (in_array($this->method, array('PUT', 'PATCH', 'DELETE'))) {
267
+            $spoof        = $this->app['former']->hidden('_method', $this->method);
268
+            $this->method = 'POST';
269
+        } else {
270
+            $spoof = null;
271
+        }
272
+
273
+        return $this->open().$spoof;
274
+    }
275
+
276
+    ////////////////////////////////////////////////////////////////////
277
+    ////////////////////////// PUBLIC HELPERS //////////////////////////
278
+    ////////////////////////////////////////////////////////////////////
279
+
280
+    /**
281
+     * Alias for $this->app['former']->withRules
282
+     */
283
+    public function rules()
284
+    {
285
+        call_user_func_array(array($this->app['former'], 'withRules'), func_get_args());
286
+
287
+        return $this;
288
+    }
289
+
290
+    /**
291
+     * Populate a form with specific values
292
+     *
293
+     * @param array|object $values
294
+     *
295
+     * @return $this
296
+     */
297
+    public function populate($values)
298
+    {
299
+        $this->populator->replace($values);
300
+
301
+        return $this;
302
+    }
303
+
304
+    /**
305
+     * Get the Populator binded to the Form
306
+     *
307
+     * @return Populator
308
+     */
309
+    public function getPopulator()
310
+    {
311
+        return $this->populator;
312
+    }
313
+
314
+    ////////////////////////////////////////////////////////////////////
315
+    ////////////////////////////// HELPERS /////////////////////////////
316
+    ////////////////////////////////////////////////////////////////////
317
+
318
+    /**
319
+     * Find the method of a route by its _uses or name
320
+     *
321
+     * @param  string $name
322
+     *
323
+     * @return string
324
+     */
325
+    protected function findRouteMethod($name)
326
+    {
327
+        if (!$this->app->bound('router')) {
328
+            return;
329
+        }
330
+
331
+        // Get string by name
332
+        if (!Str::contains($name, '@')) {
333
+            $routes = $this->app['router']->getRoutes();
334
+            $route  = method_exists($routes, 'getByName') ? $routes->getByName($name) : $routes->get($name);
335
+            // Get string by uses
336
+        } else {
337
+            foreach ($this->app['router']->getRoutes() as $route) {
338
+                $routeUses = method_exists($route, 'getOption') ? $route->getOption('_uses') : Arr::get($route->getAction(), 'controller');
339
+                if ($action = $routeUses) {
340
+                    if ($action == $name) {
341
+                        break;
342
+                    }
343
+                }
344
+            }
345
+        }
346
+
347
+        // Get method
348
+        $methods = method_exists($route, 'getMethods') ? $route->getMethods() : $route->methods();
349
+        $method  = Arr::get($methods, 0);
350
+
351
+        return $method;
352
+    }
353
+
354
+    /**
355
+     * @param $name
356
+     * @param $params
357
+     * @param $type
358
+     *
359
+     * @return $this
360
+     */
361
+    protected function setRouteOrAction($name, $params, $type)
362
+    {
363
+        // Set the form action
364
+        $this->action = $this->url->$type($name, $params);
365
+
366
+        // Set the proper method
367
+        if ($method = $this->findRouteMethod($name)) {
368
+            $this->method($method);
369
+        }
370
+
371
+        return $this;
372
+    }
373
+
374
+    /**
375
+     * Apply various parameters according to form type
376
+     *
377
+     * @param  string $type The original form type provided
378
+     *
379
+     * @return string The final form type
380
+     */
381
+    private function applyType($type)
382
+    {
383
+        // If classic form
384
+        if ($type == 'open') {
385
+            return $this->app['former']->getOption('default_form_type');
386
+        }
387
+
388
+        // Look for HTTPS form
389
+        if (Str::contains($type, 'secure')) {
390
+            $type         = str_replace('secure', '', $type);
391
+            $this->secure = true;
392
+        }
393
+
394
+        // Look for file form
395
+        if (Str::contains($type, 'for_files')) {
396
+            $type                        = str_replace('for_files', '', $type);
397
+            $this->attributes['enctype'] = 'multipart/form-data';
398
+        }
399
+
400
+        // Calculate form type
401
+        $type = str_replace('open', '', $type);
402
+        $type = trim($type, '_');
403
+
404
+        // If raw form
405
+        if ($type == 'raw') {
406
+            $this->app->bind('former.form.framework', function ($app) {
407
+                return $app['former']->getFrameworkInstance('Nude');
408
+            });
409
+        }
410
+
411
+        // Use default form type if the one provided is invalid
412
+        if ($type !== 'raw' and !in_array($type, $this->app['former.form.framework']->availableTypes())) {
413
+            $type = $this->app['former']->getOption('default_form_type');
414
+        }
415
+
416
+        return $type;
417
+    }
418 418
 }
Please login to merge, or discard this patch.
src/Former/Form/Group.php 1 patch
Indentation   +460 added lines, -460 removed lines patch added patch discarded remove patch
@@ -13,464 +13,464 @@
 block discarded – undo
13 13
  */
14 14
 class Group extends Tag
15 15
 {
16
-	/**
17
-	 * The Container
18
-	 *
19
-	 * @var Container
20
-	 */
21
-	protected $app;
22
-
23
-	/**
24
-	 * The current state of the group
25
-	 *
26
-	 * @var string
27
-	 */
28
-	protected $state = null;
29
-
30
-	/**
31
-	 * Whether the field should be displayed raw or not
32
-	 *
33
-	 * @var boolean
34
-	 */
35
-	protected $raw = false;
36
-
37
-	/**
38
-	 * The group label
39
-	 *
40
-	 * @var Element
41
-	 */
42
-	protected $label;
43
-
44
-	/**
45
-	 * The group help
46
-	 *
47
-	 * @var array
48
-	 */
49
-	protected $help = array();
50
-
51
-	/**
52
-	 * An array of elements to preprend the field
53
-	 *
54
-	 * @var array
55
-	 */
56
-	protected $prepend = array();
57
-
58
-	/**
59
-	 * An array of elements to append the field
60
-	 *
61
-	 * @var array
62
-	 */
63
-	protected $append = array();
64
-
65
-	/**
66
-	 * The field validations to be checked for errors
67
-	 *
68
-	 * @var array
69
-	 */
70
-	protected $validations = array();
71
-
72
-	/**
73
-	 * The group's element
74
-	 *
75
-	 * @var string
76
-	 */
77
-	protected $element = 'div';
78
-
79
-	/**
80
-	 * Whether a custom group is opened or not
81
-	 *
82
-	 * @var boolean
83
-	 */
84
-	public static $opened = false;
85
-
86
-	/**
87
-	 * The custom group that is open
88
-	 *
89
-	 * @var Former\Form\Group
90
-	 */
91
-	public static $openGroup = null;
92
-
93
-	////////////////////////////////////////////////////////////////////
94
-	/////////////////////////// CORE METHODS ///////////////////////////
95
-	////////////////////////////////////////////////////////////////////
96
-
97
-	/**
98
-	 * Creates a group
99
-	 *
100
-	 * @param string $label Its label
101
-	 */
102
-	public function __construct(Container $app, $label, $validations = null)
103
-	{
104
-		// Get special classes
105
-		$this->app = $app;
106
-		$this->addClass($this->app['former.framework']->getGroupClasses());
107
-
108
-		// Invisible if Nude
109
-		if ($this->app['former.framework']->is('Nude')) {
110
-			$this->element = '';
111
-		}
112
-
113
-		// Set group label
114
-		if ($label) {
115
-			$this->setLabel($label);
116
-		}
117
-
118
-		// Set validations used to override groups own conclusions
119
-		$this->validations = (array) $validations;
120
-	}
121
-
122
-	/**
123
-	 * Prints out the opening of the Control Group
124
-	 *
125
-	 * @return string A control group opening tag
126
-	 */
127
-	public function __toString()
128
-	{
129
-		return $this->open().$this->getFormattedLabel();
130
-	}
131
-
132
-	/**
133
-	 * Opens a group
134
-	 *
135
-	 * @return string Opening tag
136
-	 */
137
-	public function open()
138
-	{
139
-		if ($this->getErrors()) {
140
-			$this->state($this->app['former.framework']->errorState());
141
-		}
142
-
143
-		// Retrieve state and append it to classes
144
-		if ($this->state) {
145
-			$this->addClass($this->state);
146
-		}
147
-
148
-		// Required state
149
-		if ($this->app->bound('former.field') and $this->app['former.field']->isRequired()) {
150
-			$this->addClass($this->app['former']->getOption('required_class'));
151
-		}
152
-
153
-		return parent::open();
154
-	}
155
-
156
-	/**
157
-	 * Set the contents of the current group
158
-	 *
159
-	 * @param string $contents The group contents
160
-	 *
161
-	 * @return string A group
162
-	 */
163
-	public function contents($contents)
164
-	{
165
-		return $this->wrap($contents, $this->getFormattedLabel());
166
-	}
167
-
168
-	/**
169
-	 * Wrap a Field with the current group
170
-	 *
171
-	 * @param  \Former\Traits\Field $field A Field instance
172
-	 *
173
-	 * @return string        A group
174
-	 */
175
-	public function wrapField($field)
176
-	{
177
-		$label = $this->getLabel($field);
178
-		$field = $this->prependAppend($field);
179
-		$field .= $this->getHelp();
180
-
181
-		return $this->wrap($field, $label);
182
-	}
183
-
184
-	////////////////////////////////////////////////////////////////////
185
-	//////////////////////////// FIELD METHODS /////////////////////////
186
-	////////////////////////////////////////////////////////////////////
187
-
188
-	/**
189
-	 * Set the state of the group
190
-	 *
191
-	 * @param  string $state A Bootstrap state class
192
-	 */
193
-	public function state($state)
194
-	{
195
-		// Filter state
196
-		$state = $this->app['former.framework']->filterState($state);
197
-
198
-		$this->state = $state;
199
-	}
200
-
201
-	/**
202
-	 * Set a class on the Group
203
-	 *
204
-	 * @param string $class The class to add
205
-	 */
206
-	public function addGroupClass($class)
207
-	{
208
-		$this->addClass($class);
209
-	}
210
-
211
-	/**
212
-	 * Adds a label to the group
213
-	 *
214
-	 * @param  string $label A label
215
-	 */
216
-	public function setLabel($label)
217
-	{
218
-		if (!$label instanceof Element) {
219
-			$label = Helpers::translate($label);
220
-			$label = Element::create('label', $label)->for($label);
221
-		}
222
-
223
-		$this->label = $label;
224
-	}
225
-
226
-	/**
227
-	 * Get the formatted group label
228
-	 *
229
-	 * @return string|null
230
-	 */
231
-	public function getFormattedLabel()
232
-	{
233
-		if (!$this->label) {
234
-			return false;
235
-		}
236
-
237
-		return $this->label->addClass($this->app['former.framework']->getLabelClasses());
238
-	}
239
-
240
-	/**
241
-	 * Disables the control group for the current field
242
-	 */
243
-	public function raw()
244
-	{
245
-		$this->raw = true;
246
-	}
247
-
248
-	/**
249
-	 * Check if the current group is to be displayed or not
250
-	 *
251
-	 * @return boolean
252
-	 */
253
-	public function isRaw()
254
-	{
255
-		return (bool) $this->raw;
256
-	}
257
-
258
-	////////////////////////////////////////////////////////////////////
259
-	///////////////////////////// HELP BLOCKS //////////////////////////
260
-	////////////////////////////////////////////////////////////////////
261
-
262
-	/**
263
-	 * Alias for inlineHelp
264
-	 *
265
-	 * @param  string $help       The help text
266
-	 * @param  array  $attributes Facultative attributes
267
-	 */
268
-	public function help($help, $attributes = array())
269
-	{
270
-		return $this->inlineHelp($help, $attributes);
271
-	}
272
-
273
-	/**
274
-	 * Add an inline help
275
-	 *
276
-	 * @param  string $help       The help text
277
-	 * @param  array  $attributes Facultative attributes
278
-	 */
279
-	public function inlineHelp($help, $attributes = array())
280
-	{
281
-		// If no help text, do nothing
282
-		if (!$help) {
283
-			return false;
284
-		}
285
-
286
-		$this->help['inline'] = $this->app['former.framework']->createHelp($help, $attributes);
287
-	}
288
-
289
-	/**
290
-	 * Add an block help
291
-	 *
292
-	 * @param  string $help       The help text
293
-	 * @param  array  $attributes Facultative attributes
294
-	 */
295
-	public function blockHelp($help, $attributes = array())
296
-	{
297
-		// Reserved method
298
-		if ($this->app['former.framework']->isnt('TwitterBootstrap') &&
299
-		    $this->app['former.framework']->isnt('TwitterBootstrap3') &&
300
-		    $this->app['former.framework']->isnt('TwitterBootstrap4')
301
-		) {
302
-			throw new BadMethodCallException('This method is only available on the Bootstrap framework');
303
-		}
304
-
305
-		// If no help text, do nothing
306
-		if (!$help) {
307
-			return false;
308
-		}
309
-
310
-		$this->help['block'] = $this->app['former.framework']->createBlockHelp($help, $attributes);
311
-	}
312
-
313
-	////////////////////////////////////////////////////////////////////
314
-	///////////////////////// PREPEND/APPEND METHODS ///////////////////
315
-	////////////////////////////////////////////////////////////////////
316
-
317
-	/**
318
-	 * Prepend elements to the field
319
-	 */
320
-	public function prepend()
321
-	{
322
-		$this->placeAround(func_get_args(), 'prepend');
323
-	}
324
-
325
-	/**
326
-	 * Append elements to the field
327
-	 */
328
-	public function append()
329
-	{
330
-		$this->placeAround(func_get_args(), 'append');
331
-	}
332
-
333
-	/**
334
-	 * Prepends an icon to a field
335
-	 *
336
-	 * @param string $icon       The icon to prepend
337
-	 * @param array  $attributes Its attributes
338
-	 */
339
-	public function prependIcon($icon, $attributes = array(), $iconSettings = array())
340
-	{
341
-		$icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
342
-
343
-		$this->prepend($icon);
344
-	}
345
-
346
-	/**
347
-	 * Append an icon to a field
348
-	 *
349
-	 * @param string $icon       The icon to prepend
350
-	 * @param array  $attributes Its attributes
351
-	 */
352
-	public function appendIcon($icon, $attributes = array(), $iconSettings = array())
353
-	{
354
-		$icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
355
-
356
-		$this->append($icon);
357
-	}
358
-
359
-	////////////////////////////////////////////////////////////////////
360
-	//////////////////////////////// HELPERS ///////////////////////////
361
-	////////////////////////////////////////////////////////////////////
362
-
363
-	/**
364
-	 * Get the errors for the group
365
-	 *
366
-	 * @return string
367
-	 */
368
-	public function getErrors()
369
-	{
370
-		$errors = '';
371
-
372
-		if (!self::$opened) {
373
-
374
-			// for non-custom groups, normal error handling applies
375
-			$errors = $this->app['former']->getErrors();
376
-		} elseif (!empty($this->validations)) {
377
-
378
-			// error handling only when validations specified for custom groups
379
-			foreach ($this->validations as $validation) {
380
-				$errors .= $this->app['former']->getErrors($validation);
381
-			}
382
-		}
383
-
384
-		return $errors;
385
-	}
386
-
387
-	/**
388
-	 * Wraps content in a group
389
-	 *
390
-	 * @param string $contents The content
391
-	 * @param string $label    The label to add
392
-	 *
393
-	 * @return string A group
394
-	 */
395
-	public function wrap($contents, $label = null)
396
-	{
397
-		$group = $this->open();
398
-		$group .= $label;
399
-		$group .= $this->app['former.framework']->wrapField($contents);
400
-		$group .= $this->close();
401
-
402
-		return $group;
403
-	}
404
-
405
-	/**
406
-	 * Prints out the current label
407
-	 *
408
-	 * @param  string $field The field to create a label for
409
-	 *
410
-	 * @return string        A <label> tag
411
-	 */
412
-	protected function getLabel($field = null)
413
-	{
414
-		// Don't create a label if none exist
415
-		if (!$field or !$this->label) {
416
-			return null;
417
-		}
418
-
419
-		// Wrap label in framework classes
420
-		$this->label->addClass($this->app['former.framework']->getLabelClasses());
421
-		$this->label = $this->app['former.framework']->createLabelOf($field, $this->label);
422
-		$this->label = $this->app['former.framework']->wrapLabel($this->label);
423
-
424
-		return $this->label;
425
-	}
426
-
427
-	/**
428
-	 * Prints out the current help
429
-	 *
430
-	 * @return string A .help-block or .help-inline
431
-	 */
432
-	protected function getHelp()
433
-	{
434
-		$inline = Arr::get($this->help, 'inline');
435
-		$block  = Arr::get($this->help, 'block');
436
-
437
-		// Replace help text with error if any found
438
-		$errors = $this->app['former']->getErrors();
439
-		if ($errors and $this->app['former']->getOption('error_messages')) {
440
-			$inline = $this->app['former.framework']->createValidationError($errors);
441
-		}
442
-
443
-		return join(null, array($inline, $block));
444
-	}
445
-
446
-	/**
447
-	 * Format the field with prepended/appended elements
448
-	 *
449
-	 * @param  Field $field The field to format
450
-	 *
451
-	 * @return string        Field plus supplementary elements
452
-	 */
453
-	protected function prependAppend($field)
454
-	{
455
-		if (!$this->prepend and !$this->append) {
456
-			return $field->render();
457
-		}
458
-
459
-		return $this->app['former.framework']->prependAppend($field, $this->prepend, $this->append);
460
-	}
461
-
462
-	/**
463
-	 * Place elements around the field
464
-	 *
465
-	 * @param  array  $items An array of items to place
466
-	 * @param  string $place Where they should end up (prepend|append)
467
-	 */
468
-	protected function placeAround($items, $place)
469
-	{
470
-		// Iterate over the items and place them where they should
471
-		foreach ((array) $items as $item) {
472
-			$item             = $this->app['former.framework']->placeAround($item);
473
-			$this->{$place}[] = $item;
474
-		}
475
-	}
16
+    /**
17
+     * The Container
18
+     *
19
+     * @var Container
20
+     */
21
+    protected $app;
22
+
23
+    /**
24
+     * The current state of the group
25
+     *
26
+     * @var string
27
+     */
28
+    protected $state = null;
29
+
30
+    /**
31
+     * Whether the field should be displayed raw or not
32
+     *
33
+     * @var boolean
34
+     */
35
+    protected $raw = false;
36
+
37
+    /**
38
+     * The group label
39
+     *
40
+     * @var Element
41
+     */
42
+    protected $label;
43
+
44
+    /**
45
+     * The group help
46
+     *
47
+     * @var array
48
+     */
49
+    protected $help = array();
50
+
51
+    /**
52
+     * An array of elements to preprend the field
53
+     *
54
+     * @var array
55
+     */
56
+    protected $prepend = array();
57
+
58
+    /**
59
+     * An array of elements to append the field
60
+     *
61
+     * @var array
62
+     */
63
+    protected $append = array();
64
+
65
+    /**
66
+     * The field validations to be checked for errors
67
+     *
68
+     * @var array
69
+     */
70
+    protected $validations = array();
71
+
72
+    /**
73
+     * The group's element
74
+     *
75
+     * @var string
76
+     */
77
+    protected $element = 'div';
78
+
79
+    /**
80
+     * Whether a custom group is opened or not
81
+     *
82
+     * @var boolean
83
+     */
84
+    public static $opened = false;
85
+
86
+    /**
87
+     * The custom group that is open
88
+     *
89
+     * @var Former\Form\Group
90
+     */
91
+    public static $openGroup = null;
92
+
93
+    ////////////////////////////////////////////////////////////////////
94
+    /////////////////////////// CORE METHODS ///////////////////////////
95
+    ////////////////////////////////////////////////////////////////////
96
+
97
+    /**
98
+     * Creates a group
99
+     *
100
+     * @param string $label Its label
101
+     */
102
+    public function __construct(Container $app, $label, $validations = null)
103
+    {
104
+        // Get special classes
105
+        $this->app = $app;
106
+        $this->addClass($this->app['former.framework']->getGroupClasses());
107
+
108
+        // Invisible if Nude
109
+        if ($this->app['former.framework']->is('Nude')) {
110
+            $this->element = '';
111
+        }
112
+
113
+        // Set group label
114
+        if ($label) {
115
+            $this->setLabel($label);
116
+        }
117
+
118
+        // Set validations used to override groups own conclusions
119
+        $this->validations = (array) $validations;
120
+    }
121
+
122
+    /**
123
+     * Prints out the opening of the Control Group
124
+     *
125
+     * @return string A control group opening tag
126
+     */
127
+    public function __toString()
128
+    {
129
+        return $this->open().$this->getFormattedLabel();
130
+    }
131
+
132
+    /**
133
+     * Opens a group
134
+     *
135
+     * @return string Opening tag
136
+     */
137
+    public function open()
138
+    {
139
+        if ($this->getErrors()) {
140
+            $this->state($this->app['former.framework']->errorState());
141
+        }
142
+
143
+        // Retrieve state and append it to classes
144
+        if ($this->state) {
145
+            $this->addClass($this->state);
146
+        }
147
+
148
+        // Required state
149
+        if ($this->app->bound('former.field') and $this->app['former.field']->isRequired()) {
150
+            $this->addClass($this->app['former']->getOption('required_class'));
151
+        }
152
+
153
+        return parent::open();
154
+    }
155
+
156
+    /**
157
+     * Set the contents of the current group
158
+     *
159
+     * @param string $contents The group contents
160
+     *
161
+     * @return string A group
162
+     */
163
+    public function contents($contents)
164
+    {
165
+        return $this->wrap($contents, $this->getFormattedLabel());
166
+    }
167
+
168
+    /**
169
+     * Wrap a Field with the current group
170
+     *
171
+     * @param  \Former\Traits\Field $field A Field instance
172
+     *
173
+     * @return string        A group
174
+     */
175
+    public function wrapField($field)
176
+    {
177
+        $label = $this->getLabel($field);
178
+        $field = $this->prependAppend($field);
179
+        $field .= $this->getHelp();
180
+
181
+        return $this->wrap($field, $label);
182
+    }
183
+
184
+    ////////////////////////////////////////////////////////////////////
185
+    //////////////////////////// FIELD METHODS /////////////////////////
186
+    ////////////////////////////////////////////////////////////////////
187
+
188
+    /**
189
+     * Set the state of the group
190
+     *
191
+     * @param  string $state A Bootstrap state class
192
+     */
193
+    public function state($state)
194
+    {
195
+        // Filter state
196
+        $state = $this->app['former.framework']->filterState($state);
197
+
198
+        $this->state = $state;
199
+    }
200
+
201
+    /**
202
+     * Set a class on the Group
203
+     *
204
+     * @param string $class The class to add
205
+     */
206
+    public function addGroupClass($class)
207
+    {
208
+        $this->addClass($class);
209
+    }
210
+
211
+    /**
212
+     * Adds a label to the group
213
+     *
214
+     * @param  string $label A label
215
+     */
216
+    public function setLabel($label)
217
+    {
218
+        if (!$label instanceof Element) {
219
+            $label = Helpers::translate($label);
220
+            $label = Element::create('label', $label)->for($label);
221
+        }
222
+
223
+        $this->label = $label;
224
+    }
225
+
226
+    /**
227
+     * Get the formatted group label
228
+     *
229
+     * @return string|null
230
+     */
231
+    public function getFormattedLabel()
232
+    {
233
+        if (!$this->label) {
234
+            return false;
235
+        }
236
+
237
+        return $this->label->addClass($this->app['former.framework']->getLabelClasses());
238
+    }
239
+
240
+    /**
241
+     * Disables the control group for the current field
242
+     */
243
+    public function raw()
244
+    {
245
+        $this->raw = true;
246
+    }
247
+
248
+    /**
249
+     * Check if the current group is to be displayed or not
250
+     *
251
+     * @return boolean
252
+     */
253
+    public function isRaw()
254
+    {
255
+        return (bool) $this->raw;
256
+    }
257
+
258
+    ////////////////////////////////////////////////////////////////////
259
+    ///////////////////////////// HELP BLOCKS //////////////////////////
260
+    ////////////////////////////////////////////////////////////////////
261
+
262
+    /**
263
+     * Alias for inlineHelp
264
+     *
265
+     * @param  string $help       The help text
266
+     * @param  array  $attributes Facultative attributes
267
+     */
268
+    public function help($help, $attributes = array())
269
+    {
270
+        return $this->inlineHelp($help, $attributes);
271
+    }
272
+
273
+    /**
274
+     * Add an inline help
275
+     *
276
+     * @param  string $help       The help text
277
+     * @param  array  $attributes Facultative attributes
278
+     */
279
+    public function inlineHelp($help, $attributes = array())
280
+    {
281
+        // If no help text, do nothing
282
+        if (!$help) {
283
+            return false;
284
+        }
285
+
286
+        $this->help['inline'] = $this->app['former.framework']->createHelp($help, $attributes);
287
+    }
288
+
289
+    /**
290
+     * Add an block help
291
+     *
292
+     * @param  string $help       The help text
293
+     * @param  array  $attributes Facultative attributes
294
+     */
295
+    public function blockHelp($help, $attributes = array())
296
+    {
297
+        // Reserved method
298
+        if ($this->app['former.framework']->isnt('TwitterBootstrap') &&
299
+            $this->app['former.framework']->isnt('TwitterBootstrap3') &&
300
+            $this->app['former.framework']->isnt('TwitterBootstrap4')
301
+        ) {
302
+            throw new BadMethodCallException('This method is only available on the Bootstrap framework');
303
+        }
304
+
305
+        // If no help text, do nothing
306
+        if (!$help) {
307
+            return false;
308
+        }
309
+
310
+        $this->help['block'] = $this->app['former.framework']->createBlockHelp($help, $attributes);
311
+    }
312
+
313
+    ////////////////////////////////////////////////////////////////////
314
+    ///////////////////////// PREPEND/APPEND METHODS ///////////////////
315
+    ////////////////////////////////////////////////////////////////////
316
+
317
+    /**
318
+     * Prepend elements to the field
319
+     */
320
+    public function prepend()
321
+    {
322
+        $this->placeAround(func_get_args(), 'prepend');
323
+    }
324
+
325
+    /**
326
+     * Append elements to the field
327
+     */
328
+    public function append()
329
+    {
330
+        $this->placeAround(func_get_args(), 'append');
331
+    }
332
+
333
+    /**
334
+     * Prepends an icon to a field
335
+     *
336
+     * @param string $icon       The icon to prepend
337
+     * @param array  $attributes Its attributes
338
+     */
339
+    public function prependIcon($icon, $attributes = array(), $iconSettings = array())
340
+    {
341
+        $icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
342
+
343
+        $this->prepend($icon);
344
+    }
345
+
346
+    /**
347
+     * Append an icon to a field
348
+     *
349
+     * @param string $icon       The icon to prepend
350
+     * @param array  $attributes Its attributes
351
+     */
352
+    public function appendIcon($icon, $attributes = array(), $iconSettings = array())
353
+    {
354
+        $icon = $this->app['former.framework']->createIcon($icon, $attributes, $iconSettings);
355
+
356
+        $this->append($icon);
357
+    }
358
+
359
+    ////////////////////////////////////////////////////////////////////
360
+    //////////////////////////////// HELPERS ///////////////////////////
361
+    ////////////////////////////////////////////////////////////////////
362
+
363
+    /**
364
+     * Get the errors for the group
365
+     *
366
+     * @return string
367
+     */
368
+    public function getErrors()
369
+    {
370
+        $errors = '';
371
+
372
+        if (!self::$opened) {
373
+
374
+            // for non-custom groups, normal error handling applies
375
+            $errors = $this->app['former']->getErrors();
376
+        } elseif (!empty($this->validations)) {
377
+
378
+            // error handling only when validations specified for custom groups
379
+            foreach ($this->validations as $validation) {
380
+                $errors .= $this->app['former']->getErrors($validation);
381
+            }
382
+        }
383
+
384
+        return $errors;
385
+    }
386
+
387
+    /**
388
+     * Wraps content in a group
389
+     *
390
+     * @param string $contents The content
391
+     * @param string $label    The label to add
392
+     *
393
+     * @return string A group
394
+     */
395
+    public function wrap($contents, $label = null)
396
+    {
397
+        $group = $this->open();
398
+        $group .= $label;
399
+        $group .= $this->app['former.framework']->wrapField($contents);
400
+        $group .= $this->close();
401
+
402
+        return $group;
403
+    }
404
+
405
+    /**
406
+     * Prints out the current label
407
+     *
408
+     * @param  string $field The field to create a label for
409
+     *
410
+     * @return string        A <label> tag
411
+     */
412
+    protected function getLabel($field = null)
413
+    {
414
+        // Don't create a label if none exist
415
+        if (!$field or !$this->label) {
416
+            return null;
417
+        }
418
+
419
+        // Wrap label in framework classes
420
+        $this->label->addClass($this->app['former.framework']->getLabelClasses());
421
+        $this->label = $this->app['former.framework']->createLabelOf($field, $this->label);
422
+        $this->label = $this->app['former.framework']->wrapLabel($this->label);
423
+
424
+        return $this->label;
425
+    }
426
+
427
+    /**
428
+     * Prints out the current help
429
+     *
430
+     * @return string A .help-block or .help-inline
431
+     */
432
+    protected function getHelp()
433
+    {
434
+        $inline = Arr::get($this->help, 'inline');
435
+        $block  = Arr::get($this->help, 'block');
436
+
437
+        // Replace help text with error if any found
438
+        $errors = $this->app['former']->getErrors();
439
+        if ($errors and $this->app['former']->getOption('error_messages')) {
440
+            $inline = $this->app['former.framework']->createValidationError($errors);
441
+        }
442
+
443
+        return join(null, array($inline, $block));
444
+    }
445
+
446
+    /**
447
+     * Format the field with prepended/appended elements
448
+     *
449
+     * @param  Field $field The field to format
450
+     *
451
+     * @return string        Field plus supplementary elements
452
+     */
453
+    protected function prependAppend($field)
454
+    {
455
+        if (!$this->prepend and !$this->append) {
456
+            return $field->render();
457
+        }
458
+
459
+        return $this->app['former.framework']->prependAppend($field, $this->prepend, $this->append);
460
+    }
461
+
462
+    /**
463
+     * Place elements around the field
464
+     *
465
+     * @param  array  $items An array of items to place
466
+     * @param  string $place Where they should end up (prepend|append)
467
+     */
468
+    protected function placeAround($items, $place)
469
+    {
470
+        // Iterate over the items and place them where they should
471
+        foreach ((array) $items as $item) {
472
+            $item             = $this->app['former.framework']->placeAround($item);
473
+            $this->{$place}[] = $item;
474
+        }
475
+    }
476 476
 }
Please login to merge, or discard this patch.
src/Former/Former.php 1 patch
Indentation   +479 added lines, -479 removed lines patch added patch discarded remove patch
@@ -14,483 +14,483 @@
 block discarded – undo
14 14
  */
15 15
 class Former
16 16
 {
17
-	// Instances
18
-	////////////////////////////////////////////////////////////////////
19
-
20
-
21
-	/**
22
-	 * The current environment
23
-	 *
24
-	 * @var \Illuminate\Container\Container
25
-	 */
26
-	protected $app;
27
-
28
-	/**
29
-	 * The Method Dispatcher
30
-	 *
31
-	 * @var MethodDispatcher
32
-	 */
33
-	protected $dispatch;
34
-
35
-	// Informations
36
-	////////////////////////////////////////////////////////////////////
37
-
38
-	/**
39
-	 * The form's errors
40
-	 *
41
-	 * @var Message
42
-	 */
43
-	protected $errors;
44
-
45
-	/**
46
-	 * An array of rules to use
47
-	 *
48
-	 * @var array
49
-	 */
50
-	protected $rules = array();
51
-
52
-	/**
53
-	 * An array of field macros
54
-	 *
55
-	 * @var array
56
-	 */
57
-	protected $macros = array();
58
-
59
-	/**
60
-	 * The labels created so far
61
-	 *
62
-	 * @var array
63
-	 */
64
-	public $labels = array();
65
-
66
-	/**
67
-	 * The IDs created so far
68
-	 *
69
-	 * @var array
70
-	 */
71
-	public $ids = array();
72
-
73
-	/**
74
-	 * A lookup table where the key is the input name,
75
-	 * and the value is number of times seen. This is
76
-	 * used to calculate unique ids.
77
-	 *
78
-	 * @var array
79
-	 */
80
-	public $names = array();
81
-
82
-	// Namespaces
83
-	////////////////////////////////////////////////////////////////////
84
-
85
-	/**
86
-	 * The namespace of Form elements
87
-	 */
88
-	const FORMSPACE = 'Former\Form\\';
89
-
90
-	/**
91
-	 * The namespace of fields
92
-	 */
93
-	const FIELDSPACE = 'Former\Form\Fields\\';
94
-
95
-	/**
96
-	 * Build a new Former instance
97
-	 *
98
-	 * @param Container        $app
99
-	 * @param MethodDispatcher $dispatcher
100
-	 */
101
-	public function __construct(Container $app, MethodDispatcher $dispatcher)
102
-	{
103
-		$this->app      = $app;
104
-		$this->dispatch = $dispatcher;
105
-	}
106
-
107
-	////////////////////////////////////////////////////////////////////
108
-	//////////////////////////// INTERFACE /////////////////////////////
109
-	////////////////////////////////////////////////////////////////////
110
-
111
-	/**
112
-	 * Acts as a router that redirects methods to all of Former classes
113
-	 *
114
-	 * @param  string $method     The method called
115
-	 * @param  array  $parameters An array of parameters
116
-	 *
117
-	 * @return mixed
118
-	 */
119
-	public function __call($method, $parameters)
120
-	{
121
-		// Dispatch to Form\Elements
122
-		// Explicitly check false since closeGroup() may return an empty string
123
-		if (($element = $this->dispatch->toElements($method, $parameters)) !== false) {
124
-			return $element;
125
-		}
126
-
127
-		// Dispatch to Form\Form
128
-		if ($form = $this->dispatch->toForm($method, $parameters)) {
129
-			$this->app->instance('former.form', $form);
130
-
131
-			return $this->app['former.form'];
132
-		}
133
-
134
-		// Dispatch to Form\Group
135
-		if ($group = $this->dispatch->toGroup($method, $parameters)) {
136
-			return $group;
137
-		}
138
-
139
-		// Dispatch to Form\Actions
140
-		if ($actions = $this->dispatch->toActions($method, $parameters)) {
141
-			return $actions;
142
-		}
143
-
144
-		// Dispatch to macros
145
-		if ($macro = $this->dispatch->toMacros($method, $parameters)) {
146
-			return $macro;
147
-		}
148
-
149
-		// Checking for any supplementary classes
150
-		$modifiers = explode('_', $method);
151
-		$method  = array_pop($modifiers);
152
-
153
-		// Dispatch to the different Form\Fields
154
-		$field     = $this->dispatch->toFields($method, $parameters);
155
-		$field->setModifiers($modifiers);
156
-		$field->addClass('');
157
-
158
-		// Else bind field
159
-		$this->app->instance('former.field', $field);
160
-
161
-		return $this->app['former.field'];
162
-	}
163
-
164
-	////////////////////////////////////////////////////////////////////
165
-	//////////////////////////////// MACROS ////////////////////////////
166
-	////////////////////////////////////////////////////////////////////
167
-
168
-	/**
169
-	 * Register a macro with Former
170
-	 *
171
-	 * @param  string   $name  The name of the macro
172
-	 * @param  Callable $macro The macro itself
173
-	 *
174
-	 * @return mixed
175
-	 */
176
-	public function macro($name, $macro)
177
-	{
178
-		$this->macros[$name] = $macro;
179
-	}
180
-
181
-	/**
182
-	 * Check if a macro exists
183
-	 *
184
-	 * @param  string $name
185
-	 *
186
-	 * @return boolean
187
-	 */
188
-	public function hasMacro($name)
189
-	{
190
-		return isset($this->macros[$name]);
191
-	}
192
-
193
-	/**
194
-	 * Get a registered macro
195
-	 *
196
-	 * @param  string $name
197
-	 *
198
-	 * @return Closure
199
-	 */
200
-	public function getMacro($name)
201
-	{
202
-		return $this->macros[$name];
203
-	}
204
-
205
-	////////////////////////////////////////////////////////////////////
206
-	///////////////////////////// POPULATOR ////////////////////////////
207
-	////////////////////////////////////////////////////////////////////
208
-
209
-	/**
210
-	 * Add values to populate the array
211
-	 *
212
-	 * @param mixed $values Can be an Eloquent object or an array
213
-	 */
214
-	public function populate($values)
215
-	{
216
-		$this->app['former.populator']->replace($values);
217
-	}
218
-
219
-	/**
220
-	 * Set the value of a particular field
221
-	 *
222
-	 * @param string $field The field's name
223
-	 * @param mixed  $value Its new value
224
-	 */
225
-	public function populateField($field, $value)
226
-	{
227
-		$this->app['former.populator']->put($field, $value);
228
-	}
229
-
230
-	/**
231
-	 * Get the value of a field
232
-	 *
233
-	 * @param string $field The field's name
234
-	 * @param null   $fallback
235
-	 *
236
-	 * @return mixed
237
-	 */
238
-	public function getValue($field, $fallback = null)
239
-	{
240
-		return $this->app['former.populator']->get($field, $fallback);
241
-	}
242
-
243
-	/**
244
-	 * Fetch a field value from both the new and old POST array
245
-	 *
246
-	 * @param  string $name     A field name
247
-	 * @param  string $fallback A fallback if nothing was found
248
-	 *
249
-	 * @return string           The results
250
-	 */
251
-	public function getPost($name, $fallback = null)
252
-	{
253
-		$name     = str_replace(array('[', ']'), array('.', ''), $name);
254
-		$name     = trim($name, '.');
255
-		$oldValue = $this->app['request']->old($name, $fallback);
256
-
257
-		return $this->app['request']->input($name, $oldValue, true);
258
-	}
259
-
260
-	////////////////////////////////////////////////////////////////////
261
-	////////////////////////////// TOOLKIT /////////////////////////////
262
-	////////////////////////////////////////////////////////////////////
263
-
264
-	/**
265
-	 * Set the errors to use for validations
266
-	 *
267
-	 * @param Message $validator The result from a validation
268
-	 *
269
-	 * @return  void
270
-	 */
271
-	public function withErrors($validator = null)
272
-	{
273
-		// Try to get the errors form the session
274
-		if ($this->app['session']->has('errors')) {
275
-			$this->errors = $this->app['session']->get('errors');
276
-		}
277
-
278
-		// If we're given a raw Validator, go fetch the errors in it
279
-		if ($validator instanceof Validator) {
280
-			$this->errors = $validator->getMessageBag();
281
-		} else {
282
-			if ($validator instanceof MessageBag) {
283
-				$this->errors = $validator;
284
-			}
285
-		}
286
-
287
-		return $this->errors;
288
-	}
289
-
290
-	/**
291
-	 * Add live validation rules
292
-	 *
293
-	 * @param  array *$rules An array of Laravel rules
294
-	 *
295
-	 * @return  void
296
-	 */
297
-	public function withRules()
298
-	{
299
-		$rules = call_user_func_array('array_merge', func_get_args());
300
-
301
-		// Parse the rules according to Laravel conventions
302
-		foreach ($rules as $name => $fieldRules) {
303
-			$expFieldRules = $fieldRules;
304
-			if (!is_array($expFieldRules)) {
305
-				$expFieldRules = explode('|', $expFieldRules);
306
-				$expFieldRules = array_map('trim', $expFieldRules);
307
-			}
308
-
309
-			foreach ($expFieldRules as $rule) {
310
-
311
-				$parameters = null;
312
-
313
-				if (($colon = strpos($rule, ':')) !== false) {
314
-					$rulename = substr($rule, 0, $colon);
315
-
316
-					/**
317
-					 * Regular expressions may contain commas and should not be divided by str_getcsv.
318
-					 * For regular expressions we are just using the complete expression as a parameter.
319
-					 */
320
-					if ($rulename !== 'regex') {
321
-						$parameters = str_getcsv(substr($rule, $colon + 1));
322
-					} else {
323
-						$parameters = [substr($rule, $colon + 1)];
324
-					}
325
-				}
326
-
327
-				// Exclude unsupported rules
328
-				$rule = is_numeric($colon) ? substr($rule, 0, $colon) : $rule;
329
-
330
-				// Store processed rule in Former's array
331
-				if (!isset($parameters)) {
332
-					$parameters = array();
333
-				}
334
-
335
-				$this->rules[$name][$rule] = $parameters;
336
-			}
337
-		}
338
-	}
339
-
340
-	/**
341
-	 * Switch the framework used by Former
342
-	 *
343
-	 * @param string $framework The name of the framework to use
344
-	 */
345
-	public function framework($framework = null)
346
-	{
347
-		if (!$framework) {
348
-			return $this->app['former.framework']->current();
349
-		}
350
-
351
-		$this->setOption('framework', $framework);
352
-
353
-		$framework = $this->getFrameworkInstance($framework);
354
-		$this->app->bind('former.framework', function ($app) use ($framework) {
355
-			return $framework;
356
-		});
357
-	}
358
-
359
-	/**
360
-	 * Get a new framework instance
361
-	 *
362
-	 * @param string $framework
363
-	 *
364
-	 * @throws Exceptions\InvalidFrameworkException
365
-	 * @return \Former\Interfaces\FrameworkInterface
366
-	 */
367
-	public function getFrameworkInstance($framework)
368
-	{
369
-		$formerClass = __NAMESPACE__.'\Framework\\'.$framework;
370
-
371
-		//get interfaces of the given framework
372
-		$interfaces = class_exists($framework) ? class_implements($framework) : array();
373
-
374
-		if(class_exists($formerClass)) {
375
-			$returnClass = $formerClass;
376
-		} elseif(class_exists($framework) && isset($interfaces['Former\Interfaces\FrameworkInterface'])) {
377
-			// We have some outside class, lets return it.
378
-			$returnClass = $framework;
379
-		} else {
380
-			throw (new InvalidFrameworkException())->setFramework($framework);
381
-		}
382
-
383
-		return new $returnClass($this->app);
384
-	}
385
-
386
-	/**
387
-	 * Get an option from the config
388
-	 *
389
-	 * @param string $option  The option
390
-	 * @param mixed  $default Optional fallback
391
-	 *
392
-	 * @return mixed
393
-	 */
394
-	public function getOption($option, $default = null)
395
-	{
396
-		return $this->app['config']->get('former.'.$option, $default);
397
-	}
398
-
399
-	/**
400
-	 * Set an option on the config
401
-	 *
402
-	 * @param string $option
403
-	 * @param string $value
404
-	 */
405
-	public function setOption($option, $value)
406
-	{
407
-		return $this->app['config']->set('former.'.$option, $value);
408
-	}
409
-
410
-	////////////////////////////////////////////////////////////////////
411
-	////////////////////////////// BUILDERS ////////////////////////////
412
-	////////////////////////////////////////////////////////////////////
413
-
414
-	/**
415
-	 * Closes a form
416
-	 *
417
-	 * @return string A form closing tag
418
-	 */
419
-	public function close()
420
-	{
421
-		if ($this->app->bound('former.form')) {
422
-			$closing = $this->app['former.form']->close();
423
-		}
424
-
425
-		// Destroy instances
426
-		$instances = array('former.form', 'former.form.framework');
427
-		foreach ($instances as $instance) {
428
-			$this->app[$instance] = null;
429
-			unset($this->app[$instance]);
430
-		}
431
-
432
-		// Reset populator
433
-		$this->app['former.populator']->reset();
434
-
435
-		// Reset all values
436
-		$this->errors = null;
437
-		$this->rules  = array();
438
-
439
-		return isset($closing) ? $closing : null;
440
-	}
441
-
442
-	////////////////////////////////////////////////////////////////////
443
-	////////////////////////////// HELPERS /////////////////////////////
444
-	////////////////////////////////////////////////////////////////////
445
-
446
-	/**
447
-	 * Get the errors for the current field
448
-	 *
449
-	 * @param  string $name A field name
450
-	 *
451
-	 * @return string       An error message
452
-	 */
453
-	public function getErrors($name = null)
454
-	{
455
-		// Get name and translate array notation
456
-		if (!$name and $this->app['former.field']) {
457
-			$name = $this->app['former.field']->getName();
458
-
459
-			// Always return empty string for anonymous fields (i.e. fields with no name/id)
460
-			if (!$name) {
461
-				return '';
462
-			}
463
-		}
464
-
465
-		if ($this->errors and $name) {
466
-			$name = str_replace(array('[', ']'), array('.', ''), $name);
467
-			$name = trim($name, '.');
468
-
469
-			return $this->errors->first($name);
470
-		}
471
-
472
-		return $this->errors;
473
-	}
474
-
475
-	/**
476
-	 * Get a rule from the Rules array
477
-	 *
478
-	 * @param  string $name The field to fetch
479
-	 *
480
-	 * @return array        An array of rules
481
-	 */
482
-	public function getRules($name)
483
-	{
484
-		// Check the rules for the name as given
485
-		$ruleset = Arr::get($this->rules, $name);
486
-
487
-		// If no rules found, convert to dot notation and try again
488
-		if (is_null($ruleset)) {
489
-			$name = str_replace(array('[', ']'), array('.', ''), $name);
490
-			$name = trim($name, '.');
491
-			$ruleset = Arr::get($this->rules, $name);
492
-		}
493
-
494
-		return $ruleset;
495
-	}
17
+    // Instances
18
+    ////////////////////////////////////////////////////////////////////
19
+
20
+
21
+    /**
22
+     * The current environment
23
+     *
24
+     * @var \Illuminate\Container\Container
25
+     */
26
+    protected $app;
27
+
28
+    /**
29
+     * The Method Dispatcher
30
+     *
31
+     * @var MethodDispatcher
32
+     */
33
+    protected $dispatch;
34
+
35
+    // Informations
36
+    ////////////////////////////////////////////////////////////////////
37
+
38
+    /**
39
+     * The form's errors
40
+     *
41
+     * @var Message
42
+     */
43
+    protected $errors;
44
+
45
+    /**
46
+     * An array of rules to use
47
+     *
48
+     * @var array
49
+     */
50
+    protected $rules = array();
51
+
52
+    /**
53
+     * An array of field macros
54
+     *
55
+     * @var array
56
+     */
57
+    protected $macros = array();
58
+
59
+    /**
60
+     * The labels created so far
61
+     *
62
+     * @var array
63
+     */
64
+    public $labels = array();
65
+
66
+    /**
67
+     * The IDs created so far
68
+     *
69
+     * @var array
70
+     */
71
+    public $ids = array();
72
+
73
+    /**
74
+     * A lookup table where the key is the input name,
75
+     * and the value is number of times seen. This is
76
+     * used to calculate unique ids.
77
+     *
78
+     * @var array
79
+     */
80
+    public $names = array();
81
+
82
+    // Namespaces
83
+    ////////////////////////////////////////////////////////////////////
84
+
85
+    /**
86
+     * The namespace of Form elements
87
+     */
88
+    const FORMSPACE = 'Former\Form\\';
89
+
90
+    /**
91
+     * The namespace of fields
92
+     */
93
+    const FIELDSPACE = 'Former\Form\Fields\\';
94
+
95
+    /**
96
+     * Build a new Former instance
97
+     *
98
+     * @param Container        $app
99
+     * @param MethodDispatcher $dispatcher
100
+     */
101
+    public function __construct(Container $app, MethodDispatcher $dispatcher)
102
+    {
103
+        $this->app      = $app;
104
+        $this->dispatch = $dispatcher;
105
+    }
106
+
107
+    ////////////////////////////////////////////////////////////////////
108
+    //////////////////////////// INTERFACE /////////////////////////////
109
+    ////////////////////////////////////////////////////////////////////
110
+
111
+    /**
112
+     * Acts as a router that redirects methods to all of Former classes
113
+     *
114
+     * @param  string $method     The method called
115
+     * @param  array  $parameters An array of parameters
116
+     *
117
+     * @return mixed
118
+     */
119
+    public function __call($method, $parameters)
120
+    {
121
+        // Dispatch to Form\Elements
122
+        // Explicitly check false since closeGroup() may return an empty string
123
+        if (($element = $this->dispatch->toElements($method, $parameters)) !== false) {
124
+            return $element;
125
+        }
126
+
127
+        // Dispatch to Form\Form
128
+        if ($form = $this->dispatch->toForm($method, $parameters)) {
129
+            $this->app->instance('former.form', $form);
130
+
131
+            return $this->app['former.form'];
132
+        }
133
+
134
+        // Dispatch to Form\Group
135
+        if ($group = $this->dispatch->toGroup($method, $parameters)) {
136
+            return $group;
137
+        }
138
+
139
+        // Dispatch to Form\Actions
140
+        if ($actions = $this->dispatch->toActions($method, $parameters)) {
141
+            return $actions;
142
+        }
143
+
144
+        // Dispatch to macros
145
+        if ($macro = $this->dispatch->toMacros($method, $parameters)) {
146
+            return $macro;
147
+        }
148
+
149
+        // Checking for any supplementary classes
150
+        $modifiers = explode('_', $method);
151
+        $method  = array_pop($modifiers);
152
+
153
+        // Dispatch to the different Form\Fields
154
+        $field     = $this->dispatch->toFields($method, $parameters);
155
+        $field->setModifiers($modifiers);
156
+        $field->addClass('');
157
+
158
+        // Else bind field
159
+        $this->app->instance('former.field', $field);
160
+
161
+        return $this->app['former.field'];
162
+    }
163
+
164
+    ////////////////////////////////////////////////////////////////////
165
+    //////////////////////////////// MACROS ////////////////////////////
166
+    ////////////////////////////////////////////////////////////////////
167
+
168
+    /**
169
+     * Register a macro with Former
170
+     *
171
+     * @param  string   $name  The name of the macro
172
+     * @param  Callable $macro The macro itself
173
+     *
174
+     * @return mixed
175
+     */
176
+    public function macro($name, $macro)
177
+    {
178
+        $this->macros[$name] = $macro;
179
+    }
180
+
181
+    /**
182
+     * Check if a macro exists
183
+     *
184
+     * @param  string $name
185
+     *
186
+     * @return boolean
187
+     */
188
+    public function hasMacro($name)
189
+    {
190
+        return isset($this->macros[$name]);
191
+    }
192
+
193
+    /**
194
+     * Get a registered macro
195
+     *
196
+     * @param  string $name
197
+     *
198
+     * @return Closure
199
+     */
200
+    public function getMacro($name)
201
+    {
202
+        return $this->macros[$name];
203
+    }
204
+
205
+    ////////////////////////////////////////////////////////////////////
206
+    ///////////////////////////// POPULATOR ////////////////////////////
207
+    ////////////////////////////////////////////////////////////////////
208
+
209
+    /**
210
+     * Add values to populate the array
211
+     *
212
+     * @param mixed $values Can be an Eloquent object or an array
213
+     */
214
+    public function populate($values)
215
+    {
216
+        $this->app['former.populator']->replace($values);
217
+    }
218
+
219
+    /**
220
+     * Set the value of a particular field
221
+     *
222
+     * @param string $field The field's name
223
+     * @param mixed  $value Its new value
224
+     */
225
+    public function populateField($field, $value)
226
+    {
227
+        $this->app['former.populator']->put($field, $value);
228
+    }
229
+
230
+    /**
231
+     * Get the value of a field
232
+     *
233
+     * @param string $field The field's name
234
+     * @param null   $fallback
235
+     *
236
+     * @return mixed
237
+     */
238
+    public function getValue($field, $fallback = null)
239
+    {
240
+        return $this->app['former.populator']->get($field, $fallback);
241
+    }
242
+
243
+    /**
244
+     * Fetch a field value from both the new and old POST array
245
+     *
246
+     * @param  string $name     A field name
247
+     * @param  string $fallback A fallback if nothing was found
248
+     *
249
+     * @return string           The results
250
+     */
251
+    public function getPost($name, $fallback = null)
252
+    {
253
+        $name     = str_replace(array('[', ']'), array('.', ''), $name);
254
+        $name     = trim($name, '.');
255
+        $oldValue = $this->app['request']->old($name, $fallback);
256
+
257
+        return $this->app['request']->input($name, $oldValue, true);
258
+    }
259
+
260
+    ////////////////////////////////////////////////////////////////////
261
+    ////////////////////////////// TOOLKIT /////////////////////////////
262
+    ////////////////////////////////////////////////////////////////////
263
+
264
+    /**
265
+     * Set the errors to use for validations
266
+     *
267
+     * @param Message $validator The result from a validation
268
+     *
269
+     * @return  void
270
+     */
271
+    public function withErrors($validator = null)
272
+    {
273
+        // Try to get the errors form the session
274
+        if ($this->app['session']->has('errors')) {
275
+            $this->errors = $this->app['session']->get('errors');
276
+        }
277
+
278
+        // If we're given a raw Validator, go fetch the errors in it
279
+        if ($validator instanceof Validator) {
280
+            $this->errors = $validator->getMessageBag();
281
+        } else {
282
+            if ($validator instanceof MessageBag) {
283
+                $this->errors = $validator;
284
+            }
285
+        }
286
+
287
+        return $this->errors;
288
+    }
289
+
290
+    /**
291
+     * Add live validation rules
292
+     *
293
+     * @param  array *$rules An array of Laravel rules
294
+     *
295
+     * @return  void
296
+     */
297
+    public function withRules()
298
+    {
299
+        $rules = call_user_func_array('array_merge', func_get_args());
300
+
301
+        // Parse the rules according to Laravel conventions
302
+        foreach ($rules as $name => $fieldRules) {
303
+            $expFieldRules = $fieldRules;
304
+            if (!is_array($expFieldRules)) {
305
+                $expFieldRules = explode('|', $expFieldRules);
306
+                $expFieldRules = array_map('trim', $expFieldRules);
307
+            }
308
+
309
+            foreach ($expFieldRules as $rule) {
310
+
311
+                $parameters = null;
312
+
313
+                if (($colon = strpos($rule, ':')) !== false) {
314
+                    $rulename = substr($rule, 0, $colon);
315
+
316
+                    /**
317
+                     * Regular expressions may contain commas and should not be divided by str_getcsv.
318
+                     * For regular expressions we are just using the complete expression as a parameter.
319
+                     */
320
+                    if ($rulename !== 'regex') {
321
+                        $parameters = str_getcsv(substr($rule, $colon + 1));
322
+                    } else {
323
+                        $parameters = [substr($rule, $colon + 1)];
324
+                    }
325
+                }
326
+
327
+                // Exclude unsupported rules
328
+                $rule = is_numeric($colon) ? substr($rule, 0, $colon) : $rule;
329
+
330
+                // Store processed rule in Former's array
331
+                if (!isset($parameters)) {
332
+                    $parameters = array();
333
+                }
334
+
335
+                $this->rules[$name][$rule] = $parameters;
336
+            }
337
+        }
338
+    }
339
+
340
+    /**
341
+     * Switch the framework used by Former
342
+     *
343
+     * @param string $framework The name of the framework to use
344
+     */
345
+    public function framework($framework = null)
346
+    {
347
+        if (!$framework) {
348
+            return $this->app['former.framework']->current();
349
+        }
350
+
351
+        $this->setOption('framework', $framework);
352
+
353
+        $framework = $this->getFrameworkInstance($framework);
354
+        $this->app->bind('former.framework', function ($app) use ($framework) {
355
+            return $framework;
356
+        });
357
+    }
358
+
359
+    /**
360
+     * Get a new framework instance
361
+     *
362
+     * @param string $framework
363
+     *
364
+     * @throws Exceptions\InvalidFrameworkException
365
+     * @return \Former\Interfaces\FrameworkInterface
366
+     */
367
+    public function getFrameworkInstance($framework)
368
+    {
369
+        $formerClass = __NAMESPACE__.'\Framework\\'.$framework;
370
+
371
+        //get interfaces of the given framework
372
+        $interfaces = class_exists($framework) ? class_implements($framework) : array();
373
+
374
+        if(class_exists($formerClass)) {
375
+            $returnClass = $formerClass;
376
+        } elseif(class_exists($framework) && isset($interfaces['Former\Interfaces\FrameworkInterface'])) {
377
+            // We have some outside class, lets return it.
378
+            $returnClass = $framework;
379
+        } else {
380
+            throw (new InvalidFrameworkException())->setFramework($framework);
381
+        }
382
+
383
+        return new $returnClass($this->app);
384
+    }
385
+
386
+    /**
387
+     * Get an option from the config
388
+     *
389
+     * @param string $option  The option
390
+     * @param mixed  $default Optional fallback
391
+     *
392
+     * @return mixed
393
+     */
394
+    public function getOption($option, $default = null)
395
+    {
396
+        return $this->app['config']->get('former.'.$option, $default);
397
+    }
398
+
399
+    /**
400
+     * Set an option on the config
401
+     *
402
+     * @param string $option
403
+     * @param string $value
404
+     */
405
+    public function setOption($option, $value)
406
+    {
407
+        return $this->app['config']->set('former.'.$option, $value);
408
+    }
409
+
410
+    ////////////////////////////////////////////////////////////////////
411
+    ////////////////////////////// BUILDERS ////////////////////////////
412
+    ////////////////////////////////////////////////////////////////////
413
+
414
+    /**
415
+     * Closes a form
416
+     *
417
+     * @return string A form closing tag
418
+     */
419
+    public function close()
420
+    {
421
+        if ($this->app->bound('former.form')) {
422
+            $closing = $this->app['former.form']->close();
423
+        }
424
+
425
+        // Destroy instances
426
+        $instances = array('former.form', 'former.form.framework');
427
+        foreach ($instances as $instance) {
428
+            $this->app[$instance] = null;
429
+            unset($this->app[$instance]);
430
+        }
431
+
432
+        // Reset populator
433
+        $this->app['former.populator']->reset();
434
+
435
+        // Reset all values
436
+        $this->errors = null;
437
+        $this->rules  = array();
438
+
439
+        return isset($closing) ? $closing : null;
440
+    }
441
+
442
+    ////////////////////////////////////////////////////////////////////
443
+    ////////////////////////////// HELPERS /////////////////////////////
444
+    ////////////////////////////////////////////////////////////////////
445
+
446
+    /**
447
+     * Get the errors for the current field
448
+     *
449
+     * @param  string $name A field name
450
+     *
451
+     * @return string       An error message
452
+     */
453
+    public function getErrors($name = null)
454
+    {
455
+        // Get name and translate array notation
456
+        if (!$name and $this->app['former.field']) {
457
+            $name = $this->app['former.field']->getName();
458
+
459
+            // Always return empty string for anonymous fields (i.e. fields with no name/id)
460
+            if (!$name) {
461
+                return '';
462
+            }
463
+        }
464
+
465
+        if ($this->errors and $name) {
466
+            $name = str_replace(array('[', ']'), array('.', ''), $name);
467
+            $name = trim($name, '.');
468
+
469
+            return $this->errors->first($name);
470
+        }
471
+
472
+        return $this->errors;
473
+    }
474
+
475
+    /**
476
+     * Get a rule from the Rules array
477
+     *
478
+     * @param  string $name The field to fetch
479
+     *
480
+     * @return array        An array of rules
481
+     */
482
+    public function getRules($name)
483
+    {
484
+        // Check the rules for the name as given
485
+        $ruleset = Arr::get($this->rules, $name);
486
+
487
+        // If no rules found, convert to dot notation and try again
488
+        if (is_null($ruleset)) {
489
+            $name = str_replace(array('[', ']'), array('.', ''), $name);
490
+            $name = trim($name, '.');
491
+            $ruleset = Arr::get($this->rules, $name);
492
+        }
493
+
494
+        return $ruleset;
495
+    }
496 496
 }
Please login to merge, or discard this patch.