Completed
Push — master ( 01ba7c...6d88ca )
by Damian
21:36 queued 11:17
created

FormFieldSchemaTrait::getSchemaDataDefaults()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 20
rs 9.4285
cc 1
eloc 18
nc 1
nop 0
1
<?php
2
3
namespace SilverStripe\Forms\Schema;
4
5
/**
6
 * Class FormFieldSchemaTrait
7
 * @package SilverStripe\Forms\Schema
8
 *
9
 * Allows {@link FormField} to be represented as structured data,
10
 * including both structure (name, id, attributes, etc.) and state (field value).
11
 * Can be used by {@link FormSchema} to represent a form in JSON,
12
 * to be consumed by a front-end application.
13
 *
14
 * WARNING: Experimental API.
15
 */
16
trait FormFieldSchemaTrait {
17
18
	/**
19
	 * The type of front-end component to render the FormField as.
20
	 *
21
	 * @var string
22
	 */
23
	protected $schemaComponent;
24
25
	/**
26
	 * Structured schema data representing the FormField.
27
	 * Used to render the FormField as a ReactJS Component on the front-end.
28
	 *
29
	 * @var array
30
	 */
31
	protected $schemaData = [];
32
33
	/**
34
	 * Structured schema state representing the FormField's current data and validation.
35
	 * Used to render the FormField as a ReactJS Component on the front-end.
36
	 *
37
	 * @var array
38
	 */
39
	protected $schemaState = [];
40
41
	/**
42
	 * Sets the component type the FormField will be rendered as on the front-end.
43
	 *
44
	 * @param string $componentType
45
	 * @return FormField
46
	 */
47
	public function setSchemaComponent($componentType) {
48
		$this->schemaComponent = $componentType;
49
		return $this;
50
	}
51
52
	/**
53
	 * Gets the type of front-end component the FormField will be rendered as.
54
	 *
55
	 * @return string
56
	 */
57
	public function getSchemaComponent() {
58
		return $this->schemaComponent;
59
	}
60
61
	/**
62
	 * Sets the schema data used for rendering the field on the front-end.
63
	 * Merges the passed array with the current `$schemaData` or {@link getSchemaDataDefaults()}.
64
	 * Any passed keys that are not defined in {@link getSchemaDataDefaults()} are ignored.
65
	 * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`.
66
	 *
67
	 * @param array $schemaData - The data to be merged with $this->schemaData.
68
	 * @return FormField
69
	 *
70
	 * @todo Add deep merging of arrays like `data` and `attributes`.
71
	 */
72
	public function setSchemaData($schemaData = []) {
73
		$current = $this->getSchemaData();
74
75
		$this->schemaData = array_merge($current, array_intersect_key($schemaData, $current));
76
		return $this;
77
	}
78
79
	/**
80
	 * Gets the schema data used to render the FormField on the front-end.
81
	 *
82
	 * @return array
83
	 */
84
	public function getSchemaData() {
85
		return array_merge($this->getSchemaDataDefaults(), $this->schemaData);
86
	}
87
88
	/**
89
	 * Gets the defaults for $schemaData.
90
	 * The keys defined here are immutable, meaning undefined keys passed to {@link setSchemaData()} are ignored.
91
	 * Instead the `data` array should be used to pass around ad hoc data.
92
	 *
93
	 * @return array
94
	 */
95
	public function getSchemaDataDefaults() {
96
		return [
97
			'type' => $this->class,
0 ignored issues
show
Bug introduced by
The property class does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
98
			'component' => $this->getSchemaComponent(),
99
			'id' => $this->ID,
0 ignored issues
show
Bug introduced by
The property ID does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
100
			'holder_id' => null,
101
			'name' => $this->getName(),
0 ignored issues
show
Bug introduced by
It seems like getName() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
102
			'title' => $this->Title(),
0 ignored issues
show
Bug introduced by
It seems like Title() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
103
			'source' => null,
104
			'extraClass' => $this->ExtraClass(),
0 ignored issues
show
Bug introduced by
It seems like ExtraClass() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
105
			'description' => $this->getDescription(),
0 ignored issues
show
Bug introduced by
It seems like getDescription() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
106
			'rightTitle' => $this->RightTitle(),
0 ignored issues
show
Bug introduced by
It seems like RightTitle() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
107
			'leftTitle' => $this->LeftTitle(),
0 ignored issues
show
Bug introduced by
It seems like LeftTitle() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
108
			'readOnly' => $this->isReadOnly(),
0 ignored issues
show
Bug introduced by
It seems like isReadOnly() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
109
			'disabled' => $this->isDisabled(),
0 ignored issues
show
Bug introduced by
It seems like isDisabled() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
110
			'customValidationMessage' => $this->getCustomValidationMessage(),
0 ignored issues
show
Bug introduced by
It seems like getCustomValidationMessage() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
111
			'attributes' => [],
112
			'data' => [],
113
		];
114
	}
115
116
	/**
117
	 * Sets the schema data used for rendering the field on the front-end.
118
	 * Merges the passed array with the current `$schemaData` or {@link getSchemaDataDefaults()}.
119
	 * Any passed keys that are not defined in {@link getSchemaDataDefaults()} are ignored.
120
	 * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`.
121
	 *
122
	 * @param array $schemaData - The data to be merged with $this->schemaData.
0 ignored issues
show
Bug introduced by
There is no parameter named $schemaData. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
123
	 * @return FormField
124
	 *
125
	 * @todo Add deep merging of arrays like `data` and `attributes`.
126
	 */
127
	public function setSchemaState($schemaState = []) {
128
		$current = $this->getSchemaState();
129
130
		$this->schemaState = array_merge($current, array_intersect_key($schemaState, $current));
131
		return $this;
132
	}
133
134
	/**
135
	 * Gets the schema state used to render the FormField on the front-end.
136
	 *
137
	 * @return array
138
	 */
139
	public function getSchemaState() {
140
		return array_merge($this->getSchemaStateDefaults(), $this->schemaState);
141
	}
142
143
	/**
144
	 * Gets the defaults for $schemaState.
145
	 * The keys defined here are immutable, meaning undefined keys passed to {@link setSchemaState()} are ignored.
146
	 * Instead the `data` array should be used to pass around ad hoc data.
147
	 * Includes validation data if the field is associated to a {@link Form},
148
	 * and {@link Form->validate()} has been called.
149
	 *
150
	 * @return array
151
	 */
152
	public function getSchemaStateDefaults() {
153
		$field = $this;
154
		$form = $this->getForm();
0 ignored issues
show
Bug introduced by
It seems like getForm() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
155
		$validator = $form ? $form->getValidator() : null;
156
		$errors = $validator ? (array)$validator->getErrors() : [];
157
		$messages = array_filter(array_map(function($error) use ($field) {
158
			if($error['fieldName'] === $field->getName()) {
0 ignored issues
show
Bug introduced by
It seems like getName() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
159
				return [
160
					'value' => $error['message'],
161
					'type' => $error['messageType']
162
				];
163
			}
164
		}, $errors));
165
166
		return [
167
			'id' => $this->ID(),
0 ignored issues
show
Bug introduced by
It seems like ID() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
168
			'value' => $this->Value(),
0 ignored issues
show
Bug introduced by
It seems like Value() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
169
			'valid' => (count($messages) === 0),
170
			'messages' => (array)$messages,
171
			'data' => [],
172
		];
173
	}
174
}
175