Field::getTitle()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 5
nop 0
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
/**
3
 * Part of the Joomla Framework Form Package
4
 *
5
 * @copyright  Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
6
 * @license    GNU General Public License version 2 or later; see LICENSE
7
 */
8
9
namespace Joomla\Form;
10
11
12
use Joomla\String\StringHelper;
13
use Joomla\String\Normalise;
14
use Joomla\Language\Text;
15
use SimpleXMLElement;
16
17
/**
18
 * Abstract Form Field class for the Joomla Framework.
19
 *
20
 * @since       1.0
21
 * @deprecated  The joomla/form package is deprecated
22
 */
23
abstract class Field
24
{
25
	/**
26
	 * The description text for the form field.  Usually used in tooltips.
27
	 *
28
	 * @var    string
29
	 * @since  1.0
30
	 */
31
	protected $description;
32
33
	/**
34
	 * The SimpleXMLElement object of the <field /> XML element that describes the form field.
35
	 *
36
	 * @var    SimpleXMLElement
37
	 * @since  1.0
38
	 */
39
	protected $element;
40
41
	/**
42
	 * The Form object of the form attached to the form field.
43
	 *
44
	 * @var    Form
45
	 * @since  1.0
46
	 */
47
	protected $form;
48
49
	/**
50
	 * The form control prefix for field names from the Form object attached to the form field.
51
	 *
52
	 * @var    string
53
	 * @since  1.0
54
	 */
55
	protected $formControl;
56
57
	/**
58
	 * The hidden state for the form field.
59
	 *
60
	 * @var    boolean
61
	 * @since  1.0
62
	 */
63
	protected $hidden = false;
64
65
	/**
66
	 * True to translate the field label string.
67
	 *
68
	 * @var    boolean
69
	 * @since  1.0
70
	 */
71
	protected $translateLabel = true;
72
73
	/**
74
	 * True to translate the field description string.
75
	 *
76
	 * @var    boolean
77
	 * @since  1.0
78
	 */
79
	protected $translateDescription = true;
80
81
	/**
82
	 * The document id for the form field.
83
	 *
84
	 * @var    string
85
	 * @since  1.0
86
	 */
87
	protected $id;
88
89
	/**
90
	 * The input for the form field.
91
	 *
92
	 * @var    string
93
	 * @since  1.0
94
	 */
95
	protected $input;
96
97
	/**
98
	 * The label for the form field.
99
	 *
100
	 * @var    string
101
	 * @since  1.0
102
	 */
103
	protected $label;
104
105
	/**
106
	 * The multiple state for the form field.  If true then multiple values are allowed for the
107
	 * field.  Most often used for list field types.
108
	 *
109
	 * @var    boolean
110
	 * @since  1.0
111
	 */
112
	protected $multiple = false;
113
114
	/**
115
	 * The name of the form field.
116
	 *
117
	 * @var    string
118
	 * @since  1.0
119
	 */
120
	protected $name;
121
122
	/**
123
	 * The name of the field.
124
	 *
125
	 * @var    string
126
	 * @since  1.0
127
	 */
128
	protected $fieldname;
129
130
	/**
131
	 * The group of the field.
132
	 *
133
	 * @var    string
134
	 * @since  1.0
135
	 */
136
	protected $group;
137
138
	/**
139
	 * The required state for the form field.  If true then there must be a value for the field to
140
	 * be considered valid.
141
	 *
142
	 * @var    boolean
143
	 * @since  1.0
144
	 */
145
	protected $required = false;
146
147
	/**
148
	 * The disabled state for the form field.  If true then there must not be a possibility
149
	 * to change the pre-selected value, and the value must not be submitted by the browser.
150
	 *
151
	 * @var    boolean
152
	 * @since  1.0
153
	 */
154
	protected $disabled = false;
155
156
	/**
157
	 * The readonly state for the form field.  If true then there must not be a possibility
158
	 * to change the pre-selected value, and the value must submitted by the browser.
159
	 *
160
	 * @var    boolean
161
	 * @since  1.0
162
	 */
163
	protected $readonly = false;
164
165
	/**
166
	 * The form field type.
167
	 *
168
	 * @var    string
169
	 * @since  1.0
170
	 */
171
	protected $type;
172
173
	/**
174
	 * The validation method for the form field.  This value will determine which method is used
175
	 * to validate the value for a field.
176
	 *
177
	 * @var    string
178
	 * @since  1.0
179
	 */
180
	protected $validate;
181
182
	/**
183
	 * The value of the form field.
184
	 *
185
	 * @var    mixed
186
	 * @since  1.0
187
	 */
188
	protected $value;
189
190
	/**
191
	 * The label's CSS class of the form field
192
	 *
193
	 * @var    mixed
194
	 * @since  1.0
195
	 */
196
	protected $labelClass;
197
198
	/**
199
	 * The count value for generated name field
200
	 *
201
	 * @var    integer
202
	 * @since  1.0
203
	 */
204
	protected static $count = 0;
205
206
	/**
207
	 * The string used for generated fields names
208
	 *
209
	 * @var    string
210
	 * @since  1.0
211
	 */
212
	protected static $generated_fieldname = '__field';
213
214
	/**
215
	 * Method to instantiate the form field object.
216
	 *
217
	 * @param   Form  $form  The form to attach to the form field object.
218
	 *
219
	 * @since   1.0
220
	 */
221
	public function __construct(Form $form = null)
222
	{
223
		// If there is a form passed into the constructor set the form and form control properties.
224
		if ($form instanceof Form)
225
		{
226
			$this->form = $form;
227
			$this->formControl = $form->getFormControl();
228
		}
229
230
		// Detect the field type if not set
231
		if (!isset($this->type))
232
		{
233
			$parts = Normalise::fromCamelCase(get_called_class(), true);
234
235
			if ($parts[0] == 'J')
236
			{
237
				$this->type = StringHelper::ucfirst($parts[count($parts) - 1], '_');
0 ignored issues
show
Documentation Bug introduced by
It seems like \Joomla\String\StringHel...ount($parts) - 1], '_') can also be of type false. However, the property $type is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
238
			}
239
			else
240
			{
241
				$this->type = StringHelper::ucfirst($parts[0], '_') . StringHelper::ucfirst($parts[count($parts) - 1], '_');
242
			}
243
		}
