Kohana_Jam_Form::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php defined('SYSPATH') OR die('No direct script access.');
2
3
/**
4
 * Handles building and maintaining HTML Forms
5
 *
6
 * @package    Jam
7
 * @category   Form
8
 * @author     Ivan Kerin
9
 * @copyright  (c) 2011-2012 Despark Ltd.
10
 * @license    http://www.opensource.org/licenses/isc-license.txt
11
 */
12
abstract class Kohana_Jam_Form {
13
14
	/**
15
	 * Helper method to build a prefix based
16
	 *
17
	 * @param string $prefix
18
	 * @param string $name
19
	 * @return string
20
	 */
21 1
	public static function generate_prefix($prefix, $name)
22
	{
23 1
		$additional = array_slice(func_get_args(), 2);
24 1
		foreach ($additional as $additional_name)
25
		{
26 1
			if ($additional_name !== NULL)
27 1
				$name .= "[$additional_name]";
28
		}
29
30 1
		if (strpos($prefix,'[') !== FALSE)
31
		{
32
			return str_replace('[%s]','',$prefix).preg_replace('/^([^\[]+)(.*)$/', "[\$1]\$2[%s]", $name);
33
		}
34
		else
35
		{
36 1
			return preg_replace('/^([^\[]+)(.*)$/', "{$name}[\$1]\$2", $prefix);
37
		}
38
	}
39
40
	/**
41
	 * Convert Jam_Builder or Jam_Collection to an array of id => name
42
	 *
43
	 * @param mixed $choices
44
	 * @return  array
45
	 */
46 2
	public static function list_choices($choices)
47
	{
48 2
		if ($choices instanceof Jam_Query_Builder_Select OR $choices instanceof Jam_Array_Model)
49
		{
50 2
			$choices = $choices->as_array(':primary_key', ':name_key');
0 ignored issues
show
Bug introduced by
The method as_array does only exist in Jam_Array_Model, but not in Jam_Query_Builder_Select.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
51
		}
52
53 2
		return $choices;
54
	}
55
56
	/**
57
	 * Get the id or list of ids of an object (Jam_Model / Jam_Colleciton respectively)
58
	 *
59
	 * @param int|array $id
60
	 * @param bool $force_single if a value is an array get the first value
61
	 */
62 5
	public static function list_id($id, $force_single = FALSE)
63
	{
64 5
		if ($id instanceof Jam_Model)
65
		{
66 2
			$id = $id->id();
67
		}
68 5
		elseif ($id instanceof Jam_Query_Builder_Select OR $id instanceof Jam_Array_Model)
69
		{
70 1
			$id = $id->ids();
71
		}
72
73 5
		if ($force_single AND is_array($id))
74
		{
75 1
			$id = reset($id);
76
		}
77
78 5
		return $id;
79
	}
80
81
	/**
82
	 * Add a class to the 'class' attribute, without removing existing value
83
	 *
84
	 * @param array  $attributes
85
	 * @param string $class
86
	 */
87
	public static function add_class(array $attributes, $class)
88
	{
89
		$attributes['class'] = (isset($attributes['class']) ? $attributes['class'].' ' : '').$class;
90
		return $attributes;
91
	}
92
93 1
	public static function common_params($collection, array $params = array())
94
	{
95 1
		$collection = ($collection instanceof Jam_Query_Builder_Collection OR $collection instanceof Jam_Array_Model) ? $collection->as_array() : $collection;
96
97 1
		$common = array();
98 1
		foreach ($params as $name => $param)
99
		{
100 1
			$attribute_name = is_numeric($name) ? $param : $name;
101
			$param_collection = array_map(function($item) use ($attribute_name) { return $item->$attribute_name; }, $collection);
102
103 1
			if (is_numeric($name))
104
			{
105 1
				$common[$param] = array_reduce($param_collection, function($result, $item){
106 1
					return Jam_Form::list_id($result) !== Jam_Form::list_id($item) ? NULL : $item;
107 1
				}, reset($param_collection));
108
			}
109
			else
110
			{
111 1
				$common[$name] = Jam_Form::common_params($param_collection, $param);
112
			}
113
		}
114
115 1
		return $common;
116
	}
117
118
	/**
119
	 * The "prefix" of the form - this is used to implement nesting with html forms
120
	 *
121
	 * @var string
122
	 */
123
	protected $_prefix = '%s';
124
125
	/**
126
	 * The current object the form is bound to
127
	 *
128
	 * @var Jam_Model
129
	 */
130
	protected $_object;
131
132
	/**
133
	 * This flag determines if we want to have html5 validation of the form
134
	 * @var boolean
135
	 */
136
	protected $_validation = TRUE;
137
138
	/**
139
	 * The meta of the Jam_Object the form is bound to
140
	 *
141
	 * @var Jam_Meta
142
	 */
143
	protected $_meta;
144
145 14
	function __construct(Jam_Validated $model)
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...
146
	{
147 14
		$this->_object = $model;
0 ignored issues
show
Documentation Bug introduced by
$model is of type object<Jam_Validated>, but the property $_object was declared to be of type object<Jam_Model>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof 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 given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
148 14
		$this->_meta = Jam::meta($model);
149 14
	}
150
151
	/**
152
	 * Getter / setter of validation flag
153
	 * @param boolean $validation
154
	 */
155 11
	public function validation($validation = NULL)
156
	{
157 11
		if ($validation !== NULL)
158
		{
159
			$this->_validation = (bool) $validation;
160
			return $this;
161
		}
162 11
		return $this->_validation;
163
	}
164
165
	/**
166
	 * Getter / setter of the prefix
167
	 *
168
	 * @param string $prefix
169
	 */
170 11
	public function prefix($prefix = NULL)
171
	{
172 11
		if ($prefix !== NULL)
173
		{
174 1
			$this->_prefix = $prefix;
175 1
			return $this;
176
		}
177
178 11
		return $this->_prefix;
179
	}
180
181
	/**
182
	 * @return Jam_Validated this form is bound to
183
	 */
184 11
	public function object()
185
	{
186 11
		return $this->_object;
187
	}
188
189
	/**
190
	 * @return Jam_Meta of the model this form is bound to
191
	 */
192 2
	public function meta()
193
	{
194 2
		return $this->_meta;
195
	}
196
197
	/**
198
	 * Create a nested form for a child association of the model, assigning the correct prefix
199
	 *
200
	 * @param string $name  of the association
201
	 * @param int $index an index id of a collection (if the association if a colleciton)
202
	 * @return static
203
	 */
204 1
	public function fields_for($name, $index = NULL)
205
	{
206 1
		$object = $this->object()->$name;
207
208 1
		if ($index !== NULL)
209
		{
210 1
			if (is_numeric($index) AND $object[$index])
211
			{
212 1
				$object = $object[$index];
213
			}
214
			else
215
			{
216 1
				$object = $object->build();
217
			}
218
		}
219 1
		elseif ( ! $object)
220
		{
221 1
			$object = $this->object()->build($name);
222
		}
223
224
225 1
		$new_prefix = Jam_Form::generate_prefix($this->prefix(), $name, $index);
226
227 1
		return Jam::form($object, get_class($this))->prefix($new_prefix);
228
	}
229
230
	/**
231
	 * Get the default name for a field of this form
232
	 *
233
	 * @param string $name
234
	 * @return string
235
	 */
236 11
	public function default_name($name)
237
	{
238 11
		return sprintf($this->prefix(), $name);
239
	}
240
241
	/**
242
	 * Get the default html attribute id for a field of this form
243
	 *
244
	 * @param string $name
245
	 * @return string
246
	 */
247 11
	public function default_id($name)
248
	{
249 11
		return str_replace(array(']', '['), array('', '_'), $this->default_name($name));
250
	}
251
252
	/**
253
	 * Get the default attributes (name and id) for a field of this form
254
	 *
255
	 * @param string $name
256
	 * @param array  $overrides
257
	 * @return array
258
	 */
259 11
	public function default_attributes($name, array $overrides = array())
260
	{
261 11
		if ( ! isset($overrides['id']))
262
		{
263 10
			$overrides['id'] = $this->default_id($name);
264
		}
265
266 11
		if ( ! isset($overrides['name']))
267
		{
268 11
			$overrides['name'] = $this->default_name($name);
269
		}
270
271 11
		if ($this->validation())
272
		{
273 11
			foreach ($this->object()->meta()->validators() as $validator)
274
			{
275 11
				$overrides = Arr::merge($validator->html5_validation($this->object(), $name), $overrides);
276
			}
277
		}
278
279 11
		return $overrides;
280
	}
281
}
282