/framework/basic/YPFObject.php

https://github.com/yonpols/ypframework · PHP · 257 lines · 197 code · 51 blank · 9 comment · 40 complexity · 1e394b87111d48f37c20c537c1d3f57e MD5 · raw file

  1. <?php
  2. class YPFObject implements YPFSerializable {
  3. private static $__mixin_included = null;
  4. private static $__object_ids = 0;
  5. public static $__callbacks = null;
  6. private static $__loadedClasses = null;
  7. private $id = null;
  8. //Mixins================================================================
  9. /**
  10. * Include class variables and functions to this class
  11. * @param string $className
  12. * @return boolean returns true if the class was included
  13. */
  14. public static function __include($className) {
  15. $baseClass = get_called_class();
  16. if (!isset(YPFObject::$__mixin_included->{$baseClass}))
  17. {
  18. $params = new stdClass();
  19. $params->classes = array();
  20. $params->methods = array();
  21. $params->vars = array();
  22. YPFObject::$__mixin_included->{$baseClass} = $params;
  23. } else
  24. $params = YPFObject::$__mixin_included->{$baseClass};
  25. if (array_search($className, $params->classes) !== false)
  26. return false;
  27. $params->classes[] = $className;
  28. $class = new ReflectionClass($className);
  29. $methods = $class->getMethods(ReflectionMethod::IS_PUBLIC);
  30. foreach($methods as $method)
  31. if (($method->name[0] != '_') && ($method->getDeclaringClass()->name == $className))
  32. $params->methods[$method->name] = $className;
  33. $properties = $class->getProperties(ReflectionProperty::IS_PUBLIC);
  34. $vars = get_class_vars($className);
  35. foreach($properties as $property)
  36. if ($property->getDeclaringClass()->name == $className)
  37. $params->vars[$property->name] = $vars[$property->name];
  38. return true;
  39. }
  40. public function __construct() {
  41. $baseName = get_class($this);
  42. while ($baseName)
  43. {
  44. if ((YPFObject::$__mixin_included !== null) && isset(YPFObject::$__mixin_included->{$baseName}))
  45. {
  46. foreach (YPFObject::$__mixin_included->{$baseName}->vars as $varName => $varValue)
  47. $this->{$varName} = $varValue;
  48. foreach (YPFObject::$__mixin_included->{$baseName}->classes as $class)
  49. {
  50. if (array_search ('__included', get_class_methods ($class)) !== false)
  51. eval("$class::__included(\$this);");
  52. }
  53. }
  54. $baseName = get_parent_class($baseName);
  55. }
  56. }
  57. public function __call($name, $arguments) {
  58. $baseName = get_class($this);
  59. do {
  60. if ((YPFObject::$__mixin_included !== null)
  61. && isset(YPFObject::$__mixin_included->{$baseName})
  62. && isset(YPFObject::$__mixin_included->{$baseName}->methods[$name]))
  63. {
  64. $className = YPFObject::$__mixin_included->{$baseName}->methods[$name];
  65. if (empty($arguments))
  66. $methodCall = "return $className::$name();";
  67. else
  68. $methodCall = "return $className::$name(\$arguments[".implode('], $arguments[', array_keys($arguments)).']);';
  69. return eval($methodCall);
  70. }
  71. } while (($baseName = get_parent_class($baseName)));
  72. throw new BaseError(sprintf('No method defined for: %s->%s', $baseName, $name));
  73. }
  74. //Object UID============================================================
  75. public function getObjectId() {
  76. if ($this->id === null)
  77. $this->id = sprintf("%x", time()+(self::$__object_ids++));
  78. return $this->id;
  79. }
  80. //Object Event Model====================================================
  81. public static function initialize() {
  82. $className = get_called_class();
  83. if ($className !== 'YPFObject') {
  84. YPFObject::$__loadedClasses[] = $className;
  85. return;
  86. }
  87. YPFObject::$__mixin_included = new stdClass();
  88. YPFObject::$__callbacks = new stdClass();
  89. YPFObject::$__loadedClasses = array();
  90. }
  91. public static function finalize() {
  92. if (get_called_class() !== 'YPFObject')
  93. return;
  94. foreach (YPFObject::$__loadedClasses as $className)
  95. $className::finalize();
  96. }
  97. public static final function before($event, $action = null) {
  98. $className = get_called_class();
  99. $callbacks = self::__getCallbacks($className);
  100. if (!isset($callbacks->before->{$event}))
  101. $callbacks->before->{$event} = array();
  102. if ($action === null)
  103. return $callbacks->before->{$event};
  104. elseif ($action === false)
  105. $callbacks->before->{$event} = array();
  106. elseif (array_search($action, $callbacks->before->{$event}) === false)
  107. $callbacks->before->{$event}[] = $action;
  108. }
  109. public static final function after($event, $action = null) {
  110. $className = get_called_class();
  111. $callbacks = self::__getCallbacks($className);
  112. if (!isset($callbacks->after->{$event}))
  113. $callbacks->after->{$event} = array();
  114. if ($action === null)
  115. return $callbacks->after->{$event};
  116. elseif ($action === false)
  117. $callbacks->after->{$event} = array();
  118. elseif (array_search($action, $callbacks->after->{$event}) === false)
  119. $callbacks->after->{$event}[] = $action;
  120. }
  121. public static final function on($event, $action = null) {
  122. $className = get_called_class();
  123. $callbacks = self::__getCallbacks($className);
  124. if (!isset($callbacks->on->{$event}))
  125. $callbacks->on->{$event} = array();
  126. if ($action === null)
  127. return $callbacks->on->{$event};
  128. elseif ($action === false)
  129. $callbacks->on->{$event} = array();
  130. elseif (array_search($action, $callbacks->on->{$event}) === false)
  131. $callbacks->on->{$event}[] = $action;
  132. }
  133. private static function __getCallbacks($className) {
  134. if (!isset(YPFObject::$__callbacks->{$className})) {
  135. $callbacks = new stdClass();
  136. $callbacks->before = new stdClass();
  137. $callbacks->after = new stdClass();
  138. $callbacks->on = new stdClass();
  139. $parentClass = get_parent_class($className);
  140. if ($parentClass != 'YPFObject') {
  141. $parentCallbacks = self::__getCallbacks($parentClass);
  142. foreach ($parentCallbacks->before as $key => $vals)
  143. $callbacks->before->{$key} = $vals;
  144. foreach ($parentCallbacks->after as $key => $vals)
  145. $callbacks->after->{$key} = $vals;
  146. foreach ($parentCallbacks->on as $key => $vals)
  147. $callbacks->on->{$key} = $vals;
  148. }
  149. YPFObject::$__callbacks->{$className} = $callbacks;
  150. } else
  151. $callbacks = YPFObject::$__callbacks->{$className};
  152. return $callbacks;
  153. }
  154. //Object serialization==================================================
  155. public function __toString() {
  156. $str = sprintf('<%s ', get_class($this));
  157. foreach ($this as $k=>$v)
  158. $str .= sprintf('%s: %s; ', $k, var_export($v, true));
  159. return substr($str, 0, -2).'>';
  160. }
  161. public function __toJSONRepresentable() {
  162. $result = array();
  163. foreach ($this as $k=>$v)
  164. {
  165. if (is_object($v) && ($v instanceof YPFSerializable))
  166. {
  167. if (!($v instanceof YPFNoJsonable))
  168. $result[$k] = $v->__toJSONRepresentable();
  169. } elseif ($k != 'id')
  170. $result[$k] = $v;
  171. }
  172. return $result;
  173. }
  174. public function __toJSON() {
  175. return json_encode($this->__toJSONRepresentable());
  176. }
  177. public function __toXML($xmlParent = null) {
  178. if ($xmlParent === null)
  179. $root = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><root />');
  180. else
  181. $root = $xmlParent;
  182. foreach($this as $key=>$val)
  183. {
  184. if (is_array($val)) {
  185. $parent = $root->addChild($key);
  186. foreach($val as $item)
  187. if (is_object($item) && ($item instanceof YPFObject))
  188. $item->__toXML($parent);
  189. else
  190. $parent->addChild($item);
  191. } elseif (is_scalar($val) or ($val == null))
  192. $root->addChild($key, $val);
  193. elseif (is_object($val) && ($val instanceof YPFObject))
  194. $val->__toXML($root->addChild($key));
  195. }
  196. if ($xmlParent === null)
  197. return $root->asXML();
  198. }
  199. }
  200. interface YPFSerializable {
  201. public function __toJSONRepresentable();
  202. public function __toJSON();
  203. public function __toXML($xmlParent = null);
  204. }
  205. YPFObject::initialize();
  206. ?>