244
	}
245
246
	/**
247
	 * Method to get certain otherwise inaccessible properties from the form field object.
248
	 *
249
	 * @param   string  $name  The property name for which to the the value.
250
	 *
251
	 * @return  mixed  The property value or null.
252
	 *
253
	 * @since   1.0
254
	 */
255
	public function __get($name)
256
	{
257
		switch ($name)
258
		{
259
			case 'description':
260
			case 'formControl':
261
			case 'hidden':
262
			case 'id':
263
			case 'multiple':
264
			case 'name':
265
			case 'required':
266
			case 'disabled':
267
			case 'readonly':
268
			case 'type':
269
			case 'validate':
270
			case 'value':
271
			case 'labelClass':
272
			case 'fieldname':
273
			case 'group':
274
				return $this->$name;
275
276
			case 'input':
277
				// If the input hasn't yet been generated, generate it.
278
				if (empty($this->input))
279
				{
280
					$this->input = $this->getInput();
281
				}
282
283
				return $this->input;
284
285
			case 'label':
286
				// If the label hasn't yet been generated, generate it.
287
				if (empty($this->label))
288
				{
289
					$this->label = $this->getLabel();
290
				}
291
292
				return $this->label;
293
294
			case 'title':
295
				return $this->getTitle();
296
		}
297
298
		return null;
299
	}
300
301
	/**
302
	 * Method to attach a Form object to the field.
303
	 *
304
	 * @param   Form  $form  The Form object to attach to the form field.
305
	 *
306
	 * @return  Field  The form field object so that the method can be used in a chain.
307
	 *
308
	 * @since   1.0
309
	 */
310
	public function setForm(Form $form)
311
	{
312
		$this->form = $form;
313
		$this->formControl = $form->getFormControl();
314
315
		return $this;
316
	}
317
318
	/**
319
	 * Method to attach a Form object to the field.
320
	 *
321
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the <field /> tag for the form field object.
322
	 * @param   mixed             $value    The form field value to validate.
323
	 * @param   string            $group    The field name group control value. This acts as as an array container for the field.
324
	 *                                      For example if the field has name="foo" and the group value is set to "bar" then the
325
	 *                                      full field name would end up being "bar[foo]".
326
	 *
327
	 * @return  boolean  True on success.
328
	 *
329
	 * @since   1.0
330
	 */
331
	public function setup(SimpleXMLElement $element, $value, $group = null)
332
	{
333
		// Make sure there is a valid FormField XML element.
334
		if ((string) $element->getName() != 'field')
335
		{
336
			return false;
337
		}
338
339
		// Reset the input and label values.
340
		$this->input = null;
341
		$this->label = null;
342
343
		// Set the XML element object.
344
		$this->element = $element;
345
346
		// Get some important attributes from the form field element.
347
		$class = (string) $element['class'];
348
		$id = (string) $element['id'];
349
		$multiple = (string) $element['multiple'];
350
		$name = (string) $element['name'];
351
		$required = (string) $element['required'];
352
		$disabled = (string) $element['disabled'];
353
		$readonly = (string) $element['readonly'];
354
355
		// Set the required, disabled and validation options.
356
		$this->required = ($required == 'true' || $required == 'required' || $required == '1');
357
		$this->disabled = ($disabled == 'true' || $disabled == 'disabled' || $disabled == '1');
358
		$this->readonly = ($readonly == 'true' || $readonly == 'readonly' || $readonly == '1');
359
		$this->validate = (string) $element['validate'];
360
361
		// Add the required class if the field is required.
362
		if ($this->required)
363
		{
364
			if ($class)
365
			{
366
				if (strpos($class, 'required') === false)
367
				{
368
					$this->element['class'] = $class . ' required';
369
				}
370
			}
371
			else
372
			{
373
				$this->element->addAttribute('class', 'required');
374
			}
375
		}
376
377
		// Set the multiple values option.
378
		$this->multiple = ($multiple == 'true' || $multiple == 'multiple');
379
380
		// Allow for field classes to force the multiple values option.
381
		if (isset($this->forceMultiple))
382
		{
383
			$this->multiple = (bool) $this->forceMultiple;
0 ignored issues
show
Bug introduced by
The property forceMultiple does not seem to exist. Did you mean multiple?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
384
		}
385
386
		// Set the field description text.
387
		$this->description = (string) $element['description'];
388
389
		// Set the visibility.
390
		$this->hidden = ((string) $element['type'] == 'hidden' || (string) $element['hidden'] == 'true');
391
392
		// Determine whether to translate the field label and/or description.
393
		$this->translateLabel = !((string) $this->element['translate_label'] == 'false' || (string) $this->element['translate_label'] == '0');
394
		$this->translateDescription = !((string) $this->element['translate_description'] == 'false'
395
			|| (string) $this->element['translate_description'] == '0');
396
397
		// Set the group of the field.
398
		$this->group = $group;
399
400
		// Set the field name and id.
401
		$this->fieldname = $this->getFieldName($name);
402
		$this->name = $this->getName($this->fieldname);
403
		$this->id = $this->getId($id, $this->fieldname);
404
405
		// Set the field default value.
406
		$this->value = $value;
407
408
		// Set the CSS class of field label
409
		$this->labelClass = (string) $element['labelclass'];
410
411
		return true;
412
	}
413
414
	/**
415
	 * Method to get the id used for the field input tag.
416
	 *
417
	 * @param   string  $fieldId    The field element id.
418
	 * @param   string  $fieldName  The field element name.
419
	 *
420
	 * @return  string  The id to be used for the field input tag.
421
	 *
422
	 * @since   1.0
423
	 */
424
	protected function getId($fieldId, $fieldName)
425
	{
426
		$id = '';
427
428
		// If there is a form control set for the attached form add it first.
429
		if ($this->formControl)
430
		{
431
			$id .= $this->formControl;
432
		}
433
434
		// If the field is in a group add the group control to the field id.
435
		if ($this->group)
436
		{
437
			// If we already have an id segment add the group control as another level.
438
			if ($id)
439
			{
440
				$id .= '_' . str_replace('.', '_', $this->group);
441
			}
442
			else
443
			{
444
				$id .= str_replace('.', '_', $this->group);
445
			}
446
		}
447
448
		// If we already have an id segment add the field id/name as another level.
449
		if ($id)
450
		{
451
			$id .= '_' . ($fieldId ? $fieldId : $fieldName);
452
		}
453
		else
454
		{
455
			$id .= ($fieldId ? $fieldId : $fieldName);
456
		}
457
458
		// Clean up any invalid characters.
459
		$id = preg_replace('#\W#', '_', $id);
460
461
		return $id;
462
	}
463
464
	/**
465
	 * Method to get the field input markup.
466
	 *
467
	 * @return  string  The field input markup.
468
	 *
469
	 * @since   1.0
470
	 */
471
	abstract protected function getInput();
