LOG4PHP-141: Finished default renderer implementation.
authorIvan Habunek <ihabunek@apache.org>
Sat, 6 Oct 2012 08:10:29 +0000 (08:10 +0000)
committerIvan Habunek <ihabunek@apache.org>
Sat, 6 Oct 2012 08:10:29 +0000 (08:10 +0000)
Updated docs and tests.

git-svn-id: https://svn.apache.org/repos/asf/logging/log4php/trunk@1394956 13f79535-47bb-0310-9956-ffa450edef68

19 files changed:
src/main/php/LoggerAutoloader.php
src/main/php/LoggerHierarchy.php
src/main/php/configurators/LoggerConfigurationAdapterXML.php
src/main/php/configurators/LoggerConfiguratorDefault.php
src/main/php/renderers/LoggerRenderer.php
src/main/php/renderers/LoggerRendererDefault.php
src/main/php/renderers/LoggerRendererException.php
src/main/php/renderers/LoggerRendererMap.php
src/main/php/renderers/LoggerRendererObject.php [deleted file]
src/site/xdoc/changelog.xml
src/site/xdoc/docs/renderers.xml
src/test/php/LoggerConfiguratorTest.php
src/test/php/renderers/LoggerRendererDefaultTest.php [deleted file]
src/test/php/renderers/LoggerRendererExceptionTest.php [deleted file]
src/test/php/renderers/LoggerRendererMapTest.php
src/test/php/renderers/LoggerRendererObjectTest.php [deleted file]
src/test/php/renderers/test4.properties [deleted file]
src/test/resources/configs/renderers/config_default_renderer.xml [moved from src/test/resources/configs/renderers/config_not_existing_rendered_class.xml with 80% similarity]
src/test/resources/configs/renderers/config_not_existing_rendering_class.xml

index d3b5df5..87a87c7 100644 (file)
@@ -128,7 +128,6 @@ class LoggerAutoloader {
                'LoggerRendererException' => '/renderers/LoggerRendererException.php',\r
                'LoggerRendererMap' => '/renderers/LoggerRendererMap.php',\r
                'LoggerRenderer' => '/renderers/LoggerRenderer.php',\r
-               'LoggerRendererObject'  => '/renderers/LoggerRendererObject.php',\r
        );\r
        \r
        /**\r
index 8b71601..55fe143 100644 (file)
@@ -204,7 +204,7 @@ class LoggerHierarchy {
                        $logger->removeAllAppenders();
                }
                
-               $this->rendererMap->clear();
+               $this->rendererMap->reset();
                LoggerAppenderPool::clear();
        }
        
index 7ee6f6d..7032da6 100644 (file)
@@ -62,6 +62,12 @@ class LoggerConfigurationAdapterXML implements LoggerConfigurationAdapter
                foreach($xml->renderer as $rendererNode) {\r
                        $this->parseRenderer($rendererNode);\r
                }\r
+\r
+               // Process <defaultRenderer> node\r
+               foreach($xml->defaultRenderer as $rendererNode) {\r
+                       $this->parseDefaultRenderer($rendererNode);\r
+               }\r
+\r
                return $this->config;\r
        }\r
        \r
@@ -245,6 +251,18 @@ class LoggerConfigurationAdapterXML implements LoggerConfigurationAdapter
                $this->config['renderers'][] = compact('renderedClass', 'renderingClass');\r
        }\r
        \r
+       /** Parses a <defaultRenderer> node. */\r
+       private function parseDefaultRenderer(SimpleXMLElement $node) {\r
+               $renderingClass = $this->getAttributeValue($node, 'renderingClass');\r
+               \r
+               // Warn on duplicates\r
+               if(isset($this->config['defaultRenderer'])) {\r
+                       $this->warn("Duplicate <defaultRenderer> node. Overwriting.");\r
+               }\r
+               \r
+               $this->config['defaultRenderer'] = $renderingClass; \r
+       }\r
+       \r
        // ******************************************\r
        // ** Helper methods                       **\r
        // ******************************************\r
index 14f2d01..f78b797 100644 (file)
@@ -219,61 +219,36 @@ class LoggerConfiguratorDefault implements LoggerConfigurator
                        foreach($config['renderers'] as $rendererConfig) {\r
                                $this->configureRenderer($hierarchy, $rendererConfig);\r
                        }\r
-                       \r
-                       \r
+               }\r
+               \r
+               if (isset($config['defaultRenderer'])) {\r
+                       $this->configureDefaultRenderer($hierarchy, $config['defaultRenderer']);\r
                }\r
        }\r
        \r
        private function configureRenderer(LoggerHierarchy $hierarchy, $config) {\r
-               if (isset($config['defaultObjectRenderer'])) {\r
-                       $objectRendererClass = $config['defaultObjectRenderer']; \r
-                       $this->existsRendererClass($objectRendererClass);\r
-                       $objectRendererInstance = new $objectRendererClass;\r
-                       $this->isRendererClassLoggerRenderer($objectRendererInstance, $objectRendererClass);\r
-                       \r
-                       $hierarchy->getRendererMap()->setDefaultObjectRenderer($objectRendererInstance);\r
+               if (empty($config['renderingClass'])) {\r
+                       $this->warn("Rendering class not specified. Skipping renderer definition.");\r
                        return;\r
                }\r
                \r
-               \r
-               if (!isset($config['renderingClass'])) {\r
-                       $this->warn("Rendering class not specified. Skipping renderers definition.");\r
-                       return;                 \r
-               }\r
-               \r
-               $renderingClass = $config['renderingClass'];\r
-               \r
-               $this->existsRendererClass($renderingClass);\r
-               \r
-               $renderingClassInstance = new $renderingClass();\r
-               $this->isRendererClassLoggerRenderer($renderingClassInstance, $renderingClass);\r
-       \r
-               if (!isset($config['renderedClass'])) {\r
-                       $this->warn("Rendered class not specified for rendering Class [$renderingClass]. Skipping renderers definition.");\r
-                       return;                 \r
-               }\r
-               \r
-               $renderedClass = $config['renderedClass'];\r
-               if (!class_exists($renderedClass)) {\r
-                       $this->warn("Nonexistant rendered class [$renderedClass] specified for renderer [$renderingClass]. Skipping renderers definition.");\r
+               if (empty($config['renderedClass'])) {\r
+                       $this->warn("Rendered class not specified. Skipping renderer definition.");\r
                        return;\r
                }\r
                \r
-               $hierarchy->getRendererMap()->addRenderer($renderedClass, $renderingClassInstance);\r
+               // Error handling performed by RendererMap\r
+               $hierarchy->getRendererMap()->addRenderer($config['renderedClass'], $config['renderingClass']);\r
        }\r
        \r
-       private function existsRendererClass($renderingClass) {\r
-               if (!class_exists($renderingClass)) {\r
-                       $this->warn("Nonexistant rendering class [$renderingClass] specified. Skipping renderers definition.");\r
-                       return;\r
-               }               \r
-       }\r
-       \r
-       private function isRendererClassLoggerRenderer($renderingClassInstance, $renderingClass) {\r
-               if (!$renderingClassInstance instanceof LoggerRenderer) {\r
-                       $this->warn("Invalid class [$renderingClass] given. Not a valid LoggerRenderer class. Skipping renderers definition.");\r
+       private function configureDefaultRenderer(LoggerHierarchy $hierarchy, $class) {\r
+               if (empty($class)) {\r
+                       $this->warn("Rendering class not specified. Skipping default renderer definition.");\r
                        return;\r
                }\r
+               \r
+               // Error handling performed by RendererMap\r
+               $hierarchy->getRendererMap()->setDefaultRenderer($class);\r
        }\r
        \r
        /** \r
index 816d1f8..dd913fe 100644 (file)
  */
 
 /**
- * Implement this interface in order to render objects as strings using {@link LoggerRendererMap}.
- *
- * Implement this interface in order to render objects as strings using {@link LoggerRendererMap}.
- *
- * Example:
- * {@example ../../examples/php/renderer_map.php 19}<br>
- * {@example ../../examples/resources/renderer_map.properties 18}<br>
- * <pre>
- * DEBUG - Now comes the current MyClass object:
- * DEBUG - Doe, John
- * </pre>
+ * Implement this interface in order to render objects to strings.
  *
  * @version $Revision$
  * @package log4php
@@ -38,9 +28,9 @@
  */
 interface LoggerRenderer {
        /**
-        * Render the entity passed as parameter as a String.
-        * @param mixed $input entity to render
-        * @return string
+        * Renders the entity passed as <var>input</var> to a string.
+        * @param mixed $input The entity to render.
+        * @return string The rendered string.
         */
        public function render($input);
 }
index b5f409a..2f35f97 100644 (file)
  */
 
 /**
- * The default Renderer renders objects by type casting.
+ * The default renderer, which is used when no other renderer is found.
  * 
- * Example:
- * 
- * {@example ../../examples/php/renderer_default.php 19}<br>
- * {@example ../../examples/resources/renderer_default.properties 18}<br>
- * <pre>
- * DEBUG - Now comes the current MyClass object:
- * DEBUG - Person::__set_state(array(
- *  'firstName' => 'John',
- *  'lastName' => 'Doe',
- * ))
- * </pre>
+ * Renders the input using <var>print_r</var>.
  *
  * @package log4php
  * @subpackage renderers
  */
 class LoggerRendererDefault implements LoggerRenderer {
 
-       /**
-        * Render objects by type casting
-        *
-        * @param mixed $input the object to render
-        * @return string
-        */
+       /** @inheritdoc */
        public function render($input) {
-               return var_export($input, true);
+               return print_r($input, true);
        }
 }
index 4040035..d78bcb8 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 /**
- * Exception renderer
+ * Renderer used for Exceptions.
  *
  * @package log4php
  * @subpackage renderers
 class LoggerRendererException implements LoggerRenderer {
 
        public function render($input) {
-               $strRep  = 'Throwable('.get_class($input).'): '.$input->getMessage().' in '.$input->getFile().' on line '.$input->getLine();
-               $strRep .= PHP_EOL.$input->getTraceAsString();
                
-               if (method_exists($input, 'getPrevious') && $input->getPrevious() !== null) {
-                       $strRep .= PHP_EOL.'Caused by: '.$this->render($input->getPrevious());
-               }
-               
-               return $strRep;         
+               // Exception class has a very decent __toString method
+               // so let's just use that instead of writing lots of code.
+               return (string) $input; 
        }
 }
index d02eed2..8e7631b 100644 (file)
  */
 
 /**
- * Log objects using customized renderers that implement {@link LoggerRendererObject}.
+ * Manages defined renderers and determines which renderer to use for a given 
+ * input. 
  *
- * Example:
- * {@example ../../examples/php/renderer_map.php 19}<br>
- * {@example ../../examples/resources/renderer_map.properties 18}<br>
- * <pre>
- * DEBUG - Now comes the current MyClass object:
- * DEBUG - Doe, John
- * </pre>
- * 
  * @version $Revision$
  * @package log4php
  * @subpackage renderers
 class LoggerRendererMap {
 
        /**
+        * Maps class names to appropriate renderers.
         * @var array
         */
-       private $map;
+       private $map = array();
 
        /**
-        * @var LoggerDefaultRenderer
+        * The default renderer to use if no specific renderer is found. 
+        * @var LoggerRenderer
         */
        private $defaultRenderer;
        
-       /**
-        * @var LoggerRendererObject
-        */
-       private $defaultObjectRenderer;
-
-       /**
-        * Constructor
-        */
        public function __construct() {
-               $this->map = array();
-               $this->defaultRenderer = new LoggerRendererDefault();
-               $this->defaultObjectRenderer = new LoggerRendererObject();
+               
+               // Set default config
+               $this->reset();
        }
 
        /**
-        * Add a renderer to a hierarchy passed as parameter.
-        * Note that hierarchy must implement getRendererMap() and setRenderer() methods.
+        * Adds a renderer to the map.
+        * 
+        * If a renderer already exists for the given <var>$renderedClass</var> it 
+        * will be overwritten without warning.
         *
-        * @param LoggerHierarchy $repository a logger repository.
-        * @param string $renderedClassName
-        * @param string $renderingClassName
+        * @param string $renderedClass The name of the class which will be 
+        *              rendered by the renderer.
+        * @param string $renderingClass The name of the class which will 
+        *              perform the rendering.
         */
-       public function addRenderer($renderedClassName, $renderingClassName) {
-               $renderer = LoggerReflectionUtils::createObject($renderingClassName);
-               if($renderer == null) {
+       public function addRenderer($renderedClass, $renderingClass) {
+               // Check the rendering class exists
+               if (!class_exists($renderingClass)) {
+                       trigger_error("log4php: Failed adding renderer. Rendering class [$renderingClass] not found.");
                        return;
-               } else {
-                       $this->put($renderedClassName, $renderer);
                }
+               
+               // Create the instance
+               $renderer = new $renderingClass();
+               
+               // Check the class implements the right interface
+               if (!($renderer instanceof LoggerRenderer)) {
+                       trigger_error("log4php: Failed adding renderer. Rendering class [$renderingClass] does not implement the LoggerRenderer interface.");
+                       return;
+               }
+               
+               // Convert to lowercase since class names in PHP are not case sensitive
+               $renderedClass = strtolower($renderedClass);
+               
+               $this->map[$renderedClass] = $renderer;
        }
-
-
+       
        /**
-        * Find the appropriate renderer for the class type of the
-        * <var>o</var> parameter. 
+        * Sets a custom default renderer class.
+        * 
+        * TODO: there's code duplication here. This method is almost identical to 
+        * addRenderer(). However, it has custom error messages so let it sit for 
+        * now.
         *
-        * This is accomplished by calling the {@link getByObject()} 
-        * method if <var>o</var> is object or using {@link LoggerRendererDefault}. 
-        * Once a renderer is found, it is applied on the object <var>o</var> and 
-        * the result is returned as a string.
+        * @param string $renderingClass The name of the class which will 
+        *              perform the rendering.
+        */
+       public function setDefaultRenderer($renderingClass) {
+               // Check the class exists
+               if (!class_exists($renderingClass)) {
+                       trigger_error("log4php: Failed setting default renderer. Rendering class [$renderingClass] not found.");
+                       return;
+               }
+               
+               // Create the instance
+               $renderer = new $renderingClass();
+               
+               // Check the class implements the right interface
+               if (!($renderer instanceof LoggerRenderer)) {
+                       trigger_error("log4php: Failed setting default renderer. Rendering class [$renderingClass] does not implement the LoggerRenderer interface.");
+                       return;
+               }
+               
+               $this->defaultRenderer = $renderer;
+       }
+       
+       /**
+        * Returns the default renderer.
+        * @var LoggerRenderer
+        */
+       public function getDefaultRenderer() {
+               return $this->defaultRenderer;
+       }
+       
+       /**
+        * Finds the appropriate renderer for the given <var>input</var>, and 
+        * renders it (i.e. converts it to a string). 
         *
-        * @param mixed $input
-        * @return string 
+        * @param mixed $input Input to render.
+        * @return string The rendered contents.
         */
        public function findAndRender($input) {
-               if($input == null) {
+               if ($input === null) {
                        return null;
-               } else {
-                       if(is_object($input)) {
-                               $renderer = $this->getByObject($input);
-                               if($renderer !== null) {
-                                       return $renderer->render($input);
-                               }
-
-                               return $this->defaultObjectRenderer->render($input);
-                       } else {
-                               $renderer = $this->defaultRenderer;
+               }
+               
+               // For objects, try to find a renderer in the map
+               if(is_object($input)) {
+                       $renderer = $this->getByClassName(get_class($input));
+                       if (isset($renderer)) {
                                return $renderer->render($input);
                        }
                }
+               
+               // Fall back to the default renderer
+               return $this->defaultRenderer->render($input);
        }
 
        /**
-        * Syntactic sugar method that calls {@link PHP_MANUAL#get_class} with the
-        * class of the object parameter.
+        * Returns the appropriate renderer for a given object.
         * 
         * @param mixed $object
-        * @return string
+        * @return LoggerRenderer Or null if none found.
         */
        public function getByObject($object) {
-               return ($object == null) ? null : $this->getByClassName(get_class($object));
+               if (!is_object($object)) {
+                       return null;
+               }
+               return $this->getByClassName(get_class($object));
        }
-
-
+       
        /**
-        * Search the parents of <var>clazz</var> for a renderer. 
-        *
-        * The renderer closest in the hierarchy will be returned. If no
-        * renderers could be found, then the default renderer is returned.
+        * Returns the appropriate renderer for a given class name.
+        * 
+        * If no renderer could be found, returns NULL.
         *
         * @param string $class
-        * @return LoggerRendererObject
+        * @return LoggerRendererObject Or null if not found.
         */
        public function getByClassName($class) {
                for(; !empty($class); $class = get_parent_class($class)) {
@@ -139,24 +172,15 @@ class LoggerRendererMap {
                return null;
        }
 
+       /** Empties the renderer map. */
        public function clear() {
                $this->map = array();
        }
-
-       /**
-        * Register a {@link LoggerRendererObject}.
-        * @param string $class Class which to render.
-        * @param LoggerRendererObject $renderer
-        */
-       private function put($class, $renderer) {
-               $this->map[strtolower($class)] = $renderer;
-       }
        
-       public function setDefaultObjectRenderer($renderer) {
-               $this->defaultObjectRenderer = $renderer;
-       }
-       
-       public function getDefaultObjectRenderer() {
-               return $this->defaultObjectRenderer;
+       /** Resets the renderer map to it's default configuration. */
+       public function reset() {
+               $this->defaultRenderer = new LoggerRendererDefault();
+               $this->clear();
+               $this->addRenderer('Exception', 'LoggerRendererException');
        }
 }
diff --git a/src/main/php/renderers/LoggerRendererObject.php b/src/main/php/renderers/LoggerRendererObject.php
deleted file mode 100644 (file)
index 0ad21d3..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php\r
-\r
-/**\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements. See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License. You may obtain a copy of the License at\r
- *\r
- *        http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *\r
- * @package log4php\r
- */\r
-\r
-/**\r
- * Default implementation of a renreder for objects.\r
- *   \r
- * @package log4php\r
- * @subpackage renderers\r
- * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0\r
- * @version $Revision$\r
- */\r
-class LoggerRendererObject implements LoggerRenderer {\r
-\r
-       public function render($o) {\r
-               return print_r($o, true);\r
-       }\r
-}\r
index 50bc2d4..3dda45e 100644 (file)
@@ -36,6 +36,7 @@
                                <p><strong>New features:</strong></p>\r
                                <ul>\r
                                        <li>New appender: <a href="docs/appenders/firephp.html">FirePHP</a> (thanks to Bruce Ingalls)</li>\r
+                                       <li>Ability to override the <a href="docs/renderers.html#Default_renderer">default renderer</a>.</li>\r
                                </ul>\r
                                \r
                                <p><strong>Improvements:</strong></p>\r
@@ -63,6 +64,8 @@
                                                access $_SERVER and $_ENV values using <code>%X{server.*}</code> and <code>%X{env.*}</code>\r
                                                conversion words; use the new words <code>%server{*}</code> and <code>%env{*}</code> instead.\r
                                                </li>\r
+                                       <li>Custom renderer classes should implement the <code>LoggerRenderer</code> interface instead of  \r
+                                               <code>LoggerRendererObject</code>.</li>\r
                                </ul>\r
                                <p>Please review the documentation and make any necessary changes to your configuration.</p>\r
                                \r
index 2aab8db..6c1b921 100644 (file)
@@ -35,7 +35,7 @@
 <pre class="prettyprint linenums"><![CDATA[\r
 class Person {\r
     public $firstName;\r
-    public $lastName;    \r
+    public $lastName;\r
     public $age;\r
 }\r
 ]]></pre>\r
@@ -57,24 +57,25 @@ $logger->info($person);
                                \r
 <pre class="prettyprint linenums"><![CDATA[\r
 INFO - Here comes the person:\r
-INFO - Person::__set_state(array(\r
-   'firstName' => 'John',\r
-   'lastName' => 'Doe',\r
-   'age' => 37,\r
-))\r
+INFO - Person Object\r
+(\r
+    [firstName] => John\r
+    [lastName] => Doe\r
+    [age] => 37\r
+)\r
 ]]></pre>\r
                                \r
                        </subsection>\r
                        \r
                        <subsection name="Creating a custom renderer">\r
-                               <p>In order to make log4php render our Person object in a more readable format, we need to create a \r
-                               custom renderer class which will convert Person objects to a string suitable for logging.</p>\r
+                               <p>In order to make log4php log the Person object in a more readable format, a custom renderer \r
+                               class can be defined which will convert Person objects to a string suitable for logging.</p>\r
                                \r
-                               <p>Let's call our renderer class PersonRenderer.</p>\r
+                               <p>Let's call this renderer class PersonRenderer.</p>\r
                                \r
 <pre class="prettyprint linenums"><![CDATA[\r
-/** All object renderers must implement the LoggerRendererObject interface. */\r
-class PersonRenderer implements LoggerRendererObject {\r
+/** All renderers must implement the LoggerRenderer interface. */\r
+class PersonRenderer implements LoggerRenderer {\r
     public function render($person) {\r
         return "{$person->firstName} {$person->lastName} ({$person->age})";\r
     }\r
@@ -83,9 +84,15 @@ class PersonRenderer implements LoggerRendererObject {
 \r
                                <p>Now log4php has to be configured to use PersonRenderer for rendering Person objects. This is done \r
                                in the configuration file.</p>\r
-                               \r
-                               <p>XML configuration:</p>\r
-                               \r
+\r
+                               <div class="auto-tabs">\r
+                                       <ul>\r
+                                               <li>XML</li>\r
+                                               <li>PHP</li>\r
+                                       </ul>\r
+                                       \r
+                                       <div class="tab-content">\r
+                                               <div class="tab-pane">\r
 <pre class="prettyprint linenums"><![CDATA[\r
 <configuration xmlns="http://logging.apache.org/log4php/">\r
     <renderer renderedClass="Person" renderingClass="PersonRenderer" />\r
@@ -95,14 +102,15 @@ class PersonRenderer implements LoggerRendererObject {
     </root>\r
 </configuration>\r
 ]]></pre>\r
-                               \r
-                               <p>Equivalent PHP configuration:</p>\r
-                               \r
+                                               </div>\r
+                                               <div class="tab-pane">\r
 <pre class="prettyprint linenums"><![CDATA[\r
 array(\r
     'renderers' => array(\r
-        'renderedClass' => 'Person',\r
-        'renderingClass' => 'PersonRenderer'\r
+        array(\r
+            'renderedClass' => 'Person',\r
+            'renderingClass' => 'PersonRenderer'\r
+        )\r
     ),\r
     'appenders' => array(\r
         'default' => array(\r
@@ -112,8 +120,12 @@ array(
     'rootLogger' => array(\r
         'appenders' => array('default'),\r
     ),\r
-);\r
+)\r
 ]]></pre>\r
+                                               </div>\r
+                                       </div>\r
+                               </div>\r
+                               \r
                        \r
                                <p>If the same code is run as above, the following output is produced:</p>\r
                        \r
@@ -124,6 +136,75 @@ INFO - John Doe (37)
                                <p>Which is much more readable than the default rendering.</p>\r
                        </subsection>\r
                        \r
+                       <subsection name="Overriding the default renderer">\r
+                               <p>It is possible to set your own custom renderer as the default renderer.</p>\r
+                               \r
+                               <p>For example, if you're not happy with the way in which the default renderer converts objects, \r
+                               you can create your own renderer:</p>\r
+                                  \r
+<pre class="prettyprint linenums"><![CDATA[\r
+class MyRenderer implements LoggerRenderer {\r
+    public function render($input) {\r
+        return var_dump($input);\r
+    }\r
+}\r
+]]></pre>\r
+\r
+                               <p>And set it as the default renderer in the configuration:</p>\r
+                               \r
+                               <div class="auto-tabs">\r
+                                       <ul>\r
+                                               <li>XML</li>\r
+                                               <li>PHP</li>\r
+                                       </ul>\r
+                                       \r
+                                       <div class="tab-content">\r
+                                               <div class="tab-pane">\r
+<pre class="prettyprint linenums"><![CDATA[\r
+<configuration xmlns="http://logging.apache.org/log4php/">\r
+    <defaultRenderer renderingClass="MyRenderer" />\r
+    <appender name="defualt" class="LoggerAppenderEcho" />\r
+    <root>\r
+        <appender_ref ref="defualt" />\r
+    </root>\r
+</configuration>\r
+]]></pre>\r
+                                               </div>\r
+                                               <div class="tab-pane">\r
+<pre class="prettyprint linenums"><![CDATA[\r
+array(\r
+    'defaultRenderer' => 'MyRenderer',\r
+    'appenders' => array(\r
+        'default' => array(\r
+            'class' => 'LoggerAppenderEcho',\r
+        ),\r
+    ),\r
+    'rootLogger' => array(\r
+        'appenders' => array('default'),\r
+    ),\r
+)\r
+]]></pre>\r
+                                               </div>\r
+                                       </div>\r
+                               </div>\r
+                               \r
+                               <p>Logging a Person object using this configuration will make log4php fall back to the newly \r
+                               defined default renderer, which uses <code>var_dump</code> instead of <code>print_r</code>, and \r
+                               the result will look like:</p>\r
+                                               \r
+<pre class="prettyprint linenums"><![CDATA[\r
+INFO - Here comes the person:\r
+class Person#5 (3) {\r
+  public $firstName =>\r
+  string(4) "John"\r
+  public $lastName =>\r
+  string(3) "Doe"\r
+  public $age =>\r
+  int(37)\r
+}\r
+]]></pre>\r
+                       </subsection>\r
+                       \r
                        <subsection name="Class hierarchy">\r
                                <p>Object rendering follows the class hierarchy. </p>\r
 \r
index d82e03c..e8ff410 100644 (file)
@@ -185,7 +185,7 @@ class CostumDefaultRenderer implements LoggerRenderer {
 \r
     /**\r
         * @expectedException PHPUnit_Framework_Error\r
-        * @expectedExceptionMessage Invalid class [stdClass] given. Not a valid LoggerRenderer class. Skipping renderers definition.\r
+        * @expectedExceptionMessage Failed adding renderer. Rendering class [stdClass] does not implement the LoggerRenderer interface.\r
         */\r
        public function testInvalidRenderingClassSet() {\r
                Logger::configure(PHPUNIT_CONFIG_DIR . '/renderers/config_invalid_rendering_class.xml');\r
@@ -193,7 +193,7 @@ class CostumDefaultRenderer implements LoggerRenderer {
        \r
     /**\r
         * @expectedException PHPUnit_Framework_Error\r
-        * @expectedExceptionMessage Rendering class not specified. Skipping renderers definition.\r
+        * @expectedExceptionMessage Rendering class not specified. Skipping renderer definition.\r
         */\r
        public function testNoRenderingClassSet() {\r
                Logger::configure(PHPUNIT_CONFIG_DIR . '/renderers/config_no_rendering_class.xml');\r
@@ -201,23 +201,15 @@ class CostumDefaultRenderer implements LoggerRenderer {
 \r
     /**\r
         * @expectedException PHPUnit_Framework_Error\r
-        * @expectedExceptionMessage Rendered class not specified for rendering Class [LoggerRendererDefault]. Skipping renderers definition.\r
+        * @expectedExceptionMessage Rendered class not specified. Skipping renderer definition.\r
         */\r
        public function testNoRenderedClassSet() {\r
                Logger::configure(PHPUNIT_CONFIG_DIR . '/renderers/config_no_rendered_class.xml');\r
        }       \r
        \r
-     /**\r
-        * @expectedException PHPUnit_Framework_Error\r
-        * @expectedExceptionMessage Nonexistant rendered class [RenderFooClass] specified for renderer [LoggerRendererDefault]. Skipping renderers definition.\r
-        */\r
-       public function testNotExistingRenderedClassSet() {\r
-               Logger::configure(PHPUNIT_CONFIG_DIR . '/renderers/config_not_existing_rendered_class.xml');\r
-       }       \r
-       \r
        /**\r
         * @expectedException PHPUnit_Framework_Error\r
-        * @expectedExceptionMessage Nonexistant rendering class [FooRenderer] specified. Skipping renderers definition.\r
+        * @expectedExceptionMessage Failed adding renderer. Rendering class [DoesNotExistRenderer] not found.\r
         */\r
        public function testNotExistingRenderingClassSet() {\r
                Logger::configure(PHPUNIT_CONFIG_DIR . '/renderers/config_not_existing_rendering_class.xml');\r
@@ -457,33 +449,4 @@ class CostumDefaultRenderer implements LoggerRenderer {
                        ) \r
                ));\r
        }\r
-       \r
-       public function testConfigureRenderer_ShouldReturnBuildInObjectRenderer() {\r
-               Logger::configure(array(\r
-                       'rootLogger' => array(\r
-                               'appenders' => array('default')\r
-                       ),\r
-                       'appenders' => array(\r
-                               'default' => array(\r
-                                       'class' => 'LoggerAppenderEcho',\r
-                                       'threshold' => 'INFO'\r
-                               ),\r
-                       ) \r
-               ));\r
-                       \r
-               $actualDefaultObjectRenderer = Logger::getHierarchy()->getRendererMap()->getDefaultObjectRenderer();\r
-               \r
-               $this->assertTrue($actualDefaultObjectRenderer instanceof LoggerRendererObject, 'build in object renderer');\r
-       }       \r
-       \r
-       public function testConfigureRenderer_SetupCostumDefaultObjectRenderer() {\r
-               Logger::configure(array(\r
-                       'renderers' => array(\r
-                                       array('defaultObjectRenderer' => 'CostumDefaultRenderer')\r
-                       )));\r
-               \r
-               $actualCostumObjectRenderer = Logger::getHierarchy()->getRendererMap()->getDefaultObjectRenderer();\r
-               \r
-               $this->assertNotNull($actualCostumObjectRenderer, 'costum default object renderer');\r
-       }\r
  }
\ No newline at end of file
diff --git a/src/test/php/renderers/LoggerRendererDefaultTest.php b/src/test/php/renderers/LoggerRendererDefaultTest.php
deleted file mode 100644 (file)
index 66e915c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * @category   tests   
- * @package    log4php
- * @subpackage renderers
- * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
- * @version    $Revision$
- * @link       http://logging.apache.org/log4php
- */
-
-class DefaultRendererMockObject {
-       private $a;
-       protected $b;
-       public $c;
-}
-
-/**
- * @group renderers
- */
-class LoggerRendererDefaultTest extends PHPUnit_Framework_TestCase {
-
-       public function testDoRender() {
-               $class = new DefaultRendererMockObject();
-               $renderer = new LoggerRendererDefault();
-               self::assertEquals(var_export($class, true), $renderer->render($class));
-       }
-
-}
diff --git a/src/test/php/renderers/LoggerRendererExceptionTest.php b/src/test/php/renderers/LoggerRendererExceptionTest.php
deleted file mode 100644 (file)
index d612228..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * @category   tests   
- * @package    log4php
- * @subpackage renderers
- * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
- * @version    $Revision$
- * @link       http://logging.apache.org/log4php
- */
-
-/**
- * @group renderers
- */
-class LoggerRendererExceptionTest extends PHPUnit_Framework_TestCase {
-       
-       public function testRender() {
-               $exRenderer = new LoggerRendererException();
-               $ex1            = new LoggerRendererExceptionTestException('Message1');
-               $ex2            = new LoggerRendererExceptionTestException('Message2', 0, $ex1);
-               $ex3            = new LoggerRendererExceptionTestException('Message3', 0, $ex2);
-               
-        $rendered   = $exRenderer->render($ex3);
-        
-               $expected       = 3;        
-               $result         = substr_count($rendered, 'Throwable(LoggerRendererExceptionTestException): Message');          
-               $this->assertEquals($expected, $result);                
-        
-        $expected   = 2;        
-        $result     = substr_count($rendered, 'Caused by: Throwable(LoggerRendererExceptionTestException):');        
-        $this->assertEquals($expected, $result);
-        
-        $expected   = 1;        
-        $result     = substr_count($rendered, 'Caused by: Throwable(LoggerRendererExceptionTestException): Message2');        
-        $this->assertEquals($expected, $result);
-
-        $expected   = 1;        
-        $result     = substr_count($rendered, 'Caused by: Throwable(LoggerRendererExceptionTestException): Message1');        
-        $this->assertEquals($expected, $result);                
-       }
-}
-
-if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
-       class LoggerRendererExceptionTestException extends Exception { }
-} else {
-       class LoggerRendererExceptionTestException extends Exception {
-               
-               protected $previous;
-               
-               public function __construct($message = '', $code = 0, Exception $previous = null) {
-                       parent::__construct($message, $code);
-                       $this->previous = $previous;
-               }
-               
-               public function getPrevious() {
-                       return $this->previous;
-               }        
-       }
-}
-?>
\ No newline at end of file
index f3f2c1c..030f4b5 100644 (file)
  * @link       http://logging.apache.org/log4php
  */
 
-class CostumObjectRenderer implements LoggerRenderer {
-       public function render($o) {
-               return true;
+/** Renders everything as 'foo'. */
+class FooRenderer implements LoggerRenderer {
+       public function render($input) {
+               return 'foo';
        }
 }
 
+class InvalidCostumObjectRenderer { }
+
 class Fruit3 {
     public $test1 = 'test1';
     public $test2 = 'test2';
@@ -39,84 +42,202 @@ class Fruit3Descendant extends Fruit3 {
 }
 
 class FruitRenderer3 implements LoggerRenderer {
-    public function render($o) {
-               return $o->test1.','.$o->test2.','.$o->test3;
+    public function render($fruit) {
+               return $fruit->test1 . ',' . $fruit->test2 . ',' . $fruit->test3;
        }
 }
 
 class SampleObject {
-       
 }
 
 /**
  * @group renderers
  */
 class LoggerRendererMapTest extends PHPUnit_Framework_TestCase {
-        
-       public function testFindAndRender() {
-               $fruit = new Fruit3();
-               Logger::configure(dirname(__FILE__).'/test4.properties');
-               $hierarchy = Logger::getHierarchy();
-               
-               $map = $hierarchy->getRendererMap();
-               $e = $map->findAndRender($fruit);
-               self::assertEquals('test1,test2,test3', $e);
-       }
-        
-       public function testFindAndRenderDescendants() {
-               $fruit = new Fruit3Descendant();
-               Logger::configure(dirname(__FILE__).'/test4.properties');
-               $hierarchy = Logger::getHierarchy();
 
-               $map = $hierarchy->getRendererMap();
-               $e = $map->findAndRender($fruit);
-               self::assertEquals('test1,test2,test3', $e);
+       public function testDefaults() {
+               
+               $map = new LoggerRendererMap();
+               $actual = $map->getByClassName('Exception');
+               self::assertInstanceOf('LoggerRendererException', $actual);
+               
+               // Check non-configured objects return null
+               self::assertNull($map->getByObject(new stdClass()));
+               self::assertNull($map->getByClassName('stdClass'));
+       }
+       
+       public function testClear() 
+       {
+               $map = new LoggerRendererMap();
+               $map->clear(); // This should clear the map and remove default renderers
+               self::assertNull($map->getByClassName('Exception'));
        }
+       
+       public function testFindAndRender() 
+       {
+               $map = new LoggerRendererMap();
+               $map->addRenderer('Fruit3', 'FruitRenderer3');
 
-       public function testGetByObject() {
                $fruit = new Fruit3();
-               Logger::configure(dirname(__FILE__).'/test4.properties');
-               $hierarchy = Logger::getHierarchy();
-               
-               $map = $hierarchy->getRendererMap();
-               $e = $map->getByObject($fruit);
-               self::assertTrue($e instanceof FruitRenderer3);
-       }
-        
-       public function testGetByClassName() {
-               Logger::configure(dirname(__FILE__).'/test4.properties');
-               $hierarchy = Logger::getHierarchy();
-               
-               $map = $hierarchy->getRendererMap();
-               $e = $map->getByClassName('Fruit3');
-               self::assertTrue($e instanceof FruitRenderer3);
-       }
-       
-       public function testUsage() {
-           Logger::resetConfiguration();
-        Logger::configure(dirname(__FILE__).'/test4.properties');
-        $logger = Logger::getRootLogger();
-        ob_start();
-        $logger->warn(new Fruit3());
-        $actual = ob_get_contents();
-        ob_end_clean();
-
-        $expected = "WARN - test1,test2,test3" . PHP_EOL;
-        self::assertEquals($expected, $actual);
+               $descendant = new Fruit3Descendant();
+               
+               // Check rendering of fruit
+               $actual = $map->findAndRender($fruit);
+               $expected = 'test1,test2,test3';
+               self::assertSame($expected, $actual);
+               
+               $actual = $map->getByObject($fruit);
+               self::assertInstanceOf('FruitRenderer3', $actual);
+               
+               // Check rendering of fruit's descendant
+               $actual = $map->findAndRender($descendant);
+               $expected = 'test1,test2,test3';
+               self::assertSame($expected, $actual);
+               
+               $actual = $map->getByObject($descendant);
+               self::assertInstanceOf('FruitRenderer3', $actual);
+               
+               // Test rendering null returns null
+               self::assertNull($map->findAndRender(null));
+       }
+       
+       /**
+        * Try adding a non-existant class as renderer.
+        * @expectedException PHPUnit_Framework_Error
+        * @expectedExceptionMessage Failed adding renderer. Rendering class [DoesNotExist] not found.
+        */
+       public function testAddRendererError1() 
+       {
+               $map = new LoggerRendererMap();
+               $map->addRenderer('Fruit3', 'DoesNotExist');
+       }
+       
+       /**
+        * Try adding a class which does not implement LoggerRenderer as renderer.
+        * @expectedException PHPUnit_Framework_Error
+        * @expectedExceptionMessage Failed adding renderer. Rendering class [stdClass] does not implement the LoggerRenderer interface.
+        */
+       public function testAddRendererError2() 
+       {
+               $map = new LoggerRendererMap();
+               $map->addRenderer('Fruit3', 'stdClass');
+       }
+       
+       public function testAddRendererError3() 
+       {
+               $map = new LoggerRendererMap();
+               @$map->addRenderer('Fruit3', 'stdClass');
+               self::assertNull($map->getByClassName('Fruit3'));
+               
+               @$map->addRenderer('Fruit3', 'DoesNotExist');
+               self::assertNull($map->getByClassName('Fruit3'));
+       }
+       
+       /**
+        * Try setting a non-existant class as default renderer.
+        * @expectedException PHPUnit_Framework_Error
+        * @expectedExceptionMessage Failed setting default renderer. Rendering class [DoesNotExist] not found.
+        */
+       public function testSetDefaultRendererError1() 
+       {
+               $map = new LoggerRendererMap();
+               $map->setDefaultRenderer('DoesNotExist');
+       }
+       
+       /**
+        * Try setting a class which does not implement LoggerRenderer as default renderer.
+        * @expectedException PHPUnit_Framework_Error
+        * @expectedExceptionMessage Failed setting default renderer. Rendering class [stdClass] does not implement the LoggerRenderer interface.
+        */
+       public function testSetDefaultRendererError2()
+       {
+               $map = new LoggerRendererMap();
+               $map->setDefaultRenderer('stdClass');
+       }
+       
+       public function testSetDefaultRendererError3()
+       {
+               $map = new LoggerRendererMap();
+               $expected =  $map->getDefaultRenderer();
+               
+               @$map->setDefaultRenderer('stdClass');
+               $actual = $map->getDefaultRenderer();
+               self::assertSame($expected, $actual);
+       
+               @$map->setDefaultRenderer('DoesNotExist');
+               $actual = $map->getDefaultRenderer();
+               self::assertSame($expected, $actual);
+       }
+       
+       public function testFetchingRenderer() 
+       {
+               $map = new LoggerRendererMap();
+               $map->addRenderer('Fruit3', 'FruitRenderer3');
+       }
+       
+       public function testDefaultRenderer() 
+       {
+               $fruit = new Fruit3();
+               
+               $map = new LoggerRendererMap();
+               $actual = $map->findAndRender($fruit);
+               
+               $defaultRenderer = new LoggerRendererDefault();
+               $expected = $defaultRenderer->render($fruit);
+               self::assertSame($expected, $actual);
        }
        
-       public function testGetByObject_CostumRendererShouldRenderObject() {
-               $sampleObject = new SampleObject();
+       public function testOverrideDefaultRenderer() 
+       {
+               $map = new LoggerRendererMap();
+               $default = $map->getDefaultRenderer();
                
-               Logger::configure(dirname(__FILE__).'/test4.properties');
-               $hierarchy = Logger::getHierarchy();
+               $array = array(1, 2, 3);
                
-               $map = $hierarchy->getRendererMap();
-               $map->setDefaultObjectRenderer(new CostumObjectRenderer());
+               $actual = $map->findAndRender($array);
+               $expected = print_r($array, true);
+               self::assertSame($actual, $expected);
                
-               $actual = $map->findAndRender($sampleObject);
+               // Now switch the default renderer
+               $map->setDefaultRenderer('FooRenderer');
+               $actual = $map->findAndRender($array);
+               $expected = 'foo';
+               self::assertSame($actual, $expected);
+       }
+
+       public function testGetByObjectCrap()
+       {
+               $map = new LoggerRendererMap();
+               
+               // Non object input should always return null
+               self::assertNull($map->getByObject(null));
+               self::assertNull($map->getByObject(array()));
+               self::assertNull($map->getByObject('sdasda'));
+       }
+       
+       public function testXMLConfig() 
+       {
+               $map = Logger::getHierarchy()->getRendererMap();
+               Logger::resetConfiguration();
+               self::assertInstanceOf('LoggerRendererDefault', $map->getDefaultRenderer());
+               
+               Logger::configure(PHPUNIT_CONFIG_DIR . '/renderers/config_default_renderer.xml');
+               self::assertInstanceOf('FruitRenderer3', $map->getDefaultRenderer());
                
-               $this->assertTrue($actual, 'costumobjectrenderer was rendered object');
+               Logger::resetConfiguration();
+               self::assertInstanceOf('LoggerRendererDefault', $map->getDefaultRenderer());
        }
+       
+       public function testExceptionRenderer() 
+       {
+               $ex = new LoggerException("This is a test");
+               
+               $map = new LoggerRendererMap();
+               $actual = $map->findAndRender($ex);
+               $expected = (string) $ex;
+
+               self::assertSame($expected, $actual);
+       }
+       
+       
 }
diff --git a/src/test/php/renderers/LoggerRendererObjectTest.php b/src/test/php/renderers/LoggerRendererObjectTest.php
deleted file mode 100644 (file)
index 090c148..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php\r
-/**\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * \r
- * @category   tests   \r
- * @package    log4php\r
- * @subpackage renderers\r
- * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0\r
- * @version    $Revision$\r
- * @link       http://logging.apache.org/log4php\r
- */\r
-\r
-class DefaultObject {\r
-       private $a;\r
-       protected $b;\r
-       public $c;\r
-}\r
-\r
-/**\r
- * @group renderers\r
- */\r
-class LoggerRendererObjectTest extends PHPUnit_Framework_TestCase {\r
-\r
-       public function testDoRender() {\r
-               $class = new DefaultObject();\r
-               $renderer = new LoggerRendererObject();\r
-               self::assertEquals(print_r($class, true), $renderer->render($class));\r
-       }\r
-\r
-}\r
diff --git a/src/test/php/renderers/test4.properties b/src/test/php/renderers/test4.properties
deleted file mode 100644 (file)
index 16acb2a..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one or more
-; contributor license agreements.  See the NOTICE file distributed with
-; this work for additional information regarding copyright ownership.
-; The ASF licenses this file to You under the Apache License, Version 2.0
-; (the "License"); you may not use this file except in compliance with
-; the License.  You may obtain a copy of the License at
-; 
-;      http://www.apache.org/licenses/LICENSE-2.0
-; 
-; Unless required by applicable law or agreed to in writing, software
-; distributed under the License is distributed on an "AS IS" BASIS,
-; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-; See the License for the specific language governing permissions and
-; limitations under the License.
-;
-log4php.renderer.Fruit3=FruitRenderer3
-
-log4php.appender.default = LoggerAppenderEcho
-log4php.appender.default.layout = LoggerLayoutSimple
-log4php.appender.default.threshold = WARN
-
-log4php.appender.rendr2 = LoggerAppenderEcho
-log4php.appender.rendr2.layout = LoggerLayoutSimple
-log4php.appender.rendr2.threshold = ERROR
-
-log4php.threshold = WARN
-log4php.rootLogger = WARN, default, rendr2
  limitations under the License.\r
 -->\r
 <configuration xmlns="http://logging.apache.org/log4php">\r
-    <appender name="foo" class="LoggerAppenderConsole">\r
-        <layout class="LoggerLayoutSimple"/>\r
-    </appender>\r
+    <appender name="foo" class="LoggerAppenderConsole" />\r
     \r
-    <renderer renderedClass="RenderFooClass" renderingClass="LoggerRendererDefault" />\r
+    <defaultRenderer renderingClass="FruitRenderer3"  />\r
     \r
     <root>\r
         <level value="DEBUG" />\r
index fa73181..8a32d3e 100644 (file)
@@ -20,7 +20,7 @@
         <layout class="LoggerLayoutSimple"/>\r
     </appender>\r
     \r
-    <renderer renderedClass="stdClass" renderingClass="FooRenderer" />\r
+    <renderer renderedClass="stdClass" renderingClass="DoesNotExistRenderer" />\r
     \r
     <root>\r
         <level value="DEBUG" />\r