1 | <?php |
||
60 | class Story_Checkpoint implements IteratorAggregate |
||
61 | { |
||
62 | /** |
||
63 | * the StoryTeller object |
||
64 | * |
||
65 | * @var \DataSift\Storyplayer\PlayerLib\StoryTeller |
||
66 | */ |
||
67 | private $st; |
||
68 | |||
69 | /** |
||
70 | * keep track of whether the checkpoint is readonly (true) or |
||
71 | * read-write(false) |
||
72 | * |
||
73 | * @var boolean |
||
74 | */ |
||
75 | private $readOnly = false; |
||
76 | |||
77 | /** |
||
78 | * the data stored inside the checkpoint |
||
79 | * |
||
80 | * @var array |
||
81 | */ |
||
82 | private $data = array(); |
||
83 | |||
84 | /** |
||
85 | * our constructor |
||
86 | * |
||
87 | * @param StoryTeller $st |
||
88 | * The StoryTeller object (which we will cache) |
||
89 | */ |
||
90 | public function __construct(StoryTeller $st) |
||
91 | { |
||
92 | // remember the StoryTeller object for future use |
||
93 | $this->st = $st; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * is the checkpoint currently readonly? |
||
98 | * |
||
99 | * @return boolean |
||
100 | * TRUE if the checkpoint is currently readonly |
||
101 | * FALSE if you can change the data in the checkpoint |
||
102 | */ |
||
103 | public function getReadOnly() |
||
107 | |||
108 | /** |
||
109 | * put the checkpoint into readonly mode |
||
110 | */ |
||
111 | public function setReadOnly() |
||
115 | |||
116 | /** |
||
117 | * put the checkpoint into read-write mode |
||
118 | */ |
||
119 | public function setReadWrite() |
||
123 | |||
124 | /** |
||
125 | * magic method to retrieve data from the checkpoint |
||
126 | * |
||
127 | * throws the E5xx_NoSuchDataInCheckpoint exception if you attempt |
||
128 | * to get data that does not exist |
||
129 | * |
||
130 | * @param string $key |
||
131 | * the name of the data to store |
||
132 | * @return mixed |
||
133 | * the data stored in the checkpoint |
||
134 | */ |
||
135 | public function &__get($key) |
||
136 | { |
||
137 | // what are we doing? |
||
138 | $log = Log::usingLog()->startAction("retrieve '{$key}' from the checkpoint"); |
||
139 | |||
140 | // do we have the data to return? |
||
141 | if (!isset($this->data[$key])) { |
||
142 | // no, we do not |
||
143 | $log->endAction("'{$key}' is not in the checkpoint"); |
||
144 | throw new E5xx_NoSuchDataInCheckpoint($key); |
||
145 | } |
||
146 | |||
147 | // yes, we do |
||
148 | $log->endAction($this->data[$key]); |
||
149 | |||
150 | // all done |
||
151 | return $this->data[$key]; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * magic method to tell if the data is stored in the checkpoint or not |
||
156 | * |
||
157 | * @param string $key |
||
158 | * the name of the data to test for |
||
159 | * @return boolean |
||
160 | * TRUE if the data exists in the checkpoint |
||
161 | * FALSE if the data does not exist in the checkpoint |
||
162 | */ |
||
163 | public function __isset($key) |
||
167 | |||
168 | /** |
||
169 | * magic method to store data in the checkpoint |
||
170 | * |
||
171 | * throws the E5xx_CheckpointIsReadOnly exception if you attempt |
||
172 | * to store data when the checkpoint is in readonly mode |
||
173 | * |
||
174 | * @param string $key |
||
175 | * the name of the data to store |
||
176 | * @param mixed $value |
||
177 | * the value to store in the checkpoint |
||
178 | * @return void |
||
179 | */ |
||
180 | public function __set($key, $value) |
||
181 | { |
||
182 | // what are we doing? |
||
183 | $log = Log::usingLog()->startAction("store '{$key}' in the checkpoint"); |
||
184 | |||
185 | // are we allowed to change the data at this time? |
||
186 | if ($this->readOnly) |
||
187 | { |
||
188 | // no, we are not |
||
189 | $log->endAction("checkpoint is readonly; did not store '{$key}'"); |
||
190 | throw new E5xx_CheckpointIsReadOnly(); |
||
191 | } |
||
192 | |||
193 | // if we get here, we're allowed to change the checkpoint |
||
194 | $this->data[$key] = $value; |
||
195 | |||
196 | // all done |
||
197 | $log->endAction($value); |
||
198 | } |
||
199 | |||
200 | // ==================================================================== |
||
201 | // |
||
202 | // Helpers |
||
203 | // |
||
204 | // These are mostly syntactic sugar, but they help a tiny bit with |
||
205 | // code robustness because they can deal correctly with unset properties, |
||
206 | // something many developers forget to check for |
||
207 | // |
||
208 | // Copied from BaseObject (rather than implemented as a trait) as |
||
209 | // we want to support PHP 5.3 for now. We will turn them into traits |
||
210 | // when PHP 5.5 becomes the minimum requirement |
||
211 | // |
||
212 | // -------------------------------------------------------------------- |
||
213 | |||
214 | /** |
||
215 | * Do we have a named property set to non-null? |
||
216 | * |
||
217 | * @param string $propName |
||
218 | * @return boolean |
||
219 | */ |
||
220 | public function has($propName) |
||
224 | |||
225 | /** |
||
226 | * Is the named property set to true? |
||
227 | * |
||
228 | * @param string $propName |
||
229 | * @return boolean |
||
230 | */ |
||
231 | public function is($propName) |
||
235 | |||
236 | /** |
||
237 | * is the named property set to false? |
||
238 | * |
||
239 | * @param string $propName |
||
240 | * @return boolean |
||
241 | */ |
||
242 | public function isNot($propName) |
||
246 | |||
247 | /** |
||
248 | * Do we have a named property, and is it a non-empty array? |
||
249 | * |
||
250 | * @param string $propName |
||
251 | * @return boolean |
||
252 | */ |
||
253 | public function hasList($propName) |
||
259 | |||
260 | /** |
||
261 | * retrieve the named property as an associative array, even if it is |
||
262 | * actually an object |
||
263 | * |
||
264 | * @param string $propName |
||
265 | * @return array |
||
266 | */ |
||
267 | public function getList($propName) |
||
268 | { |
||
269 | // do we have the property at all? |
||
270 | if (!isset($this->$propName)) |
||
271 | { |
||
272 | // no ... send back an empty list |
||
273 | return array(); |
||
274 | } |
||
275 | |||
276 | // is the property already a list? |
||
277 | if (is_array($this->$propName)) |
||
278 | { |
||
279 | // yes ... no conversion needed |
||
280 | return $this->$propName; |
||
281 | } |
||
282 | |||
283 | // is the property something we can convert? |
||
284 | if (is_object($this->$propName)) |
||
285 | { |
||
286 | // yes |
||
287 | $return = array(); |
||
288 | foreach ($this->$propName as $key => $value) |
||
289 | { |
||
290 | $return[$key] = $value; |
||
291 | } |
||
292 | |||
293 | return $return; |
||
294 | } |
||
295 | |||
296 | // if we get here, the property isn't naturally a list |
||
297 | return array(); |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * return the named property as a string, or return the default if |
||
302 | * the property isn't a string |
||
303 | * |
||
304 | * @param string $propName name of property to retrieve |
||
305 | * @param string $default default value to return if property not set |
||
306 | * @return string |
||
307 | */ |
||
308 | public function getString($propName, $default = '') |
||
309 | { |
||
310 | // does this property exist at all? |
||
311 | if (!isset($this->$propName)) |
||
312 | { |
||
313 | // no, so return the default |
||
314 | return $default; |
||
315 | } |
||
316 | |||
317 | // is this property something that can be auto-converted to a |
||
318 | // string reliably? |
||
319 | if (is_string($this->$propName) || is_int($this->$propName) || is_double($this->$propName)) |
||
320 | { |
||
321 | // yes |
||
322 | return (string)$this->$propName; |
||
323 | } |
||
324 | |||
325 | // starting to clutch at straws now |
||
326 | |||
327 | // a boolean, perhaps? |
||
328 | if (is_bool(($this->$propName))) |
||
329 | { |
||
330 | if ($this->$propName) |
||
331 | { |
||
332 | return 'TRUE'; |
||
333 | } |
||
334 | |||
335 | return 'FALSE'; |
||
336 | } |
||
337 | |||
338 | // is it an object that can convert itself to a string? |
||
339 | if (is_object($this->$propName)) |
||
340 | { |
||
341 | $refObj = new ReflectionObject($this->$propName); |
||
342 | if ($refObj->hasMethod('__toString')) |
||
343 | { |
||
344 | return (string)$this->$propName; |
||
345 | } |
||
346 | |||
347 | // sadly, the object cannot convert itself to a string |
||
348 | return $default; |
||
349 | } |
||
350 | |||
351 | // add any other conversions in here |
||
352 | |||
353 | // okay, we give up |
||
354 | return $default; |
||
355 | } |
||
356 | |||
357 | /** |
||
358 | * convert our public properties to an array |
||
359 | * |
||
360 | * @return array |
||
361 | */ |
||
362 | public function getProperties_asList($prefix = null) |
||
|
|||
363 | { |
||
364 | $return = array(); |
||
365 | |||
366 | // get a list of the properties of the $params object |
||
367 | $refObj = new ReflectionObject($this); |
||
368 | $refProps = $refObj->getProperties(ReflectionProperty::IS_PUBLIC); |
||
369 | |||
370 | // convert each property into an array entry |
||
371 | foreach ($refProps as $refProp) |
||
372 | { |
||
373 | $propKey = $refProp->getName(); |
||
374 | $retKey = $propKey; |
||
375 | |||
376 | // do we need to enforce the prefix? |
||
377 | if ($prefix !== null && substr($this->$propKey, 0, strlen($prefix)) !== $prefix) |
||
378 | { |
||
379 | // yes we do |
||
380 | $retKey = $prefix . $propKey; |
||
381 | } |
||
382 | |||
383 | // set the value |
||
384 | $return[$retKey] = $this->$propKey; |
||
385 | } |
||
386 | |||
387 | // return the array that we've built |
||
388 | return $return; |
||
389 | } |
||
390 | |||
391 | /** |
||
392 | * get all the data held inside the checkpoint |
||
393 | * |
||
394 | * @return \stdClass |
||
395 | */ |
||
396 | public function getData() |
||
400 | |||
401 | /** |
||
402 | * support foreach() loops over our data |
||
403 | * |
||
404 | * @return \Traversable |
||
405 | */ |
||
406 | public function getIterator() |
||
410 | } |
||
411 |
This check looks for method names that are not written in camelCase.
In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes
databaseConnectionSeeker
.