Completed
Push — master ( 1a0349...c60a32 )
by Ben
09:05
created

TwitterBootstrap4::createValidationError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
namespace Former\Framework;
3
4
use Former\Interfaces\FrameworkInterface;
5
use Former\Traits\Field;
6
use Former\Traits\Framework;
7
use HtmlObject\Element;
8
use Illuminate\Container\Container;
9
use Illuminate\Support\Str;
10
11
/**
12
 * The Twitter Bootstrap form framework
13
 */
14
class TwitterBootstrap4 extends Framework implements FrameworkInterface
15
{
16
	/**
17
	 * Form types that trigger special styling for this Framework
18
	 *
19
	 * @var array
20
	 */
21
	protected $availableTypes = array('horizontal', 'vertical', 'inline');
22
23
	/**
24
	 * The button types available
25
	 *
26
	 * @var array
27
	 */
28
	private $buttons = array(
0 ignored issues
show
Unused Code introduced by
The property $buttons is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
29
		'lg',
30
		'sm',
31
		'xs',
32
		'block',
33
		'link',
34
		'primary',
35
		'secondary',
36
		'warning',
37
		'danger',
38
		'success',
39
		'info',
40
		'light',
41
		'dark',
42
	);
43
44
	/**
45
	 * The field sizes available
46
	 *
47
	 * @var array
48
	 */
49
	private $fields = array(
50
		'lg',
51
		'sm',
52
		// 'col-xs-1', 'col-xs-2', 'col-xs-3', 'col-xs-4', 'col-xs-5', 'col-xs-6',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
53
		// 'col-xs-7', 'col-xs-8', 'col-xs-9', 'col-xs-10', 'col-xs-11', 'col-xs-12',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
54
		// 'col-sm-1', 'col-sm-2', 'col-sm-3', 'col-sm-4', 'col-sm-5', 'col-sm-6',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
55
		// 'col-sm-7', 'col-sm-8', 'col-sm-9', 'col-sm-10', 'col-sm-11', 'col-sm-12',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
56
		// 'col-md-1', 'col-md-2', 'col-md-3', 'col-md-4', 'col-md-5', 'col-md-6',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
57
		// 'col-md-7', 'col-md-8', 'col-md-9', 'col-md-10', 'col-md-11', 'col-md-12',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
58
		// 'col-lg-1', 'col-lg-2', 'col-lg-3', 'col-lg-4', 'col-lg-5', 'col-lg-6',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
59
		// 'col-lg-7', 'col-lg-8', 'col-lg-9', 'col-lg-10', 'col-lg-11', 'col-lg-12',
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
60
	);
61
62
	/**
63
	 * The field states available
64
	 *
65
	 * @var array
66
	 */
67
	protected $states = array(
68
		'is-invalid',
69
	);
70
71
	/**
72
	 * The default HTML tag used for icons
73
	 *
74
	 * @var string
75
	 */
76
	protected $iconTag = 'i';
77
78
	/**
79
	 * The default set for icon fonts
80
	 * By default Bootstrap 4 offers no fonts, but we'll add Font Awesome
81
	 *
82
	 * @var string
83
	 */
84
	protected $iconSet = 'fa';
85
86
	/**
87
	 * The default prefix icon names
88
	 * Using Font Awesome 5, this can be 'fa' or 'fas' for solid, 'far' for regular
89
	 *
90
	 * @var string
91
	 */
92
	protected $iconPrefix = 'fa';
93
94
	/**
95
	 * Create a new TwitterBootstrap instance
96
	 *
97
	 * @param \Illuminate\Container\Container $app
98
	 */
99
	public function __construct(Container $app)
100
	{
101
		$this->app = $app;
0 ignored issues
show
Documentation Bug introduced by
It seems like $app of type object<Illuminate\Container\Container> is incompatible with the declared type object<Former\Traits\Container> of property $app.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
102
		$this->setFrameworkDefaults();
103
	}
104
105
	////////////////////////////////////////////////////////////////////
106
	/////////////////////////// FILTER ARRAYS //////////////////////////
107
	////////////////////////////////////////////////////////////////////
108
109
	/**
110
	 * Filter buttons classes
111
	 *
112
	 * @param  array $classes An array of classes
113
	 *
114
	 * @return string[] A filtered array
115
	 */
116
	public function filterButtonClasses($classes)
117
	{
118
		// Filter classes
119
		// $classes = array_intersect($classes, $this->buttons);
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
120
121
		// Prepend button type
122
		$classes   = $this->prependWith($classes, 'btn-');
123
		$classes[] = 'btn';
124
125
		return $classes;
126
	}
127
128
	/**
129
	 * Filter field classes
130
	 *
131
	 * @param  array $classes An array of classes
132
	 *
133
	 * @return array A filtered array
134
	 */
135
	public function filterFieldClasses($classes)
136
	{
137
		// Filter classes
138
		$classes = array_intersect($classes, $this->fields);
139
140
		// Prepend field type
141
		$classes = array_map(function ($class) {
142
			return Str::startsWith($class, 'col') ? $class : 'input-'.$class;
143
		}, $classes);
144
145
		return $classes;
146
	}
147
148
	////////////////////////////////////////////////////////////////////
149
	///////////////////// EXPOSE FRAMEWORK SPECIFICS ///////////////////
150
	////////////////////////////////////////////////////////////////////
151
152
	/**
153
	 * Framework error state
154
	 *
155
	 * @return string
156
	 */
157
	public function errorState()
158
	{
159
		return 'is-invalid';
160
	}
161
162
	/**
163
	 * Returns corresponding inline class of a field
164
	 *
165
	 * @param Field $field
166
	 *
167
	 * @return string
168
	 */
169
	public function getInlineLabelClass($field)
170
	{
171
		$inlineClass = parent::getInlineLabelClass($field);
172
		if ($field->isOfType('checkbox', 'checkboxes', 'radio', 'radios')) {
173
			$inlineClass = 'form-check-label';
174
		}
175
176
		return $inlineClass;
177
	}
178
179
	/**
180
	 * Set the fields width from a label width
181
	 *
182
	 * @param array $labelWidths
183
	 */
184
	protected function setFieldWidths($labelWidths)
185
	{
186
		$labelWidthClass = $fieldWidthClass = $fieldOffsetClass = '';
187
188
		$viewports = $this->getFrameworkOption('viewports');
189
		foreach ($labelWidths as $viewport => $columns) {
190
			if ($viewport) {
191
				$labelWidthClass .= " col-$viewports[$viewport]-$columns";
192
				$fieldWidthClass .= " col-$viewports[$viewport]-".(12 - $columns);
193
				$fieldOffsetClass .= " col-$viewports[$viewport]-offset-$columns";
194
			}
195
		}
196
197
		$this->labelWidth  = ltrim($labelWidthClass);
198
		$this->fieldWidth  = ltrim($fieldWidthClass);
199
		$this->fieldOffset = ltrim($fieldOffsetClass);
200
	}
201
202
	////////////////////////////////////////////////////////////////////
203
	///////////////////////////// ADD CLASSES //////////////////////////
204
	////////////////////////////////////////////////////////////////////
205
206
	/**
207
	 * Add classes to a field
208
	 *
209
	 * @param Field $field
210
	 * @param array $classes The possible classes to add
211
	 *
212
	 * @return Field
213
	 */
214
	public function getFieldClasses(Field $field, $classes)
215
	{
216
		// Add inline class for checkables
217
		if ($field->isCheckable()) {
218
			$classes[] = 'form-check';
219
220
			if (in_array('inline', $classes)) {
221
				$field->inline();
0 ignored issues
show
Documentation Bug introduced by
The method inline does not exist on object<Former\Traits\Field>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
222
			}
223
		}
224
225
		// Filter classes according to field type
226
		if ($field->isButton()) {
227
			$classes = $this->filterButtonClasses($classes);
228
		} else {
229
			$classes = $this->filterFieldClasses($classes);
230
		}
231
232
		// Add form-control class for text-type, textarea and select fields
233
		// As text-type is open-ended we instead exclude those that shouldn't receive the class
234
		if (!$field->isCheckable() and !$field->isButton() and !in_array($field->getType(), array(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
235
					'file',
236
					'plaintext',
237
				)) and !in_array('form-control', $classes)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
238
		) {
239
			$classes[] = 'form-control';
240
		}
241
242
		if ($this->app['former']->getErrors($field->getName())) {
243
			$classes[] = $this->errorState();
244
		}
245
246
		return $this->addClassesToField($field, $classes);
247
	}
248
249
	/**
250
	 * Add group classes
251
	 *
252
	 * @return string A list of group classes
253
	 */
254
	public function getGroupClasses()
255
	{
256
		if ($this->app['former.form']->isOfType('horizontal')) {
257
			return 'form-group row';
258
		} else {
259
			return 'form-group';
260
		}
261
	}
262
263
	/**
264
	 * Add label classes
265
	 *
266
	 * @return string[] An array of attributes with the label class
267
	 */
268
	public function getLabelClasses()
269
	{
270
		if ($this->app['former.form']->isOfType('horizontal')) {
271
			return array('control-label', $this->labelWidth);
272
		} elseif ($this->app['former.form']->isOfType('inline')) {
273
			return array('sr-only');
274
		} else {
275
			return array('control-label');
276
		}
277
	}
278
279
	/**
280
	 * Add uneditable field classes
281
	 *
282
	 * @return string An array of attributes with the uneditable class
283
	 */
284
	public function getUneditableClasses()
285
	{
286
		return '';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return ''; (string) is incompatible with the return type declared by the interface Former\Interfaces\Framew...e::getUneditableClasses of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
287
	}
288
289
	/**
290
	 * Add plain text field classes
291
	 *
292
	 * @return string An array of attributes with the plain text class
293
	 */
294
	public function getPlainTextClasses()
295
	{
296
		return 'form-control-static';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return 'form-control-static'; (string) is incompatible with the return type declared by the interface Former\Interfaces\Framew...ce::getPlainTextClasses of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
297
	}
298
299
	/**
300
	 * Add form class
301
	 *
302
	 * @param  string $type The type of form to add
303
	 *
304
	 * @return string|null
305
	 */
306
	public function getFormClasses($type)
307
	{
308
		return $type ? 'form-'.$type : null;
0 ignored issues
show
Bug Compatibility introduced by
The expression $type ? 'form-' . $type : null; of type string|null adds the type string to the return on line 308 which is incompatible with the return type declared by the interface Former\Interfaces\Framew...terface::getFormClasses of type array.
Loading history...
309
	}
310
311
	/**
312
	 * Add actions block class
313
	 *
314
	 * @return string|null
315
	 */
316
	public function getActionClasses()
317
	{
318
		if ($this->app['former.form']->isOfType('horizontal') || $this->app['former.form']->isOfType('inline')) {
319
			return 'form-group row';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return 'form-group row'; (string) is incompatible with the return type declared by the interface Former\Interfaces\Framew...rface::getActionClasses of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
320
		}
321
322
		return null;
323
	}
324
325
	////////////////////////////////////////////////////////////////////
326
	//////////////////////////// RENDER BLOCKS /////////////////////////
327
	////////////////////////////////////////////////////////////////////
328
329
	/**
330
	 * Render an help text
331
	 *
332
	 * @param string $text
333
	 * @param array  $attributes
334
	 *
335
	 * @return Element
336
	 */
337
	public function createHelp($text, $attributes = array())
338
	{
339
		return Element::create('small', $text, $attributes)->addClass('text-muted');
340
	}
341
342
	/**
343
	 * Render an validation error text
344
	 *
345
	 * @param string $text
346
	 * @param array  $attributes
347
	 *
348
	 * @return string
349
	 */
350
	public function createValidationError($text, $attributes = array())
351
	{
352
		return Element::create('div', $text, $attributes)->addClass('invalid-feedback');
353
	}
354
355
	/**
356
	 * Render an help text
357
	 *
358
	 * @param string $text
359
	 * @param array  $attributes
360
	 *
361
	 * @return Element
362
	 */
363
	public function createBlockHelp($text, $attributes = array())
364
	{
365
		return Element::create('small', $text, $attributes)->addClass('form-text text-muted');
366
	}
367
368
	/**
369
	 * Render a disabled field
370
	 *
371
	 * @param Field $field
372
	 *
373
	 * @return Element
374
	 */
375
	public function createDisabledField(Field $field)
376
	{
377
		return Element::create('span', $field->getValue(), $field->getAttributes());
378
	}
379
380
	/**
381
	 * Render a plain text field
382
	 *
383
	 * @param Field $field
384
	 *
385
	 * @return Element
386
	 */
387
	public function createPlainTextField(Field $field)
388
	{
389
		$label = $field->getLabel();
390
		if ($label) {
391
			$label->for('');
0 ignored issues
show
Bug introduced by
The method for cannot be called on $label (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
392
		}
393
394
		return Element::create('div', $field->getValue(), $field->getAttributes());
395
	}
396
397
	////////////////////////////////////////////////////////////////////
398
	//////////////////////////// WRAP BLOCKS ///////////////////////////
399
	////////////////////////////////////////////////////////////////////
400
401
	/**
402
	 * Wrap an item to be prepended or appended to the current field
403
	 *
404
	 * @return Element A wrapped item
405
	 */
406
	public function placeAround($item)
407
	{
408
		// Render object
409
		if (is_object($item) and method_exists($item, '__toString')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
410
			$item = $item->__toString();
411
		}
412
413
		// Get class to use
414
		$class = (strpos($item, '<button') !== false) ? 'btn' : 'addon';
415
416
		return Element::create('span', $item)->addClass('input-group-'.$class);
417
	}
418
419
	/**
420
	 * Wrap a field with prepended and appended items
421
	 *
422
	 * @param  Field $field
423
	 * @param  array $prepend
424
	 * @param  array $append
425
	 *
426
	 * @return string A field concatented with prepended and/or appended items
427
	 */
428
	public function prependAppend($field, $prepend, $append)
429
	{
430
		$return = '<div class="input-group">';
431
		$return .= join(null, $prepend);
432
		$return .= $field->render();
433
		$return .= join(null, $append);
434
		$return .= '</div>';
435
436
		return $return;
437
	}
438
439
	/**
440
	 * Wrap a field with potential additional tags
441
	 *
442
	 * @param  Field $field
443
	 *
444
	 * @return Element A wrapped field
445
	 */
446
	public function wrapField($field)
447
	{
448
		if ($this->app['former.form']->isOfType('horizontal')) {
449
			return Element::create('div', $field)->addClass($this->fieldWidth);
450
		}
451
452
		return $field;
453
	}
454
455
	/**
456
	 * Wrap actions block with potential additional tags
457
	 *
458
	 * @param  Actions $actions
459
	 *
460
	 * @return string A wrapped actions block
461
	 */
462
	public function wrapActions($actions)
463
	{
464
		// For horizontal forms, we wrap the actions in a div
465
		if ($this->app['former.form']->isOfType('horizontal')) {
466
			return Element::create('div', $actions)->addClass(array($this->fieldOffset, $this->fieldWidth));
0 ignored issues
show
Documentation introduced by
array($this->fieldOffset, $this->fieldWidth) is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
467
		}
468
469
		return $actions;
470
	}
471
}
472