472
473
	/**
474
	 * Method to get the field title.
475
	 *
476
	 * @return  string  The field title.
477
	 *
478
	 * @since   1.0
479
	 */
480
	protected function getTitle()
481
	{
482
		$title = '';
483
484
		if ($this->hidden)
485
		{
486
			return $title;
487
		}
488
489
		// Get the label text from the XML element, defaulting to the element name.
490
		$title = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
491
		$title = $this->translateLabel ? Text::_($title) : $title;
0 ignored issues
show
Deprecated Code introduced by
The method Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
492
493
		return $title;
494
	}
495
496
	/**
497
	 * Method to get the field label markup.
498
	 *
499
	 * @return  string  The field label markup.
500
	 *
501
	 * @since   1.0
502
	 */
503
	protected function getLabel()
504
	{
505
		$label = '';
506
507
		if ($this->hidden)
508
		{
509
			return $label;
510
		}
511
512
		// Get the label text from the XML element, defaulting to the element name.
513
		$text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
514
		$text = $this->translateLabel ? Text::_($text) : $text;
0 ignored issues
show
Deprecated Code introduced by
The method Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
515
516
		// Build the class for the label.
517
		$class = !empty($this->description) ? 'hasTip' : '';
518
		$class = $this->required == true ? $class . ' required' : $class;
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
519
		$class = !empty($this->labelClass) ? $class . ' ' . $this->labelClass : $class;
520
521
		// Add the opening label tag and main attributes attributes.
522
		$label .= '<label id="' . $this->id . '-lbl" for="' . $this->id . '" class="' . $class . '"';
523
524
		// If a description is specified, use it to build a tooltip.
525 View Code Duplication
		if (!empty($this->description))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
526
		{
527
			$label .= ' title="'
528
				. htmlspecialchars(
529
				trim($text, ':') . '::' . ($this->translateDescription ? Text::_($this->description) : $this->description),
0 ignored issues
show
Deprecated Code introduced by
The method Joomla\Language\Text::_() has been deprecated with message: 2.0 Will be replaced with a `translate` method.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
530
				ENT_COMPAT, 'UTF-8'
531
			) . '"';
532
		}
533
534
		// Add the label text and closing tag.
535
		if ($this->required)
536
		{
537
			$label .= '>' . $text . '<span class="star">&#160;*</span></label>';
538
		}
539
		else
540
		{
541
			$label .= '>' . $text . '</label>';
542
		}
543
544
		return $label;
545
	}
546
547
	/**
548
	 * Method to get the name used for the field input tag.
549
	 *
550
	 * @param   string  $fieldName  The field element name.
551
	 *
552
	 * @return  string  The name to be used for the field input tag.
553
	 *
554
	 * @since   1.0
555
	 */
556
	protected function getName($fieldName)
557
	{
558
		$name = '';
559
560
		// If there is a form control set for the attached form add it first.
561
		if ($this->formControl)
562
		{
563
			$name .= $this->formControl;
564
		}
565
566
		// If the field is in a group add the group control to the field name.
567
		if ($this->group)
568
		{
569
			// If we already have a name segment add the group control as another level.
570
			$groups = explode('.', $this->group);
571
572
			if ($name)
573
			{
574
				foreach ($groups as $group)
575
				{
576
					$name .= '[' . $group . ']';
577
				}
578
			}
579
			else
580
			{
581
				$name .= array_shift($groups);
582
583
				foreach ($groups as $group)
584
				{
585
					$name .= '[' . $group . ']';
586
				}
587
			}
588
		}
589
590
		// If we already have a name segment add the field name as another level.
591
		if ($name)
592
		{
593
			$name .= '[' . $fieldName . ']';
594
		}
595
		else
596
		{
597
			$name .= $fieldName;
598
		}
599
600
		// If the field should support multiple values add the final array segment.
601
		if ($this->multiple)
602
		{
603
			$name .= '[]';
604
		}
605
606
		return $name;
607
	}
608
609
	/**
610
	 * Method to get the field name used.
611
	 *
612
	 * @param   string  $fieldName  The field element name.
613
	 *
614
	 * @return  string  The field name
615
	 *
616
	 * @since   1.0
617
	 */
618
	protected function getFieldName($fieldName)
619
	{
620
		if ($fieldName)
621
		{
622
			return $fieldName;
623
		}
624
		else
625
		{
626
			self::$count = self::$count + 1;
627
628
			return self::$generated_fieldname . self::$count;
629
		}
630
	}
631
}
632