1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* This file is part of Yolk - Gamer Network's PHP Framework. |
4
|
|
|
* |
5
|
|
|
* Copyright (c) 2013 Gamer Network Ltd. |
6
|
|
|
* |
7
|
|
|
* Distributed under the MIT License, a copy of which is available in the |
8
|
|
|
* LICENSE file that was bundled with this package, or online at: |
9
|
|
|
* https://github.com/gamernetwork/yolk |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace yolk\support; |
13
|
|
|
|
14
|
|
|
use yolk\contracts\support\Type; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* A set of field definitions and associated validation rules. |
18
|
|
|
*/ |
19
|
|
|
class Fieldset implements \IteratorAggregate, \Countable { |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Array of fields defined in this fieldset. |
23
|
|
|
* @var array |
24
|
|
|
*/ |
25
|
|
|
protected $fields; |
26
|
|
|
|
27
|
|
|
protected $types; |
28
|
|
|
|
29
|
|
|
public function __construct() { |
30
|
|
|
$this->fields = []; |
31
|
|
|
$this->types = []; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Add a new field definition. |
36
|
|
|
* @param string $name name of the field |
37
|
|
|
* @param string $type one of the \yolk\contracts\support\Type constants or a string containing a custom type |
38
|
|
|
* @param array $rules an array of validation rules |
39
|
|
|
* @return self |
40
|
|
|
*/ |
41
|
|
|
public function add( $name, $type = Type::TEXT, $rules = [] ) { |
42
|
|
|
$this->fields[$name] = new Field($name, $type, $rules); |
43
|
|
|
$this->types = []; // clear this so it will be refreshed when we've finished adding fields |
44
|
|
|
return $this; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Validate the data in the specified array. |
49
|
|
|
* @param array $data |
50
|
|
|
* @return array first element is an array of cleaned data, second is an array of the errors (if any) |
51
|
|
|
*/ |
52
|
|
|
public function validate( array $data ) { |
53
|
|
|
|
54
|
|
|
$errors = []; |
55
|
|
|
|
56
|
|
|
foreach( $this->fields as $field ) { |
57
|
|
|
|
58
|
|
|
$f = $field->name; |
59
|
|
|
$v = isset($data[$f]) ? $data[$f] : null; |
60
|
|
|
|
61
|
|
|
list($clean, $errors[$f]) = $field->validate($v); |
62
|
|
|
|
63
|
|
|
if( !$errors[$f] ) |
64
|
|
|
$data[$f] = $clean; |
65
|
|
|
|
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
return [ |
69
|
|
|
$data, |
70
|
|
|
array_filter($errors), |
71
|
|
|
]; |
72
|
|
|
|
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
public function listNames() { |
76
|
|
|
return array_keys($this->fields); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
public function getDefaults() { |
80
|
|
|
$defaults = []; |
81
|
|
|
foreach( $this->fields as $field ) { |
82
|
|
|
$defaults[$field->name] = $field->default; |
83
|
|
|
} |
84
|
|
|
return $defaults; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
public function __get( $key ) { |
88
|
|
|
return isset($this->fields[$key]) ? $this->fields[$key] : null; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
public function __isset( $key ) { |
92
|
|
|
return isset($this->fields[$key]); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
public function getIterator() { |
96
|
|
|
return new \ArrayIterator($this->fields); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
public function count() { |
100
|
|
|
return count($this->fields); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
public function getByType( $type ) { |
104
|
|
|
|
105
|
|
|
$type = strtolower($type); |
106
|
|
|
|
107
|
|
|
if( !$this->types ) { |
|
|
|
|
108
|
|
|
$this->types['unique'] = []; |
109
|
|
|
foreach( $this->fields as $field ) { |
110
|
|
|
|
111
|
|
|
if( !isset($this->types[$field->type]) ) |
112
|
|
|
$this->types[$field->type] = []; |
113
|
|
|
|
114
|
|
|
$this->types[$field->type][] = $field->name; |
115
|
|
|
|
116
|
|
|
if( $field->isUnique() ) |
117
|
|
|
$this->types['unique'][] = $field->name; |
118
|
|
|
|
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
return isset($this->types[$type]) ? $this->types[$type] : []; |
123
|
|
|
|
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
// EOF |
129
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.