ObjectDecorator.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. namespace Symfony\Component\OutputEscaper;
  3. /*
  4. * This file is part of the Symfony package.
  5. *
  6. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. /**
  12. * Output escaping object decorator that intercepts all method calls and escapes
  13. * their return values.
  14. *
  15. * @see Escaper
  16. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  17. * @author Mike Squire <mike@somosis.co.uk>
  18. */
  19. class ObjectDecorator extends BaseEscaper implements \ArrayAccess, \Countable
  20. {
  21. /**
  22. * Magic PHP method that intercepts method calls, calls them on the objects
  23. * that is being escaped and escapes the result.
  24. *
  25. * The calling of the method is changed slightly to accommodate passing a
  26. * specific escaping strategy. An additional parameter is appended to the
  27. * argument list which is the escaping strategy. The decorator will remove
  28. * and use this parameter as the escaping strategy if it begins with 'esc_'.
  29. *
  30. * For example if an object, $o, implements methods a() and b($arg):
  31. *
  32. * $o->a() // Escapes the return value of a()
  33. * $o->a('esc_raw') // Uses the escaping strategy 'raw' with a()
  34. * $o->b('a') // Escapes the return value of b('a')
  35. * $o->b('a', 'esc_raw'); // Uses the escaping strategy 'raw' with b('a')
  36. *
  37. * @param string $method The method on the object to be called
  38. * @param array $args An array of arguments to be passed to the method
  39. *
  40. * @return mixed The escaped value returned by the method
  41. */
  42. public function __call($method, $args)
  43. {
  44. if (count($args) > 0) {
  45. $escaper = $args[count($args) - 1];
  46. if (is_string($escaper) && 'esc_' === substr($escaper, 0, 4)) {
  47. $escaper = substr($escaper, 4);
  48. array_pop($args);
  49. } else {
  50. $escaper = $this->escaper;
  51. }
  52. } else {
  53. $escaper = $this->escaper;
  54. }
  55. $value = call_user_func_array(array($this->value, $method), $args);
  56. return Escaper::escape($escaper, $value);
  57. }
  58. /**
  59. * Try to call decorated object __toString() method if exists.
  60. *
  61. * @return string
  62. */
  63. public function __toString()
  64. {
  65. return Escaper::escape($this->escaper, (string) $this->value);
  66. }
  67. /**
  68. * Gets a value from the escaper.
  69. *
  70. * @param string $key The name of the value to get
  71. *
  72. * @return mixed The value from the wrapped object
  73. */
  74. public function __get($key)
  75. {
  76. return Escaper::escape($this->escaper, $this->value->$key);
  77. }
  78. /**
  79. * Checks whether a value is set on the wrapped object.
  80. *
  81. * @param string $key The name of the value to check
  82. *
  83. * @return boolean Returns true if the value is set
  84. */
  85. public function __isset($key)
  86. {
  87. return isset($this->value->$key);
  88. }
  89. /**
  90. * Escapes an object property using the specified escaper.
  91. *
  92. * @param string $key The object property name
  93. * @param mixed $escaper The escaping method (a PHP callable or a named escaper)
  94. */
  95. public function getEscapedProperty($key, $escaper)
  96. {
  97. return Escaper::escape($escaper, $this->value->$key);
  98. }
  99. /**
  100. * Returns true if the supplied offset isset in the array (as required by the ArrayAccess interface).
  101. *
  102. * @param string $offset The offset of the value to check existence of
  103. *
  104. * @return bool true if the offset isset; false otherwise
  105. */
  106. public function offsetExists($offset)
  107. {
  108. return isset($this->value[$offset]);
  109. }
  110. /**
  111. * Returns the element associated with the offset supplied (as required by the ArrayAccess interface).
  112. *
  113. * @param string $offset The offset of the value to get
  114. *
  115. * @return mixed The escaped value
  116. */
  117. public function offsetGet($offset)
  118. {
  119. return Escaper::escape($this->escaper, $this->value[$offset]);
  120. }
  121. /**
  122. * Throws an exception saying that values cannot be set (this method is
  123. * required for the ArrayAccess interface).
  124. *
  125. * This (and the other Escaper classes) are designed to be read only
  126. * so this is an illegal operation.
  127. *
  128. * @param string $offset (ignored)
  129. * @param string $value (ignored)
  130. *
  131. * @throws \LogicException When trying to set values
  132. */
  133. public function offsetSet($offset, $value)
  134. {
  135. throw new \LogicException('Cannot set values.');
  136. }
  137. /**
  138. * Throws an exception saying that values cannot be unset (this method is
  139. * required for the ArrayAccess interface).
  140. *
  141. * This (and the other Escaper classes) are designed to be read only
  142. * so this is an illegal operation.
  143. *
  144. * @param string $offset (ignored)
  145. *
  146. * @throws \LogicException When trying to unset values
  147. */
  148. public function offsetUnset($offset)
  149. {
  150. throw new \LogicException('Cannot unset values.');
  151. }
  152. /**
  153. * Escapes a key from the array using the specified escaper.
  154. *
  155. * @param string $key The array key
  156. * @param mixed $escaper The escaping method (a PHP callable or a named escaper)
  157. */
  158. public function getEscapedKey($key, $escaper)
  159. {
  160. return Escaper::escape($escaper, $this->value[$key]);
  161. }
  162. /**
  163. * Returns the size of the array (are required by the Countable interface).
  164. *
  165. * @return int The size of the array
  166. */
  167. public function count()
  168. {
  169. if ($this->value instanceof \Countable) {
  170. return count($this->value);
  171. }
  172. return call_user_func_array(array($this->value, 'count'), func_get_args());
  173. }
  174. }