PageRenderTime 39ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/www/libs/nette-dev/ObjectMixin.php

https://github.com/bazo/Mokuji
PHP | 182 lines | 87 code | 36 blank | 59 comment | 18 complexity | 93a6c38b1702476c6441c2557cad4bc4 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. <?php
  2. /**
  3. * Nette Framework
  4. *
  5. * @copyright Copyright (c) 2004, 2010 David Grudl
  6. * @license http://nettephp.com/license Nette license
  7. * @link http://nettephp.com
  8. * @category Nette
  9. * @package Nette
  10. */
  11. /**
  12. * Nette\Object behaviour mixin.
  13. *
  14. * @copyright Copyright (c) 2004, 2010 David Grudl
  15. * @package Nette
  16. */
  17. final class ObjectMixin
  18. {
  19. /** @var array */
  20. private static $methods;
  21. /**
  22. * Static class - cannot be instantiated.
  23. */
  24. final public function __construct()
  25. {
  26. throw new LogicException("Cannot instantiate static class " . get_class($this));
  27. }
  28. /**
  29. * Call to undefined method.
  30. *
  31. * @param string method name
  32. * @param array arguments
  33. * @return mixed
  34. * @throws MemberAccessException
  35. */
  36. public static function call($_this, $name, $args)
  37. {
  38. $class = new ClassReflection($_this);
  39. if ($name === '') {
  40. throw new MemberAccessException("Call to class '$class->name' method without name.");
  41. }
  42. // event functionality
  43. if ($class->hasEventProperty($name)) {
  44. if (is_array($list = $_this->$name) || $list instanceof Traversable) {
  45. foreach ($list as $handler) {
  46. callback($handler)->invokeArgs($args);
  47. }
  48. }
  49. return NULL;
  50. }
  51. // extension methods
  52. if ($cb = $class->getExtensionMethod($name)) {
  53. array_unshift($args, $_this);
  54. return $cb->invokeArgs($args);
  55. }
  56. throw new MemberAccessException("Call to undefined method $class->name::$name().");
  57. }
  58. /**
  59. * Returns property value.
  60. *
  61. * @param string property name
  62. * @return mixed property value
  63. * @throws MemberAccessException if the property is not defined.
  64. */
  65. public static function & get($_this, $name)
  66. {
  67. $class = get_class($_this);
  68. if ($name === '') {
  69. throw new MemberAccessException("Cannot read a class '$class' property without name.");
  70. }
  71. if (!isset(self::$methods[$class])) {
  72. // get_class_methods returns ONLY PUBLIC methods of objects
  73. // but returns static methods too (nothing doing...)
  74. // and is much faster than reflection
  75. // (works good since 5.0.4)
  76. self::$methods[$class] = array_flip(get_class_methods($class));
  77. }
  78. // property getter support
  79. $name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
  80. $m = 'get' . $name;
  81. if (isset(self::$methods[$class][$m])) {
  82. // ampersands:
  83. // - uses &__get() because declaration should be forward compatible (e.g. with Nette\Web\Html)
  84. // - doesn't call &$_this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value';
  85. $val = $_this->$m();
  86. return $val;
  87. }
  88. $m = 'is' . $name;
  89. if (isset(self::$methods[$class][$m])) {
  90. $val = $_this->$m();
  91. return $val;
  92. }
  93. $name = func_get_arg(1);
  94. throw new MemberAccessException("Cannot read an undeclared property $class::\$$name.");
  95. }
  96. /**
  97. * Sets value of a property.
  98. *
  99. * @param string property name
  100. * @param mixed property value
  101. * @return void
  102. * @throws MemberAccessException if the property is not defined or is read-only
  103. */
  104. public static function set($_this, $name, $value)
  105. {
  106. $class = get_class($_this);
  107. if ($name === '') {
  108. throw new MemberAccessException("Cannot assign to a class '$class' property without name.");
  109. }
  110. if (!isset(self::$methods[$class])) {
  111. self::$methods[$class] = array_flip(get_class_methods($class));
  112. }
  113. // property setter support
  114. $name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
  115. if (isset(self::$methods[$class]['get' . $name]) || isset(self::$methods[$class]['is' . $name])) {
  116. $m = 'set' . $name;
  117. if (isset(self::$methods[$class][$m])) {
  118. $_this->$m($value);
  119. return;
  120. } else {
  121. $name = func_get_arg(1);
  122. throw new MemberAccessException("Cannot assign to a read-only property $class::\$$name.");
  123. }
  124. }
  125. $name = func_get_arg(1);
  126. throw new MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");
  127. }
  128. /**
  129. * Is property defined?
  130. *
  131. * @param string property name
  132. * @return bool
  133. */
  134. public static function has($_this, $name)
  135. {
  136. if ($name === '') {
  137. return FALSE;
  138. }
  139. $class = get_class($_this);
  140. if (!isset(self::$methods[$class])) {
  141. self::$methods[$class] = array_flip(get_class_methods($class));
  142. }
  143. $name[0] = $name[0] & "\xDF";
  144. return isset(self::$methods[$class]['get' . $name]) || isset(self::$methods[$class]['is' . $name]);
  145. }
  146. }