PHP code
  1. <?php
  2. /**
  3.  * Copyright (c) 2009, Laurent Laville <pear@laurent-laville.org>
  4.  *
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  *     * Redistributions of source code must retain the above copyright
  12.  *       notice, this list of conditions and the following disclaimer.
  13.  *     * Redistributions in binary form must reproduce the above copyright
  14.  *       notice, this list of conditions and the following disclaimer in the
  15.  *       documentation and/or other materials provided with the distribution.
  16.  *     * Neither the name of the authors nor the names of its contributors
  17.  *       may be used to endorse or promote products derived from this software
  18.  *       without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  24.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * PHP version 5
  33.  *
  34.  * @category PEAR
  35.  * @package  PEAR_TestListener
  36.  * @author   Laurent Laville <pear@laurent-laville.org>
  37.  * @license  http://www.opensource.org/licenses/bsd-license.php  BSD
  38.  * @version  CVS: $Id:$
  39.  * @link     http://pear.laurent-laville.org/pepr/PEAR_TestListener
  40.  * @since    File available since Release 0.3.0a1
  41.  */
  42.  
  43. require_once 'PHPUnit/Util/Configuration.php';
  44.  
  45. PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
  46.  
  47. /**
  48.  * Wrapper for the PHPUnit XML configuration file.
  49.  *
  50.  * @category PEAR
  51.  * @package  PEAR_TestListener
  52.  * @author   Laurent Laville <pear@laurent-laville.org>
  53.  * @license  http://www.opensource.org/licenses/bsd-license.php  BSD
  54.  * @version  Release: @package_version@
  55.  * @link     http://pear.laurent-laville.org/pepr/PEAR_TestListener
  56.  * @since    Class available since Release 0.3.0a1
  57.  */
  58. class PEAR_TestListener_Configuration extends PHPUnit_Util_Configuration
  59. {
  60.     /**
  61.      * Instances of PEAR_TestListener_Configuration for each XML configuration file
  62.      *
  63.      * @var array
  64.      */
  65.     private static $_instances = array();
  66.  
  67.     /**
  68.      * Loads a PHPUnit configuration file.
  69.      *
  70.      * @param string $filename XML configuration filename
  71.      */
  72.     public function __construct($filename)
  73.     {
  74.         parent::__construct($filename);
  75.     }
  76.  
  77.     /**
  78.      * Returns a PHPUnit configuration object.
  79.      *
  80.      * @param string $filename XML configuration filename
  81.      *
  82.      * @return PEAR_TestListener_Configuration
  83.      */
  84.     public static function getInstance($filename)
  85.     {
  86.         $realpath = realpath($filename);
  87.  
  88.         if ($realpath === false) {
  89.             throw new RuntimeException(
  90.                 sprintf('Could not read "%s".', $filename)
  91.             );
  92.         }
  93.  
  94.         if (!isset(self::$_instances[$realpath])) {
  95.             self::$_instances[$realpath]
  96.                 = new PEAR_TestListener_Configuration($realpath);
  97.         }
  98.  
  99.         return self::$_instances[$realpath];
  100.     }
  101.  
  102.     /**
  103.      * Returns the logger configuration.
  104.      *
  105.      * @return array
  106.      */
  107.     public function getLoggerConfiguration()
  108.     {
  109.         $priorities = 'all|debug|info|notice|warning|error|critical|alert|emergency';
  110.         $mPattern   = '/(MASK|MAX|MIN)?\s*'
  111.                     .'('.$priorities.')+\s*'
  112.                     .'(\&|\||\^)?\s*'
  113.                     .'('.$priorities.')?'
  114.                     .'/i';
  115.  
  116.         $result = array();
  117.  
  118.         foreach ($this->xpath->query('loggers') as $logger) {
  119.  
  120.             if ($logger->childNodes->item(1) instanceof DOMElement) {
  121.                 foreach ($logger->childNodes as $handler) {
  122.                     if ($handler instanceof DOMElement) {
  123.                         $_children = array();
  124.                         $conf      = array();
  125.                         switch ($handler->tagName) {
  126.                         case 'composite' :
  127.                             if ($handler->childNodes->item(1)
  128.                                 instanceof DOMElement
  129.                             ) {
  130.                                 foreach ($handler->childNodes as $child) {
  131.                                     if ($child instanceof DOMElement) {
  132.                                         $ident
  133.                                             = (string)$child->getAttribute('ident');
  134.                                         if (!empty($ident)) {
  135.                                             $_children[$ident] = $child->tagName;
  136.                                         }
  137.                                     }
  138.                                 }
  139.                             }
  140.                             $ident = $name = $level = $mask = '';
  141.                             break;
  142.                         case 'file' :
  143.                         case 'mail' :
  144.                         case 'sqlite' :
  145.                             $ident = (string)$handler->getAttribute('ident');
  146.                             $name  = (string)$handler->getAttribute('name');
  147.                             if (empty($ident) || empty($name)) {
  148.                                 // misconfiguring file handler, skip this entry
  149.                                 continue 2;
  150.                             }
  151.                             $level = (string)$handler->getAttribute('level');
  152.                             $mask  = (string)$handler->getAttribute('mask');
  153.                             if (preg_match($mPattern, $mask, $matches)) {
  154.                                 $mask = $this->logMaskAdapter($matches);
  155.                                 if ($mask === false) {
  156.                                     // mask error, skip this entry
  157.                                     continue 2;
  158.                                 }
  159.                             }
  160.                             $cleanId = str_replace(' ', '_', $ident);
  161.                             $name    = str_replace(
  162.                                 array('%Y', '%M', '%D', '%I'),
  163.                                 array(date('Y'), date('m'), date('d'), $cleanId),
  164.                                 $name
  165.                             );
  166.                             break;
  167.                         case 'null' :
  168.                             $ident = (string)$handler->getAttribute('ident');
  169.                             $name  = $level = '';
  170.                             break;
  171.                         }
  172.  
  173.                         // common conf option for all handlers
  174.                         if ($handler->childNodes->item(1) instanceof DOMElement) {
  175.                             foreach ($handler->childNodes as $cfg) {
  176.                                 if ($cfg instanceof DOMElement) {
  177.                                     if ($cfg->tagName == 'conf') {
  178.                                         if ($cfg->childNodes->item(1)
  179.                                             instanceof DOMElement
  180.                                         ) {
  181.                                             foreach ($cfg->childNodes as $option) {
  182.                                                 if ($option instanceof DOMElement) {
  183.                                                     $conf[$option->tagName]
  184.                                                         = $option->nodeValue;
  185.                                                 }
  186.                                             }
  187.                                         }
  188.                                     }
  189.                                 }
  190.                             }
  191.                             if (isset($conf['filename'])) {
  192.                                 // only sqlite handler used it
  193.                                
  194.                                 $conf['filename'] = str_replace(
  195.                                     array('%Y','%M','%D', '%I'),
  196.                                     array(date('Y'), date('m'), date('d'), $cleanId),
  197.                                     $conf['filename']
  198.                                 );
  199.                             }
  200.                         }
  201.  
  202.                         if (empty($level)) {
  203.                             $level = 'debug';
  204.                         }
  205.  
  206.                         $result[] = array(
  207.                             'type'  => $handler->tagName,
  208.                             'name'  => $name,
  209.                             'ident' => $ident,
  210.                             'conf'  => $conf,
  211.                             'level' => $level,
  212.                             'mask'  => $mask,
  213.                             '_children' => $_children
  214.                         );
  215.                     }
  216.                 }
  217.             }
  218.         }
  219.         return $result;
  220.     }
  221.  
  222.     /**
  223.      * Compute a complex mask
  224.      *
  225.      * To compute the mask for a specific level, use for example:  MASK notice
  226.      *
  227.      * To compute the mask for all priorities up to, and including error level,
  228.      * use:  MAX error
  229.      *
  230.      * To compute the mask for all priorities greater than or equal to a warning
  231.      * level, use:  MIN warning
  232.      *
  233.      * Masks can be be combined using bitwise operations like:
  234.      *  all ^ info
  235.      *  info & notice
  236.      *  error | warning
  237.      *
  238.      * @param array $matches complex mask condition matches
  239.      *
  240.      * @return mixed The current level mask, or FALSE on mask definition error
  241.      */
  242.     protected function logMaskAdapter($matches)
  243.     {
  244.         if (!empty($matches[1])) {
  245.             // MASK, MIN or MAX
  246.             if (!empty($matches[3]) || !empty($matches[4])) {
  247.                 // mask error
  248.                 return false;
  249.             }
  250.             $minMAX = strtoupper($matches[1]);
  251.             $priority = Log::stringToPriority(strtolower($matches[2]));
  252.             $mask = Log::$minMAX($priority);
  253.         } elseif (!empty($matches[3])) {
  254.             // bitwise operator
  255.             if (empty($matches[2]) || empty($matches[4])) {
  256.                 // mask error
  257.                 return false;
  258.             }
  259.             if ($matches[2] == 'all') {
  260.                 $p1 = PEAR_LOG_ALL;
  261.             } else {
  262.                 $p1 = Log::stringToPriority(strtolower($matches[2]));
  263.                 $p1 = Log::MASK($p1);
  264.             }
  265.             if ($matches[4] == 'all') {
  266.                 $p2 = PEAR_LOG_ALL;
  267.             } else {
  268.                 $p2 = Log::stringToPriority(strtolower($matches[4]));
  269.                 $p2 = Log::MASK($p2);
  270.             }
  271.             switch ($matches[3]) {
  272.             case '^':
  273.                 $mask = $p1 ^ $p2;
  274.                 break;
  275.             case '&':
  276.                 $mask = $p1 & $p2;
  277.                 break;
  278.             case '|':
  279.                 $mask = $p1 | $p2;
  280.                 break;
  281.             }
  282.         } else {
  283.             // mask error
  284.             return false;
  285.         }
  286.         $mask = dechex($mask);
  287.         return $mask;
  288.     }
  289. }
  290. ?>
generated by Generic Syntax Highlighter - GeSHi