1: <?php
2: /**
3: * PHP version 5
4: * @package generalDriver
5: * @author Christian Schiffler <c.schiffler@cyberspectrum.de>
6: * @author Stefan Heimes <stefan_heimes@hotmail.com>
7: * @author Tristan Lins <tristan.lins@bit3.de>
8: * @copyright The MetaModels team.
9: * @license LGPL.
10: * @filesource
11: */
12:
13: namespace DcGeneral\Data;
14:
15: use DcGeneral\Exception\DcGeneralInvalidArgumentException;
16:
17: /**
18: * A generic bag containing properties and their values.
19: */
20: class PropertyValueBag implements PropertyValueBagInterface
21: {
22: /**
23: * All properties and its values in this bag.
24: *
25: * @var array
26: */
27: protected $properties = array();
28:
29: /**
30: * All properties that are marked as invalid and their error messages.
31: *
32: * @var array
33: */
34: protected $errors = array();
35:
36: /**
37: * Create a new instance of a property bag.
38: *
39: * @param array|null $properties The initial property values to use.
40: *
41: * @throws DcGeneralInvalidArgumentException If the passed properties aren't null or an array.
42: */
43: public function __construct($properties = null)
44: {
45: if (is_array($properties) || $properties instanceof \Traversable)
46: {
47: foreach ($properties as $property => $value)
48: {
49: $this->setPropertyValue($property, $value);
50: }
51: }
52: elseif ($properties !== null)
53: {
54: throw new DcGeneralInvalidArgumentException('The parameter $properties does not contain any properties nor values');
55: }
56: }
57:
58: /**
59: * Check if a property exists, otherwise through an exception.
60: *
61: * @param string $property The name of the property to require.
62: *
63: * @return void
64: *
65: * @throws DcGeneralInvalidArgumentException If the property is not registered.
66: *
67: * @internal
68: */
69: protected function requirePropertyValue($property)
70: {
71: if (!$this->hasPropertyValue($property))
72: {
73: throw new DcGeneralInvalidArgumentException('The property ' . $property . ' does not exists');
74: }
75: }
76:
77: /**
78: * {@inheritdoc}
79: */
80: public function hasPropertyValue($property)
81: {
82: return array_key_exists($property, $this->properties);
83: }
84:
85: /**
86: * {@inheritdoc}
87: */
88: public function getPropertyValue($property)
89: {
90: $this->requirePropertyValue($property);
91: return $this->properties[$property];
92: }
93:
94: /**
95: * {@inheritdoc}
96: */
97: public function setPropertyValue($property, $value)
98: {
99: $this->properties[$property] = $value;
100:
101: $this->resetPropertyValueErrors($property);
102:
103: return $this;
104: }
105:
106: /**
107: * {@inheritdoc}
108: */
109: public function removePropertyValue($property)
110: {
111: $this->requirePropertyValue($property);
112: unset($this->properties[$property]);
113:
114: return $this;
115: }
116:
117: /**
118: * {@inheritdoc}
119: */
120: public function hasInvalidPropertyValues()
121: {
122: return (bool)$this->errors;
123: }
124:
125: /**
126: * {@inheritdoc}
127: */
128: public function hasNoInvalidPropertyValues()
129: {
130: return !$this->errors;
131: }
132:
133: /**
134: * {@inheritdoc}
135: */
136: public function isPropertyValueInvalid($property)
137: {
138: $this->requirePropertyValue($property);
139: return (bool)$this->errors[$property];
140: }
141:
142: /**
143: * {@inheritdoc}
144: */
145: public function isPropertyValueValid($property)
146: {
147: $this->requirePropertyValue($property);
148: return !$this->errors[$property];
149: }
150:
151: /**
152: * {@inheritdoc}
153: */
154: public function markPropertyValueAsInvalid($property, $error, $append = true)
155: {
156: $this->requirePropertyValue($property);
157:
158: if (!isset($this->errors[$property]) || !$append)
159: {
160: $this->errors[$property] = array();
161: }
162:
163: foreach ((array)$error as $singleError)
164: {
165: $this->errors[$property][] = $singleError;
166: }
167:
168: return $this;
169: }
170:
171: /**
172: * {@inheritdoc}
173: */
174: public function resetPropertyValueErrors($property)
175: {
176: $this->requirePropertyValue($property);
177: unset($this->errors[$property]);
178:
179: return $this;
180: }
181:
182: /**
183: * {@inheritdoc}
184: */
185: public function getInvalidPropertyNames()
186: {
187: return array_keys($this->errors);
188: }
189:
190: /**
191: * {@inheritdoc}
192: */
193: public function getPropertyValueErrors($property)
194: {
195: $this->requirePropertyValue($property);
196: return (array)$this->errors[$property];
197: }
198:
199: /**
200: * {@inheritdoc}
201: */
202: public function getInvalidPropertyErrors()
203: {
204: return $this->errors;
205: }
206:
207: /**
208: * {@inheritdoc}
209: */
210: public function getIterator()
211: {
212: return new \ArrayIterator($this->properties);
213: }
214:
215: /**
216: * {@inheritdoc}
217: */
218: public function count()
219: {
220: return count($this->properties);
221: }
222:
223: /**
224: * {@inheritdoc}
225: */
226: public function offsetExists($offset)
227: {
228: return $this->hasPropertyValue($offset);
229: }
230:
231: /**
232: * {@inheritdoc}
233: */
234: public function offsetGet($offset)
235: {
236: return $this->getPropertyValue($offset);
237: }
238:
239: /**
240: * {@inheritdoc}
241: */
242: public function offsetSet($offset, $value)
243: {
244: $this->setPropertyValue($offset, $value);
245: }
246:
247: /**
248: * {@inheritdoc}
249: */
250: public function offsetUnset($offset)
251: {
252: $this->removePropertyValue($offset);
253: }
254:
255: /**
256: * {@inheritdoc}
257: */
258: public function __isset($name)
259: {
260: return $this->hasPropertyValue($name);
261: }
262:
263: /**
264: * {@inheritdoc}
265: */
266: public function __get($name)
267: {
268: return $this->getPropertyValue($name);
269: }
270:
271: /**
272: * {@inheritdoc}
273: */
274: public function __set($name, $value)
275: {
276: $this->setPropertyValue($name, $value);
277: }
278:
279: /**
280: * {@inheritdoc}
281: */
282: public function __unset($name)
283: {
284: $this->removePropertyValue($name);
285: }
286:
287: /**
288: * Exports the {@link PropertyValueBag} to an array.
289: *
290: * @return array
291: */
292: public function getArrayCopy()
293: {
294: return $this->properties;
295: }
296: }
297: