Driver_Simple_Forms   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 32
lcom 1
cbo 0
dl 0
loc 215
ccs 79
cts 79
cp 1
rs 9.84
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A set_value_input() 0 4 1
A set_value_textarea() 0 4 1
B get_value() 0 22 7
B set_value() 0 29 7
A set_value_checkbox() 0 11 2
A set_value_radio() 0 12 3
A set_value_option() 0 21 4
A serialize_files() 0 13 2
A serialize_form() 0 31 4
1
<?php
2
3
namespace Openbuildings\Spiderling;
4
5
/**
6
 * Helper to handle form serialization, modification and posting
7
 *
8
 * @package    Openbuildings\Spiderling
9
 * @author     Ivan Kerin
10
 * @copyright  (c) 2013 OpenBuildings Ltd.
11
 * @license    http://spdx.org/licenses/BSD-3-Clause
12
 */
13
class Driver_Simple_Forms
14
{
15
	/**
16
	 * DOMXPath object to perform queries with
17
	 * @var DOMXPath
18
	 */
19
	protected $_xpath;
20
21 48
	function __construct($xpath)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
22
	{
23 48
		$this->xpath = $xpath;
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
24 48
	}
25
26
	/**
27
	 * Get the value of a DOMElement with a given xpath
28
	 * @param  string $xpath
29
	 * @return mixed
30
	 */
31 7
	public function get_value($xpath)
32
	{
33 7
		$node = $this->xpath->find($xpath);
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
34
35 7
		switch ($node->tagName)
36
		{
37 7
			case 'textarea':
38 6
				return $node->textContent;
39
			break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
40
41 6
			case 'select':
42 5
				$options = array();
43 5
				foreach ($this->xpath->query(".//option[@selected]", $node) as $option)
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
44
				{
45 5
					$options[] = $option->hasAttribute('value') ? $option->getAttribute('value') : $option->textContent;
46
				}
47 5
				return $node->hasAttribute('multiple') ? $options : (isset($options[0]) ? $options[0] : NULL);
48
			break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
49
			default:
50 6
				return $node->getAttribute('value');
51
		}
52
	}
53
54
	/**
55
	 * Set the value of a DOMElement, identified by an xpath, calls one of the stter methods
56
	 * @param string $xpath
57
	 * @param mixed $value
58
	 */
59 4
	public function set_value($xpath, $value)
60
	{
61 4
		$node = $this->xpath->find($xpath);
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
62
63 4
		$setter = 'set_value_input';
64 4
		$type = $node->getAttribute('type');
65
66 4
		if ($node->tagName == 'input' AND $type == 'checkbox')
67
		{
68 3
			$setter = 'set_value_checkbox';
69
		}
70
71 4
		elseif ($node->tagName == 'input' AND $type == 'radio')
72
		{
73 3
			$setter = 'set_value_radio';
74
		}
75
76 4
		elseif ($node->tagName == 'textarea')
77
		{
78 3
			$setter = 'set_value_textarea';
79
		}
80
81 4
		elseif ($node->tagName == 'option')
82
		{
83 4
			$setter = 'set_value_option';
84
		}
85
86 4
		$this->{$setter}($node, $value);
87 4
	}
88
89
	/**
90
	 * Set the value of a checkbos DOMNode
91
	 * @param DOMNode $checkbox
92
	 * @param boolean   $value
93
	 */
94 3
	public function set_value_checkbox(\DOMNode $checkbox, $value)
95
	{
96 3
		if ($value)
97
		{
98 3
			$checkbox->setAttribute('checked', 'checked');
99
		}
100
		else
101
		{
102 1
			$checkbox->removeAttribute('checked');
103
		}
104 3
	}
105
106
	/**
107
	 * Set the value of a radio DOMNode, uncheck any other radio input in the same group
108
	 * @param DOMNode $radio
109
	 * @param boolean   $value
110
	 */
111 3
	public function set_value_radio(\DOMNode $radio, $value)
112
	{
113 3
		$name = $radio->getAttribute('name');
114 3
		foreach ($this->xpath->query("//input[@type='radio' and @name='$name' and @checked]") as $other_radio)
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
115
		{
116 3
			$other_radio->removeAttribute('checked');
117
		}
118 3
		if ($value)
119
		{
120 2
			$radio->setAttribute('checked', 'checked');
121
		}
122 3
	}
123
124
	/**
125
	 * Set the value of a normal input
126
	 * @param DOMNode $input
127
	 * @param string   $value
128
	 */
129 2
	public function set_value_input(\DOMNode $input, $value)
130
	{
131 2
		$input->setAttribute('value', $value);
132 2
	}
133
134
	/**
135
	 * Set the value of a normal textarea
136
	 * @param DOMNode $textarea
137
	 * @param string   $value
138
	 */
139 3
	public function set_value_textarea(\DOMNode $textarea, $value)
140
	{
141 3
		$textarea->nodeValue = $value;
142 3
	}
143
144
	/**
145
	 * Set the value of an option DOMNode, unselect other options in this select, if it is not multiple
146
	 * @param DOMNode $option
147
	 * @param boolean   $value
148
	 */
149 4
	public function set_value_option(\DOMNode $option, $value)
150
	{
151 4
		if ($value)
152
		{
153 4
			$select = $this->xpath->find("./ancestor::select", $option);
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
154
155 4
			if ( ! $select->hasAttribute('multiple'))
156
			{
157 4
				foreach ($this->xpath->query(".//option[@selected]", $select) as $old_option)
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
158
				{
159 2
					$old_option->removeAttribute('selected');
160
				}
161
			}
162
163 4
			$option->setAttribute('selected', 'selected');
164
		}
165
		else
166
		{
167 3
			$option->removeAttribute('selected');
168
		}
169 4
	}
170
171
	/**
172
	 * Return all the contents of file inputs in a form, identified by an xpath
173
	 * @param  string $xpath
174
	 * @return string
175
	 */
176 2
	public function serialize_files($xpath)
177
	{
178 2
		$form = $this->xpath->find($xpath);
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
179
180 2
		$fields = ".//*[not(@disabled) and (self::input and @type = 'file')]";
181 2
		$data = array();
182 2
		foreach ($this->xpath->query($fields, $form) as $field)
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
183
		{
184 1
			$data[] = $field->getAttribute('name').'='.$field->getAttribute('value');
185
		}
186
187 2
		return join('&', $data);
188
	}
189
190
	/**
191
	 * Return the contents of all the inputs from a form, identified by an xpath.
192
	 * Don't include file inputs or disabled inputs
193
	 * @param  string $xpath
194
	 * @return string
195
	 */
196 3
	public function serialize_form($xpath)
197
	{
198 3
		$form = $this->xpath->find($xpath);
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
199
200 3
		$types['radio']    = "(self::input and @type = 'radio' and @checked)";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$types was never initialized. Although not strictly required by PHP, it is generally a good practice to add $types = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
201 3
		$types['checkbox'] = "(self::input and @type = 'checkbox' and @checked)";
202 3
		$types['others']   = "(self::input and @type != 'radio' and @type != 'checkbox' and @type != 'file' and @type != 'submit')";
203 3
		$types['notype']   = "(self::input and not(@type))";
204 3
		$types['select']   = "(self::select)";
205 3
		$types['textarea'] = "(self::textarea)";
206
207 3
		$fields = ".//*[not(@disabled) and (".join(' or ', $types).")]";
208 3
		$data = array();
209 3
		foreach ($this->xpath->query($fields, $form) as $field)
0 ignored issues
show
Bug introduced by
The property xpath does not seem to exist. Did you mean _xpath?

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...
210
		{
211 3
			$value = $this->get_value($field);
212 3
			if (is_array($value))
213
			{
214 2
				foreach ($value as $name => $value_item)
215
				{
216 2
					$data[] = $field->getAttribute('name')."[$name]".'='.urlencode($value_item);
217
				}
218
			}
219
			else
220
			{
221 3
				$data[] = $field->getAttribute('name').'='.urlencode($value);
222
			}
223
		}
224
225 3
		return join('&', $data);
226
	}
227
}
228