[OutputEscaper] refactored the component
This commit is contained in:
parent
e1116524ed
commit
c065be88b5
@ -18,7 +18,7 @@ namespace Symfony\Component\OutputEscaper;
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Mike Squire <mike@somosis.co.uk>
|
||||
*/
|
||||
class ArrayDecorator extends GetterDecorator implements \Iterator, \ArrayAccess, \Countable
|
||||
class ArrayDecorator extends BaseEscaper implements \Iterator, \ArrayAccess, \Countable
|
||||
{
|
||||
/**
|
||||
* Used by the iterator to know if the current element is valid.
|
||||
@ -141,6 +141,17 @@ class ArrayDecorator extends GetterDecorator implements \Iterator, \ArrayAccess,
|
||||
throw new \LogicException('Cannot unset values.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a key from the array using the specified escaper.
|
||||
*
|
||||
* @param string $key The array key
|
||||
* @param mixed $escaper The escaping method (a PHP callable or a named escaper)
|
||||
*/
|
||||
public function getEscapedKey($key, $escaper)
|
||||
{
|
||||
return Escaper::escape($escaper, $this->value[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the array (are required by the Countable interface).
|
||||
*
|
||||
@ -150,16 +161,4 @@ class ArrayDecorator extends GetterDecorator implements \Iterator, \ArrayAccess,
|
||||
{
|
||||
return count($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (unescaped) value from the array associated with the key supplied.
|
||||
*
|
||||
* @param string $key The key into the array to use
|
||||
*
|
||||
* @return mixed The value
|
||||
*/
|
||||
public function getRaw($key)
|
||||
{
|
||||
return $this->value[$key];
|
||||
}
|
||||
}
|
||||
|
69
src/Symfony/Component/OutputEscaper/BaseEscaper.php
Normal file
69
src/Symfony/Component/OutputEscaper/BaseEscaper.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\OutputEscaper;
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract class that provides an interface for output escaping.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Mike Squire <mike@somosis.co.uk>
|
||||
*/
|
||||
abstract class BaseEscaper
|
||||
{
|
||||
/**
|
||||
* The value that is to be escaped.
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* The escaper (a PHP callable or a named escaper) that is going to be applied to the value and its children.
|
||||
*/
|
||||
protected $escaper;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Since BaseEscaper is an abstract class, instances cannot be created
|
||||
* directly but the constructor will be inherited by sub-classes.
|
||||
*
|
||||
* @param mixed $escaper The escaping method (a PHP callable or a named escaper)
|
||||
* @param string $value Escaping value
|
||||
*/
|
||||
public function __construct($escaper, $value)
|
||||
{
|
||||
$this->escaper = $escaper;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default escaper to use.
|
||||
*
|
||||
* @param mixed $escaper The escaping method (a PHP callable or a named escaper)
|
||||
*/
|
||||
public function setEscaper($escaper)
|
||||
{
|
||||
$this->escaper = $escaper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw value associated with this instance.
|
||||
*
|
||||
* Concrete instances of BaseEscaper classes decorate a value which is
|
||||
* stored by the constructor. This returns that original, unescaped, value.
|
||||
*
|
||||
* @return mixed The original value used to construct the decorator
|
||||
*/
|
||||
public function getRawValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
@ -12,51 +12,17 @@ namespace Symfony\Component\OutputEscaper;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract class that provides an interface for escaping of output.
|
||||
* Escaper provides output escaping features.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Mike Squire <mike@somosis.co.uk>
|
||||
*/
|
||||
abstract class Escaper
|
||||
class Escaper
|
||||
{
|
||||
/**
|
||||
* The value that is to be escaped.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* The escaper (a PHP callable) that is going to be applied to the value and its
|
||||
* children.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $escaper;
|
||||
|
||||
static protected $charset = 'UTF-8';
|
||||
static protected $safeClasses = array();
|
||||
static protected $escapers;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Since Escaper is an abstract class, instances cannot be created
|
||||
* directly but the constructor will be inherited by sub-classes.
|
||||
*
|
||||
* @param string $callable A PHP callable
|
||||
* @param string $value Escaping value
|
||||
*/
|
||||
public function __construct($escaper, $value)
|
||||
{
|
||||
if (null === self::$escapers) {
|
||||
self::initializeEscapers();
|
||||
}
|
||||
|
||||
$this->escaper = is_string($escaper) && isset(self::$escapers[$escaper]) ? self::$escapers[$escaper] : $escaper;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorates a PHP variable with something that will escape any data obtained
|
||||
* from it.
|
||||
@ -78,7 +44,7 @@ abstract class Escaper
|
||||
* The escaping method is actually a PHP callable. This class hosts a set
|
||||
* of standard escaping strategies.
|
||||
*
|
||||
* @param string $escaper The escaping method (a PHP callable) to apply to the value
|
||||
* @param mixed $escaper The escaping method (a PHP callable or a named escaper) to apply to the value
|
||||
* @param mixed $value The value to escape
|
||||
*
|
||||
* @return mixed Escaped value
|
||||
@ -109,11 +75,10 @@ abstract class Escaper
|
||||
}
|
||||
|
||||
if (is_object($value)) {
|
||||
if ($value instanceof Escaper) {
|
||||
if ($value instanceof BaseEscaper) {
|
||||
// avoid double decoration
|
||||
$copy = clone $value;
|
||||
|
||||
$copy->escaper = $escaper;
|
||||
$copy->setEscaper($escaper);
|
||||
|
||||
return $copy;
|
||||
}
|
||||
@ -121,7 +86,7 @@ abstract class Escaper
|
||||
if ($value instanceof SafeDecorator) {
|
||||
// do not escape objects marked as safe
|
||||
// return the original object
|
||||
return $value->getValue();
|
||||
return $value->getRawValue();
|
||||
}
|
||||
|
||||
if (self::isClassMarkedAsSafe(get_class($value)) || $value instanceof SafeDecoratorInterface) {
|
||||
@ -170,7 +135,7 @@ abstract class Escaper
|
||||
}
|
||||
|
||||
if (is_object($value)) {
|
||||
return $value instanceof Escaper ? $value->getRawValue() : $value;
|
||||
return $value instanceof BaseEscaper ? $value->getRawValue() : $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
@ -218,19 +183,6 @@ abstract class Escaper
|
||||
self::markClassesAsSafe(array($class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw value associated with this instance.
|
||||
*
|
||||
* Concrete instances of Escaper classes decorate a value which is
|
||||
* stored by the constructor. This returns that original, unescaped, value.
|
||||
*
|
||||
* @return mixed The original value used to construct the decorator
|
||||
*/
|
||||
public function getRawValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current charset.
|
||||
*
|
||||
@ -262,6 +214,22 @@ abstract class Escaper
|
||||
self::$escapers[$name] = $escaper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a named escaper.
|
||||
*
|
||||
* @param string $name The escaper name
|
||||
*
|
||||
* @return mixed $escaper A PHP callable
|
||||
*/
|
||||
static public function getEscaper($escaper)
|
||||
{
|
||||
if (null === self::$escapers) {
|
||||
self::initializeEscapers();
|
||||
}
|
||||
|
||||
return is_string($escaper) && isset(self::$escapers[$escaper]) ? self::$escapers[$escaper] : $escaper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the built-in escapers.
|
||||
*
|
||||
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\OutputEscaper;
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract output escaping decorator class for "getter" objects.
|
||||
*
|
||||
* @see Escaper
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Mike Squire <mike@somosis.co.uk>
|
||||
*/
|
||||
abstract class GetterDecorator extends Escaper
|
||||
{
|
||||
/**
|
||||
* Returns the raw, unescaped value associated with the key supplied.
|
||||
*
|
||||
* The key might be an index into an array or a value to be passed to the
|
||||
* decorated object's get() method.
|
||||
*
|
||||
* @param string $key The key to retrieve
|
||||
*
|
||||
* @return mixed The value
|
||||
*/
|
||||
public abstract function getRaw($key);
|
||||
|
||||
/**
|
||||
* Returns the escaped value associated with the key supplied.
|
||||
*
|
||||
* Typically (using this implementation) the raw value is obtained using the
|
||||
* {@link getRaw()} method, escaped and the result returned.
|
||||
*
|
||||
* @param string $key The key to retrieve
|
||||
* @param string $escaper The escaping method (a PHP function) to use
|
||||
*
|
||||
* @return mixed The escaped value
|
||||
*/
|
||||
public function get($key, $escaper = null)
|
||||
{
|
||||
if (!$escaper) {
|
||||
$escaper = $this->escaper;
|
||||
}
|
||||
|
||||
return Escaper::escape($escaper, $this->getRaw($key));
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ namespace Symfony\Component\OutputEscaper;
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Mike Squire <mike@somosis.co.uk>
|
||||
*/
|
||||
class IteratorDecorator extends ObjectDecorator implements \Iterator, \Countable, \ArrayAccess
|
||||
class IteratorDecorator extends ObjectDecorator implements \Iterator
|
||||
{
|
||||
/**
|
||||
* The iterator to be used.
|
||||
@ -94,71 +94,4 @@ class IteratorDecorator extends ObjectDecorator implements \Iterator, \Countable
|
||||
{
|
||||
return $this->iterator->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied offset isset in the array (as required by the ArrayAccess interface).
|
||||
*
|
||||
* @param string $offset The offset of the value to check existence of
|
||||
*
|
||||
* @return bool true if the offset isset; false otherwise
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->value[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element associated with the offset supplied (as required by the ArrayAccess interface).
|
||||
*
|
||||
* @param string $offset The offset of the value to get
|
||||
*
|
||||
* @return mixed The escaped value
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return Escaper::escape($this->escaper, $this->value[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception saying that values cannot be set (this method is
|
||||
* required for the ArrayAccess interface).
|
||||
*
|
||||
* This (and the other Escaper classes) are designed to be read only
|
||||
* so this is an illegal operation.
|
||||
*
|
||||
* @param string $offset (ignored)
|
||||
* @param string $value (ignored)
|
||||
*
|
||||
* @throws \LogicException When trying to set values
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
throw new \LogicException('Cannot set values.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception saying that values cannot be unset (this method is
|
||||
* required for the ArrayAccess interface).
|
||||
*
|
||||
* This (and the other Escaper classes) are designed to be read only
|
||||
* so this is an illegal operation.
|
||||
*
|
||||
* @param string $offset (ignored)
|
||||
*
|
||||
* @throws \LogicException When trying to unset values
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
throw new \LogicException('Cannot unset values.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the array (are required by the Countable interface).
|
||||
*
|
||||
* @return int The size of the array
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->value);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace Symfony\Component\OutputEscaper;
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Mike Squire <mike@somosis.co.uk>
|
||||
*/
|
||||
class ObjectDecorator extends GetterDecorator
|
||||
class ObjectDecorator extends BaseEscaper implements \ArrayAccess, \Countable
|
||||
{
|
||||
/**
|
||||
* Magic PHP method that intercepts method calls, calls them on the objects
|
||||
@ -62,27 +62,6 @@ class ObjectDecorator extends GetterDecorator
|
||||
return Escaper::escape($escaper, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of calling the get() method on the object, bypassing
|
||||
* any escaping, if that method exists.
|
||||
*
|
||||
* If there is not a callable get() method this will throw an exception.
|
||||
*
|
||||
* @param string $key The parameter to be passed to the get() get method
|
||||
*
|
||||
* @return mixed The unescaped value returned
|
||||
*
|
||||
* @throws \LogicException if the object does not have a callable get() method
|
||||
*/
|
||||
public function getRaw($key)
|
||||
{
|
||||
if (!is_callable(array($this->value, 'get'))) {
|
||||
throw new \LogicException('Object does not have a callable get() method.');
|
||||
}
|
||||
|
||||
return $this->value->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to call decorated object __toString() method if exists.
|
||||
*
|
||||
@ -90,7 +69,7 @@ class ObjectDecorator extends GetterDecorator
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->escape($this->escaper, (string) $this->value);
|
||||
return Escaper::escape($this->escaper, (string) $this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +81,7 @@ class ObjectDecorator extends GetterDecorator
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->escape($this->escaper, $this->value->$key);
|
||||
return Escaper::escape($this->escaper, $this->value->$key);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,4 +95,97 @@ class ObjectDecorator extends GetterDecorator
|
||||
{
|
||||
return isset($this->value->$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes an object property using the specified escaper.
|
||||
*
|
||||
* @param string $key The object property name
|
||||
* @param mixed $escaper The escaping method (a PHP callable or a named escaper)
|
||||
*/
|
||||
public function getEscapedProperty($key, $escaper)
|
||||
{
|
||||
return Escaper::escape($escaper, $this->value->$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied offset isset in the array (as required by the ArrayAccess interface).
|
||||
*
|
||||
* @param string $offset The offset of the value to check existence of
|
||||
*
|
||||
* @return bool true if the offset isset; false otherwise
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->value[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element associated with the offset supplied (as required by the ArrayAccess interface).
|
||||
*
|
||||
* @param string $offset The offset of the value to get
|
||||
*
|
||||
* @return mixed The escaped value
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return Escaper::escape($this->escaper, $this->value[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception saying that values cannot be set (this method is
|
||||
* required for the ArrayAccess interface).
|
||||
*
|
||||
* This (and the other Escaper classes) are designed to be read only
|
||||
* so this is an illegal operation.
|
||||
*
|
||||
* @param string $offset (ignored)
|
||||
* @param string $value (ignored)
|
||||
*
|
||||
* @throws \LogicException When trying to set values
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
throw new \LogicException('Cannot set values.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception saying that values cannot be unset (this method is
|
||||
* required for the ArrayAccess interface).
|
||||
*
|
||||
* This (and the other Escaper classes) are designed to be read only
|
||||
* so this is an illegal operation.
|
||||
*
|
||||
* @param string $offset (ignored)
|
||||
*
|
||||
* @throws \LogicException When trying to unset values
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
throw new \LogicException('Cannot unset values.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a key from the array using the specified escaper.
|
||||
*
|
||||
* @param string $key The array key
|
||||
* @param mixed $escaper The escaping method (a PHP callable or a named escaper)
|
||||
*/
|
||||
public function getEscapedKey($key, $escaper)
|
||||
{
|
||||
return Escaper::escape($escaper, $this->value[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the array (are required by the Countable interface).
|
||||
*
|
||||
* @return int The size of the array
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
if ($this->value instanceof \Countable) {
|
||||
return count($this->value);
|
||||
}
|
||||
|
||||
return call_user_func_array(array($this->value, 'count'), func_get_args());
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace Symfony\Component\OutputEscaper;
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class SafeDecorator extends \ArrayIterator implements SafeDecoratorInterface
|
||||
class SafeDecorator implements SafeDecoratorInterface
|
||||
{
|
||||
protected $value;
|
||||
|
||||
@ -28,48 +28,14 @@ class SafeDecorator extends \ArrayIterator implements SafeDecoratorInterface
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
if (is_array($value) || is_object($value)) {
|
||||
parent::__construct($value);
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->value;
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->value->$key;
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->value->$key = $value;
|
||||
}
|
||||
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
return call_user_func_array(array($this->value, $method), $arguments);
|
||||
}
|
||||
|
||||
public function __isset($key)
|
||||
{
|
||||
return isset($this->value->$key);
|
||||
}
|
||||
|
||||
public function __unset($key)
|
||||
{
|
||||
unset($this->value->$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the embedded value.
|
||||
* Returns the raw value.
|
||||
*
|
||||
* @return mixed The embedded value
|
||||
* @return mixed The raw value
|
||||
*/
|
||||
public function getValue()
|
||||
public function getRawValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ class ArrayDecoratorTest extends \PHPUnit_Framework_TestCase
|
||||
self::$escaped = Escaper::escape('entities', $a);
|
||||
}
|
||||
|
||||
public function testGetRaw()
|
||||
public function testGetEscapedKey()
|
||||
{
|
||||
$this->assertEquals('<strong>escaped!</strong>', self::$escaped->getRaw(0), '->getRaw() returns the raw value');
|
||||
$this->assertEquals('<strong>escaped!</strong>', self::$escaped->getEscapedKey(0, 'raw'), '->getEscapedKey() returns the value with an other escaper');
|
||||
}
|
||||
|
||||
public function testArrayAccessInterface()
|
||||
|
@ -120,7 +120,7 @@ class EscaperTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('<strong>escaped!</strong>', $output->title, '::unescape() unescapes all properties of the original object');
|
||||
$this->assertEquals('<strong>escaped!</strong>', $output->getTitleTitle(), '::unescape() is recursive');
|
||||
|
||||
$this->assertInstanceOf('\DirectoryIterator', IteratorDecorator::unescape(Escaper::escape('entities', new \DirectoryIterator('.'))), '::unescape() unescapes IteratorDecorator objects');
|
||||
$this->assertInstanceOf('\DirectoryIterator', Escaper::unescape(Escaper::escape('entities', new \DirectoryIterator('.'))), '::unescape() unescapes IteratorDecorator objects');
|
||||
}
|
||||
|
||||
public function testUnescapeDoesNotUnescapeObjectMarkedAsBeingSafe()
|
||||
|
@ -50,21 +50,6 @@ class ObjectDecoratorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue(isset(self::$escaped->someMember), 'The escaped object behaves like the real object');
|
||||
$this->assertFalse(isset(self::$escaped->invalidMember), 'The escaped object behaves like the real object');
|
||||
}
|
||||
|
||||
public function testGetRaw()
|
||||
{
|
||||
$this->assertEquals('<em>escape me</em>', self::$escaped->getRaw('someMember'), '->getRaw() returns result with any escaping');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException LogicException
|
||||
*/
|
||||
public function testGetRawException()
|
||||
{
|
||||
$object = new \stdClass();
|
||||
$escaped = Escaper::escape('entities', $object);
|
||||
$escaped->getRaw('something');
|
||||
}
|
||||
}
|
||||
|
||||
class OutputEscaperTest
|
||||
|
@ -15,96 +15,9 @@ use Symfony\Component\OutputEscaper\SafeDecorator;
|
||||
|
||||
class SafeDecoratorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testGetValue()
|
||||
public function testGetRawValue()
|
||||
{
|
||||
$safe = new SafeDecorator('foo');
|
||||
$this->assertEquals('foo', $safe->getValue(), '->getValue() returns the embedded value');
|
||||
}
|
||||
|
||||
public function testMagicGetAndSet()
|
||||
{
|
||||
$safe = new SafeDecorator(new TestClass1());
|
||||
|
||||
$this->assertEquals('bar', $safe->foo, '->__get() returns the object parameter');
|
||||
$safe->foo = 'baz';
|
||||
$this->assertEquals('baz', $safe->foo, '->__set() sets the object parameter');
|
||||
}
|
||||
|
||||
public function testMagicCall()
|
||||
{
|
||||
$safe = new SafeDecorator(new TestClass2());
|
||||
|
||||
$this->assertEquals('ok', $safe->doSomething(), '->__call() invokes the embedded method');
|
||||
}
|
||||
|
||||
public function testMagicToString()
|
||||
{
|
||||
$safe = new SafeDecorator(new TestClass4());
|
||||
|
||||
$this->assertEquals('TestClass4', (string)$safe, '->__toString() invokes the embedded __toString method');
|
||||
}
|
||||
|
||||
public function testMagicIssetAndUnset()
|
||||
{
|
||||
$safe = new SafeDecorator(new TestClass3());
|
||||
|
||||
$this->assertTrue(isset($safe->boolValue), '->__isset() returns true if the property is not null');
|
||||
$this->assertFalse(isset($safe->nullValue), '->__isset() returns false if the property is null');
|
||||
$this->assertFalse(isset($safe->undefinedValue), '->__isset() returns false if the property does not exist');
|
||||
|
||||
unset($safe->boolValue);
|
||||
$this->assertFalse(isset($safe->boolValue), '->__unset() unsets the embedded property');
|
||||
}
|
||||
|
||||
public function testIteratorInterface()
|
||||
{
|
||||
$input = array('one' => 1, 'two' => 2, 'three' => 3, 'children' => array(1, 2, 3));
|
||||
$output = array();
|
||||
|
||||
$safe = new SafeDecorator($input);
|
||||
foreach ($safe as $key => $value) {
|
||||
$output[$key] = $value;
|
||||
}
|
||||
$this->assertSame($output, $input, '"Iterator" implementation imitates an array');
|
||||
}
|
||||
|
||||
public function testArrayAccessIterator()
|
||||
{
|
||||
$safe = new SafeDecorator(array('foo' => 'bar'));
|
||||
|
||||
$this->assertEquals('bar', $safe['foo'], '"ArrayAccess" implementation returns a value from the embedded array');
|
||||
$safe['foo'] = 'baz';
|
||||
$this->assertEquals('baz', $safe['foo'], '"ArrayAccess" implementation sets a value on the embedded array');
|
||||
$this->assertTrue(isset($safe['foo']), '"ArrayAccess" checks if a value is set on the embedded array');
|
||||
unset($safe['foo']);
|
||||
$this->assertFalse(isset($safe['foo']), '"ArrayAccess" unsets a value on the embedded array');
|
||||
$this->assertEquals('foo', $safe->getRawValue(), '->getValue() returns the embedded value');
|
||||
}
|
||||
}
|
||||
|
||||
class TestClass1
|
||||
{
|
||||
public $foo = 'bar';
|
||||
}
|
||||
|
||||
class TestClass2
|
||||
{
|
||||
public function doSomething()
|
||||
{
|
||||
return 'ok';
|
||||
}
|
||||
}
|
||||
|
||||
class TestClass3
|
||||
{
|
||||
public
|
||||
$boolValue = true,
|
||||
$nullValue = null;
|
||||
}
|
||||
|
||||
class TestClass4
|
||||
{
|
||||
public function __toString()
|
||||
{
|
||||
return 'TestClass4';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user