root/trunk/framework/TComponent.php
| Revision 2482, 25.4 kB (checked in by knut, 4 months ago) | |
|---|---|
|
|
| Line | |
|---|---|
| 1 | <?php |
| 2 | /** |
| 3 | * TComponent, TPropertyValue classes |
| 4 | * |
| 5 | * @author Qiang Xue <qiang.xue@gmail.com> |
| 6 | * @link http://www.pradosoft.com/ |
| 7 | * @copyright Copyright © 2005-2008 PradoSoft |
| 8 | * @license http://www.pradosoft.com/license/ |
| 9 | * @version $Id$ |
| 10 | * @package System |
| 11 | */ |
| 12 | |
| 13 | /** |
| 14 | * TComponent class |
| 15 | * |
| 16 | * TComponent is the base class for all PRADO components. |
| 17 | * TComponent implements the protocol of defining, using properties and events. |
| 18 | * |
| 19 | * A property is defined by a getter method, and/or a setter method. |
| 20 | * Properties can be accessed in the way like accessing normal object members. |
| 21 | * Reading or writing a property will cause the invocation of the corresponding |
| 22 | * getter or setter method, e.g., |
| 23 | * <code> |
| 24 | * $a=$this->Text; // equivalent to $a=$this->getText(); |
| 25 | * $this->Text='abc'; // equivalent to $this->setText('abc'); |
| 26 | * </code> |
| 27 | * The signatures of getter and setter methods are as follows, |
| 28 | * <code> |
| 29 | * // getter, defines a readable property 'Text' |
| 30 | * function getText() { ... } |
| 31 | * // setter, defines a writable property 'Text', with $value being the value to be set to the property |
| 32 | * function setText($value) { ... } |
| 33 | * </code> |
| 34 | * Property names are case-insensitive. It is recommended that they are written |
| 35 | * in the format of concatenated words, with the first letter of each word |
| 36 | * capitalized (e.g. DisplayMode, ItemStyle). |
| 37 | * |
| 38 | * An event is defined by the presence of a method whose name starts with 'on'. |
| 39 | * The event name is the method name and is thus case-insensitive. |
| 40 | * An event can be attached with one or several methods (called event handlers). |
| 41 | * An event can be raised by calling {@link raiseEvent} method, upon which |
| 42 | * the attached event handlers will be invoked automatically in the order they |
| 43 | * are attached to the event. Event handlers must have the following signature, |
| 44 | * <code> |
| 45 | * function eventHandlerFuncName($sender,$param) { ... } |
| 46 | * </code> |
| 47 | * where $sender refers to the object who is responsible for the raising of the event, |
| 48 | * and $param refers to a structure that may contain event-specific information. |
| 49 | * To raise an event (assuming named as 'Click') of a component, use |
| 50 | * <code> |
| 51 | * $component->raiseEvent('OnClick'); |
| 52 | * </code> |
| 53 | * To attach an event handler to an event, use one of the following ways, |
| 54 | * <code> |
| 55 | * $component->OnClick=$callback; // or $component->OnClick->add($callback); |
| 56 | * $$component->attachEventHandler('OnClick',$callback); |
| 57 | * </code> |
| 58 | * The first two ways make use of the fact that $component->OnClick refers to |
| 59 | * the event handler list {@link TList} for the 'OnClick' event. |
| 60 | * The variable $callback contains the definition of the event handler that can |
| 61 | * be either a string referring to a global function name, or an array whose |
| 62 | * first element refers to an object and second element a method name/path that |
| 63 | * is reachable by the object, e.g. |
| 64 | * - 'buttonClicked' : buttonClicked($sender,$param); |
| 65 | * - array($object,'buttonClicked') : $object->buttonClicked($sender,$param); |
| 66 | * - array($object,'MainContent.SubmitButton.buttonClicked') : |
| 67 | * $object->MainContent->SubmitButton->buttonClicked($sender,$param); |
| 68 | * |
| 69 | * @author Qiang Xue <qiang.xue@gmail.com> |
| 70 | * @version $Id$ |
| 71 | * @package System |
| 72 | * @since 3.0 |
| 73 | */ |
| 74 | class TComponent |
| 75 | { |
| 76 | /** |
| 77 | * @var array event handler lists |
| 78 | */ |
| 79 | private $_e=array(); |
| 80 | |
| 81 | /** |
| 82 | * Returns a property value or an event handler list by property or event name. |
| 83 | * Do not call this method. This is a PHP magic method that we override |
| 84 | * to allow using the following syntax to read a property: |
| 85 | * <code> |
| 86 | * $value=$component->PropertyName; |
| 87 | * </code> |
| 88 | * and to obtain the event handler list for an event, |
| 89 | * <code> |
| 90 | * $eventHandlerList=$component->EventName; |
| 91 | * </code> |
| 92 | * @param string the property name or the event name |
| 93 | * @return mixed the property value or the event handler list |
| 94 | * @throws TInvalidOperationException if the property/event is not defined. |
| 95 | */ |
| 96 | public function __get($name) |
| 97 | { |
| 98 | $getter='get'.$name; |
| 99 | if(method_exists($this,$getter)) |
| 100 | { |
| 101 | // getting a property |
| 102 | return $this->$getter(); |
| 103 | } |
| 104 | else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) |
| 105 | { |
| 106 | // getting an event (handler list) |
| 107 | $name=strtolower($name); |
| 108 | if(!isset($this->_e[$name])) |
| 109 | $this->_e[$name]=new TList; |
| 110 | return $this->_e[$name]; |
| 111 | } |
| 112 | else |
| 113 | { |
| 114 | throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * Sets value of a component property. |
| 120 | * Do not call this method. This is a PHP magic method that we override |
| 121 | * to allow using the following syntax to set a property or attach an event handler. |
| 122 | * <code> |
| 123 | * $this->PropertyName=$value; |
| 124 | * $this->EventName=$handler; |
| 125 | * </code> |
| 126 | * @param string the property name or event name |
| 127 | * @param mixed the property value or event handler |
| 128 | * @throws TInvalidOperationException If the property is not defined or read-only. |
| 129 | */ |
| 130 | public function __set($name,$value) |
| 131 | { |
| 132 | $setter='set'.$name; |
| 133 | if(method_exists($this,$setter)) |
| 134 | { |
| 135 | $this->$setter($value); |
| 136 | } |
| 137 | else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) |
| 138 | { |
| 139 | $this->attachEventHandler($name,$value); |
| 140 | } |
| 141 | else if(method_exists($this,'get'.$name)) |
| 142 | { |
| 143 | throw new TInvalidOperationException('component_property_readonly',get_class($this),$name); |
| 144 | } |
| 145 | else |
| 146 | { |
| 147 | throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | /** |
| 152 | * Determines whether a property is defined. |
| 153 | * A property is defined if there is a getter or setter method |
| 154 | * defined in the class. Note, property names are case-insensitive. |
| 155 | * @param string the property name |
| 156 | * @return boolean whether the property is defined |
| 157 | */ |
| 158 | public function hasProperty($name) |
| 159 | { |
| 160 | return method_exists($this,'get'.$name) || method_exists($this,'set'.$name); |
| 161 | } |
| 162 | |
| 163 | /** |
| 164 | * Determines whether a property can be read. |
| 165 | * A property can be read if the class has a getter method |
| 166 | * for the property name. Note, property name is case-insensitive. |
| 167 | * @param string the property name |
| 168 | * @return boolean whether the property can be read |
| 169 | */ |
| 170 | public function canGetProperty($name) |
| 171 | { |
| 172 | return method_exists($this,'get'.$name); |
| 173 | } |
| 174 | |
| 175 | /** |
| 176 | * Determines whether a property can be set. |
| 177 | * A property can be written if the class has a setter method |
| 178 | * for the property name. Note, property name is case-insensitive. |
| 179 | * @param string the property name |
| 180 | * @return boolean whether the property can be written |
| 181 | */ |
| 182 | public function canSetProperty($name) |
| 183 | { |
| 184 | return method_exists($this,'set'.$name); |
| 185 | } |
| 186 | |
| 187 | /** |
| 188 | * Evaluates a property path. |
| 189 | * A property path is a sequence of property names concatenated by '.' character. |
| 190 | * For example, 'Parent.Page' refers to the 'Page' property of the component's |
| 191 | * 'Parent' property value (which should be a component also). |
| 192 | * @param string property path |
| 193 | * @return mixed the property path value |
| 194 | */ |
| 195 | public function getSubProperty($path) |
| 196 | { |
| 197 | $object=$this; |
| 198 | foreach(explode('.',$path) as $property) |
| 199 | $object=$object->$property; |
| 200 | return $object; |
| 201 | } |
| 202 | |
| 203 | /** |
| 204 | * Sets a value to a property path. |
| 205 | * A property path is a sequence of property names concatenated by '.' character. |
| 206 | * For example, 'Parent.Page' refers to the 'Page' property of the component's |
| 207 | * 'Parent' property value (which should be a component also). |
| 208 | * @param string property path |
| 209 | * @param mixed the property path value |
| 210 | */ |
| 211 | public function setSubProperty($path,$value) |
| 212 | { |
| 213 | $object=$this; |
| 214 | if(($pos=strrpos($path,'.'))===false) |
| 215 | $property=$path; |
| 216 | else |
| 217 | { |
| 218 | $object=$this->getSubProperty(substr($path,0,$pos)); |
| 219 | $property=substr($path,$pos+1); |
| 220 | } |
| 221 | $object->$property=$value; |
| 222 | } |
| 223 | |
| 224 | /** |
| 225 | * Determines whether an event is defined. |
| 226 | * An event is defined if the class has a method whose name is the event name prefixed with 'on'. |
| 227 | * Note, event name is case-insensitive. |
| 228 | * @param string the event name |
| 229 | * @return boolean |
| 230 | */ |
| 231 | public function hasEvent($name) |
| 232 | { |
| 233 | return strncasecmp($name,'on',2)===0 && method_exists($this,$name); |
| 234 | } |
| 235 | |
| 236 | /** |
| 237 | * @return boolean whether an event has been attached one or several handlers |
| 238 | */ |
| 239 | public function hasEventHandler($name) |
| 240 | { |
| 241 | $name=strtolower($name); |
| 242 | return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0; |
| 243 | } |
| 244 | |
| 245 | /** |
| 246 | * Returns the list of attached event handlers for an event. |
| 247 | * @return TList list of attached event handlers for an event |
| 248 | * @throws TInvalidOperationException if the event is not defined |
| 249 | */ |
| 250 | public function getEventHandlers($name) |
| 251 | { |
| 252 | if(strncasecmp($name,'on',2)===0 && method_exists($this,$name)) |
| 253 | { |
| 254 | $name=strtolower($name); |
| 255 | if(!isset($this->_e[$name])) |
| 256 | $this->_e[$name]=new TList; |
| 257 | return $this->_e[$name]; |
| 258 | } |
| 259 | else |
| 260 | throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); |
| 261 | } |
| 262 | |
| 263 | /** |
| 264 | * Attaches an event handler to an event. |
| 265 | * |
| 266 | * The handler must be a valid PHP callback, i.e., a string referring to |
| 267 | * a global function name, or an array containing two elements with |
| 268 | * the first element being an object and the second element a method name |
| 269 | * of the object. In Prado, you can also use method path to refer to |
| 270 | * an event handler. For example, array($object,'Parent.buttonClicked') |
| 271 | * uses a method path that refers to the method $object->Parent->buttonClicked(...). |
| 272 | * |
| 273 | * The event handler must be of the following signature, |
| 274 | * <code> |
| 275 | * function handlerName($sender,$param) {} |
| 276 | * </code> |
| 277 | * where $sender represents the object that raises the event, |
| 278 | * and $param is the event parameter. |
| 279 | * |
| 280 | * This is a convenient method to add an event handler. |
| 281 | * It is equivalent to {@link getEventHandlers}($name)->add($handler). |
| 282 | * For complete management of event handlers, use {@link getEventHandlers} |
| 283 | * to get the event handler list first, and then do various |
| 284 | * {@link TList} operations to append, insert or remove |
| 285 | * event handlers. You may also do these operations like |
| 286 | * getting and setting properties, e.g., |
| 287 | * <code> |
| 288 | * $component->OnClick[]=array($object,'buttonClicked'); |
| 289 | * $component->OnClick->insertAt(0,array($object,'buttonClicked')); |
| 290 | * </code> |
| 291 | * which are equivalent to the following |
| 292 | * <code> |
| 293 | * $component->getEventHandlers('OnClick')->add(array($object,'buttonClicked')); |
| 294 | * $component->getEventHandlers('OnClick')->insertAt(0,array($object,'buttonClicked')); |
| 295 | * </code> |
| 296 | * |
| 297 | * @param string the event name |
| 298 | * @param callback the event handler |
| 299 | * @throws TInvalidOperationException if the event does not exist |
| 300 | */ |
| 301 | public function attachEventHandler($name,$handler) |
| 302 | { |
| 303 | $this->getEventHandlers($name)->add($handler); |
| 304 | } |
| 305 | |
| 306 | /** |
| 307 | * Detaches an existing event handler. |
| 308 | * This method is the opposite of {@link attachEventHandler}. |
| 309 | * @param string event name |
| 310 | * @param callback the event handler to be removed |
| 311 | * @return boolean if the removal is successful |
| 312 | */ |
| 313 | public function detachEventHandler($name,$handler) |
| 314 | { |
| 315 | if($this->hasEventHandler($name)) |
| 316 | { |
| 317 | try |
| 318 | { |
| 319 | $this->getEventHandlers($name)->remove($handler); |
| 320 | return true; |
| 321 | } |
| 322 | catch(Exception $e) |
| 323 | { |
| 324 | } |
| 325 | } |
| 326 | return false; |
| 327 | } |
| 328 | |
| 329 | /** |
| 330 | * Raises an event. |
| 331 | * This method represents the happening of an event and will |
| 332 | * invoke all attached event handlers for the event. |
| 333 | * @param string the event name |
| 334 | * @param mixed the event sender object |
| 335 | * @param TEventParameter the event parameter |
| 336 | * @throws TInvalidOperationException if the event is undefined |
| 337 | * @throws TInvalidDataValueException If an event handler is invalid |
| 338 | */ |
| 339 | public function raiseEvent($name,$sender,$param) |
| 340 | { |
| 341 | $name=strtolower($name); |
| 342 | if(isset($this->_e[$name])) |
| 343 | { |
| 344 | foreach($this->_e[$name] as $handler) |
| 345 | { |
| 346 | if(is_string($handler)) |
| 347 | { |
| 348 | if(($pos=strrpos($handler,'.'))!==false) |
| 349 | { |
| 350 | $object=$this->getSubProperty(substr($handler,0,$pos)); |
| 351 | $method=substr($handler,$pos+1); |
| 352 | if(method_exists($object,$method)) |
| 353 | $object->$method($sender,$param); |
| 354 | else |
| 355 | throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name,$handler); |
| 356 | } |
| 357 | else |
| 358 | call_user_func($handler,$sender,$param); |
| 359 | } |
| 360 | else if(is_callable($handler,true)) |
| 361 | { |
| 362 | // an array: 0 - object, 1 - method name/path |
| 363 | list($object,$method)=$handler; |
| 364 | if(is_string($object)) // static method call |
| 365 | call_user_func($handler,$sender,$param); |
| 366 | else |
| 367 | { |
| 368 | if(($pos=strrpos($method,'.'))!==false) |
| 369 | { |
| 370 | $object=$this->getSubProperty(substr($method,0,$pos)); |
| 371 | $method=substr($method,$pos+1); |
| 372 | } |
| 373 | if(method_exists($object,$method)) |
| 374 | $object->$method($sender,$param); |
| 375 | else |
| 376 | throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name,$handler[1]); |
| 377 | } |
| 378 | } |
| 379 | else |
| 380 | throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name,gettype($handler)); |
| 381 | } |
| 382 | } |
| 383 | else if(!$this->hasEvent($name)) |
| 384 | throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); |
| 385 | } |
| 386 | |
| 387 | /** |
| 388 | * Evaluates a PHP expression in the context of this control. |
| 389 | * @return mixed the expression result |
| 390 | * @throws TInvalidOperationException if the expression is invalid |
| 391 | */ |
| 392 | public function evaluateExpression($expression) |
| 393 | { |
| 394 | try |
| 395 | { |
| 396 | if(eval("\$result=$expression;")===false) |
| 397 | throw new Exception(''); |
| 398 | return $result; |
| 399 | } |
| 400 | catch(Exception $e) |
| 401 | { |
| 402 | throw new TInvalidOperationException('component_expression_invalid',get_class($this),$expression,$e->getMessage()); |
| 403 | } |
| 404 | } |
| 405 | |
| 406 | /** |
| 407 | * Evaluates a list of PHP statements. |
| 408 | * @param string PHP statements |
| 409 | * @return string content echoed or printed by the PHP statements |
| 410 | * @throws TInvalidOperationException if the statements are invalid |
| 411 | */ |
| 412 | public function evaluateStatements($statements) |
| 413 | { |
| 414 | try |
| 415 | { |
| 416 | ob_start(); |
| 417 | if(eval($statements)===false) |
| 418 | throw new Exception(''); |
| 419 | $content=ob_get_contents(); |
| 420 | ob_end_clean(); |
| 421 | return $content; |
| 422 | } |
| 423 | catch(Exception $e) |
| 424 | { |
| 425 | throw new TInvalidOperationException('component_statements_invalid',get_class($this),$statements,$e->getMessage()); |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | /** |
| 430 | * This method is invoked after the component is instantiated by a template. |
| 431 | * When this method is invoked, the component's properties have been initialized. |
| 432 | * The default implementation of this method will invoke |
| 433 | * the potential parent component's {@link addParsedObject}. |
| 434 | * This method can be overridden. |
| 435 | * @param TComponent potential parent of this control |
| 436 | * @see addParsedObject |
| 437 | */ |
| 438 | public function createdOnTemplate($parent) |
| 439 | { |
| 440 | $parent->addParsedObject($this); |
| 441 | } |
| 442 | |
| 443 | /** |
| 444 | * Processes an object that is created during parsing template. |
| 445 | * The object can be either a component or a static text string. |
| 446 | * This method can be overridden to customize the handling of newly created objects in template. |
| 447 | * Only framework developers and control developers should use this method. |
| 448 | * @param string|TComponent text string or component parsed and instantiated in template |
| 449 | * @see createdOnTemplate |
| 450 | */ |
| 451 | public function addParsedObject($object) |
| 452 | { |
| 453 | } |
| 454 | } |
| 455 | |
| 456 | /** |
| 457 | * TEnumerable class. |
| 458 | * TEnumerable is the base class for all enumerable types. |
| 459 | * To define an enumerable type, extend TEnumberable and define string constants. |
| 460 | * Each constant represents an enumerable value. |
| 461 | * The constant name must be the same as the constant value. |
| 462 | * For example, |
| 463 | * <code> |
| 464 | * class TTextAlign extends TEnumerable |
| 465 | * { |
| 466 | * const Left='Left'; |
| 467 | * const Right='Right'; |
| 468 | * } |
| 469 | * </code> |
| 470 | * Then, one can use the enumerable values such as TTextAlign::Left and |
| 471 | * TTextAlign::Right. |
| 472 | * |
| 473 | * @author Qiang Xue <qiang.xue@gmail.com> |
| 474 | * @version $Id$ |
| 475 | * @package System |
| 476 | * @since 3.0 |
| 477 | */ |
| 478 | class TEnumerable |
| 479 | { |
| 480 | } |
| 481 | |
| 482 | /** |
| 483 | * TPropertyValue class |
| 484 | * |
| 485 | * TPropertyValue is a utility class that provides static methods |
| 486 | * to convert component property values to specific types. |
| 487 | * |
| 488 | * TPropertyValue is commonly used in component setter methods to ensure |
| 489 | * the new property value is of specific type. |
| 490 | * For example, a boolean-typed property setter method would be as follows, |
| 491 | * <code> |
| 492 | * function setPropertyName($value) { |
| 493 | * $value=TPropertyValue::ensureBoolean($value); |
| 494 | * // $value is now of boolean type |
| 495 | * } |
| 496 | * </code> |
| 497 | * |
| 498 | * Properties can be of the following types with specific type conversion rules: |
| 499 | * - string: a boolean value will be converted to 'true' or 'false'. |
| 500 | * - boolean: string 'true' (case-insensitive) will be converted to true, |
| 501 | * string 'false' (case-insensitive) will be converted to false. |
| 502 | * - integer |
| 503 | * - float |
| 504 | * - array: string starting with '(' and ending with ')' will be considered as |
| 505 | * as an array expression and will be evaluated. Otherwise, an array |
| 506 | * with the value to be ensured is returned. |
| 507 | * - object |
| 508 | * - enum: enumerable type, represented by an array of strings. |
| 509 | * |
| 510 | * @author Qiang Xue <qiang.xue@gmail.com> |
| 511 | * @version $Id$ |
| 512 | * @package System |
| 513 | * @since 3.0 |
| 514 | */ |
| 515 | class TPropertyValue |
| 516 | { |
| 517 | /** |
| 518 | * Converts a value to boolean type. |
| 519 | * Note, string 'true' (case-insensitive) will be converted to true, |
| 520 | * string 'false' (case-insensitive) will be converted to false. |
| 521 | * If a string represents a non-zero number, it will be treated as true. |
| 522 | * @param mixed the value to be converted. |
| 523 | * @return boolean |
| 524 | */ |
| 525 | public static function ensureBoolean($value) |
| 526 | { |
| 527 | if (is_string($value)) |
| 528 | return strcasecmp($value,'true')==0 || $value!=0; |
| 529 | else |
| 530 | return (boolean)$value; |
| 531 | } |
| 532 | |
| 533 | /** |
| 534 | * Converts a value to string type. |
| 535 | * Note, a boolean value will be converted to 'true' if it is true |
| 536 | * and 'false' if it is false. |
| 537 | * @param mixed the value to be converted. |
| 538 | * @return string |
| 539 | */ |
| 540 | public static function ensureString($value) |
| 541 | { |
| 542 | if (is_bool($value)) |
| 543 | return $value?'true':'false'; |
| 544 | else |
| 545 | return (string)$value; |
| 546 | } |
| 547 | |
| 548 | /** |
| 549 | * Converts a value to integer type. |
| 550 | * @param mixed the value to be converted. |
| 551 | * @return integer |
| 552 | */ |
| 553 | public static function ensureInteger($value) |
| 554 | { |
| 555 | return (integer)$value; |
| 556 | } |
| 557 | |
| 558 | /** |
| 559 | * Converts a value to float type. |
| 560 | * @param mixed the value to be converted. |
| 561 | * @return float |
| 562 | */ |
| 563 | public static function ensureFloat($value) |
| 564 | { |
| 565 | return (float)$value; |
| 566 | } |
| 567 | |
| 568 | /** |
| 569 | * Converts a value to array type. If the value is a string and it is |
| 570 | * in the form (a,b,c) then an array consisting of each of the elements |
| 571 | * will be returned. If the value is a string and it is not in this form |
| 572 | * then an array consisting of just the string will be returned. If the value |
| 573 | * is not a string then |
| 574 | * @param mixed the value to be converted. |
| 575 | * @return array |
| 576 | */ |
| 577 | public static function ensureArray($value) |
| 578 | { |
| 579 | if(is_string($value)) |
| 580 | { |
| 581 | $value = trim($value); |
| 582 | $len = strlen($value); |
| 583 | if ($len >= 2 && $value[0] == '(' && $value[$len-1] == ')') |
| 584 | { |
| 585 | eval('$array=array'.$value.';'); |
| 586 | return $array; |
| 587 | } |
| 588 | else |
| 589 | return $len>0?array($value):array(); |
| 590 | } |
| 591 | else |
| 592 | return (array)$value; |
| 593 | } |
| 594 | |
| 595 | /** |
| 596 | * Converts a value to object type. |
| 597 | * @param mixed the value to be converted. |
| 598 | * @return object |
| 599 | */ |
| 600 | public static function ensureObject($value) |
| 601 | { |
| 602 | return (object)$value; |
| 603 | } |
| 604 | |
| 605 | /** |
| 606 | * Converts a value to enum type. |
| 607 | * |
| 608 | * This method checks if the value is of the specified enumerable type. |
| 609 | * A value is a valid enumerable value if it is equal to the name of a constant |
| 610 | * in the specified enumerable type (class). |
| 611 | * For more details about enumerable, see {@link TEnumerable}. |
| 612 | * |
| 613 | * For backward compatibility, this method also supports sanity |
| 614 | * check of a string value to see if it is among the given list of strings. |
| 615 | * @param mixed the value to be converted. |
| 616 | * @param mixed class name of the enumerable type, or array of valid enumeration values. If this is not an array, |
| 617 | * the method considers its parameters are of variable length, and the second till the last parameters are enumeration values. |
| 618 | * @return string the valid enumeration value |
| 619 | * @throws TInvalidDataValueException if the original value is not in the string array. |
| 620 | */ |
| 621 | public static function ensureEnum($value,$enums) |
| 622 | { |
| 623 | static $types=array(); |
| 624 | if(func_num_args()===2 && is_string($enums)) |
| 625 | { |
| 626 | if(!isset($types[$enums])) |
| 627 | $types[$enums]=new ReflectionClass($enums); |
| 628 | if($types[$enums]->hasConstant($value)) |
| 629 | return $value; |
| 630 | else |
| 631 | throw new TInvalidDataValueException( |
| 632 | 'propertyvalue_enumvalue_invalid',$value, |
| 633 | implode(' | ',$types[$enums]->getConstants())); |
| 634 | } |
| 635 | else if(!is_array($enums)) |
| 636 | { |
| 637 | $enums=func_get_args(); |
| 638 | array_shift($enums); |
| 639 | } |
| 640 | if(in_array($value,$enums,true)) |
| 641 | return $value; |
| 642 | else |
| 643 | throw new TInvalidDataValueException('propertyvalue_enumvalue_invalid',$value,implode(' | ',$enums)); |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | /** |
| 648 | * TEventParameter class. |
| 649 | * TEventParameter is the base class for all event parameter classes. |
| 650 | * |
| 651 | * @author Qiang Xue <qiang.xue@gmail.com> |
| 652 | * @version $Id$ |
| 653 | * @package System |
| 654 | * @since 3.0 |
| 655 | */ |
| 656 | class TEventParameter extends TComponent |
| 657 | { |
| 658 | } |
| 659 | |
| 660 | /** |
| 661 | * TComponentReflection class. |
| 662 | * |
| 663 | * TComponentReflection provides functionalities to inspect the public/protected |
| 664 | * properties, events and methods defined in a class. |
| 665 | * |
| 666 | * The following code displays the properties and events defined in {@link TDataGrid}, |
| 667 | * <code> |
| 668 | * $reflection=new TComponentReflection('TDataGrid'); |
| 669 | * Prado::varDump($reflection->getProperties()); |
| 670 | * Prado::varDump($reflection->getEvents()); |
| 671 | * </code> |
| 672 | * |
| 673 | * @author Qiang Xue <qiang.xue@gmail.com> |
| 674 | * @version $Id$ |
| 675 | * @package System |
| 676 | * @since 3.0 |
| 677 | */ |
| 678 | class TComponentReflection extends TComponent |
| 679 | { |
| 680 | private $_className; |
| 681 | private $_properties=array(); |
| 682 | private $_events=array(); |
| 683 | private $_methods=array(); |
| 684 | |
| 685 | /** |
| 686 | * Constructor. |
| 687 | * @param object|string the component instance or the class name |
| 688 | * @throws TInvalidDataTypeException if the object is not a component |
| 689 | */ |
| 690 |
