diff --git a/Decorator/Decorator.php b/Decorator/Decorator.php index 856b181..3231f09 100644 --- a/Decorator/Decorator.php +++ b/Decorator/Decorator.php @@ -1,6 +1,6 @@ _data = $data; - } - - public function renderData() - { - return $this->_data; - } -} - -abstract class Decorator +/** + * the Deoorator MUST implement the Renderer contract, this is the key-feature + * of this design pattern. If not, this is no longer a Decorator but just a dumb + * wrapper. + */ +abstract class Decorator implements Renderer { protected $_wrapped; - public function __construct($wrappable) + /** + * You must type-hint the wrapped component : + * It ensures you can call renderData() in the subclasses ! + * + * @param Renderer $wrappable + */ + public function __construct(Renderer $wrappable) { $this->_wrapped = $wrappable; } } -class RenderInJson extends Decorator implements Renderer -{ - public function renderData() - { - $output = $this->_wrapped->renderData(); - return json_encode($output); - } -} - -class RenderInXml extends Decorator implements Renderer -{ - public function renderData() - { - $output = $this->_wrapped->renderData(); - // do some fany conversion to xml from array ... - return simplexml_load_string($output); - } -} - -// Create a normal service -$service = new Webservice(array('foo' => 'bar')); - -// Wrap service with a JSON decorator for renderers -$service = new RenderInJson($service); -// Our Renderer will now output JSON instead of an array - -echo $service->renderData(); diff --git a/Decorator/RenderInJson.php b/Decorator/RenderInJson.php new file mode 100644 index 0000000..57f8b06 --- /dev/null +++ b/Decorator/RenderInJson.php @@ -0,0 +1,12 @@ +_wrapped->renderData(); + return json_encode($output); + } +} diff --git a/Decorator/RenderInXml.php b/Decorator/RenderInXml.php new file mode 100644 index 0000000..6e594f9 --- /dev/null +++ b/Decorator/RenderInXml.php @@ -0,0 +1,18 @@ +_wrapped->renderData(); + // do some fany conversion to xml from array ... + $doc = new \DOMDocument(); + foreach ($output as $key => $val) { + $doc->appendChild($doc->createElement('foo', 'bar')); + } + + return $doc->saveXML(); + } +} diff --git a/Decorator/Renderer.php b/Decorator/Renderer.php new file mode 100644 index 0000000..6a01d4e --- /dev/null +++ b/Decorator/Renderer.php @@ -0,0 +1,8 @@ +_data = $data; + } + + public function renderData() + { + return $this->_data; + } +} diff --git a/Tests/Decorator/DecoratorTest.php b/Tests/Decorator/DecoratorTest.php new file mode 100644 index 0000000..f8a759b --- /dev/null +++ b/Tests/Decorator/DecoratorTest.php @@ -0,0 +1,40 @@ +service = new Decorator\Webservice(array('foo' => 'bar')); + } + + public function testJsonDecorator() + { + // Wrap service with a JSON decorator for renderers + $service = new Decorator\RenderInJson($this->service); + // Our Renderer will now output JSON instead of an array + $this->assertEquals('{"foo":"bar"}', $service->renderData()); + } + + public function testXmlDecorator() + { + // Wrap service with a JSON decorator for renderers + $service = new Decorator\RenderInXml($this->service); + // Our Renderer will now output XML instead of an array + $this->assertXmlStringEqualsXmlString('bar', $service->renderData()); + } + +} \ No newline at end of file