Overview

Namespaces

  • GAubry
    • ErrorHandler
    • Helpers
    • Logger
    • Shell
  • Himedia
    • Padocc
      • DB
      • Minifier
      • Numbering
      • Properties
      • Task
        • Base
        • Extended
  • None
  • Psr
    • Log

Classes

  • AbstractLogger
  • ColoredIndentedLogger
  • MinimalLogger
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: 
  3: namespace GAubry\Logger;
  4: 
  5: use GAubry\Helpers\Helpers;
  6: use Psr\Log\LogLevel;
  7: 
  8: /**
  9:  * PSR-3 logger for adding colors and indentation on PHP CLI output.
 10:  *
 11:  * Use tags and placeholder syntax to provide an easy way to color and indent PHP CLI output.
 12:  * PSR-3 compatibility allows graceful degradation when switching to another PSR-3 compliant logger.
 13:  * See README.md for more information.
 14:  *
 15:  * Copyright (c) 2013 Geoffroy Aubry <geoffroy.aubry@free.fr>
 16:  * Licensed under the GNU Lesser General Public License v3 (LGPL version 3).
 17:  *
 18:  * @copyright 2013 Geoffroy Aubry <geoffroy.aubry@free.fr>
 19:  * @license http://www.gnu.org/licenses/lgpl.html
 20:  * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 21:  */
 22: class ColoredIndentedLogger extends AbstractLogger
 23: {
 24:     /**
 25:      * Length of the indent tag.
 26:      * @var int
 27:      * @see 'indent_tag' key of ColoredIndentedLogger::$aDefaultConfig
 28:      */
 29:     private $iIndentTagLength;
 30: 
 31:     /**
 32:      * Length of the unindent tag.
 33:      * @var int
 34:      * @see 'unindent_tag' key of ColoredIndentedLogger::$aDefaultConfig
 35:      */
 36:     private $iUnindentTagLength;
 37: 
 38:     /**
 39:      * Current zero-based indentation level.
 40:      * @var int
 41:      */
 42:     private $iIndentationLevel;
 43: 
 44:     /**
 45:      * Full length color tags combining prefix to user define colors.
 46:      * @var array
 47:      * @see ColoredIndentedLogger::buildColorTags()
 48:      * @see 'color_tag_prefix' key of ColoredIndentedLogger::$aDefaultConfig
 49:      */
 50:     private $aColorTags;
 51: 
 52:     /**
 53:      * Default configuration.
 54:      *   – 'colors'               => (array) Array of key/value pairs to associate bash color codes to color tags.
 55:      *                                       Example: array(
 56:      *                                           'debug'   => "\033[0;30m",
 57:      *                                           'warning' => "\033[0;33m",
 58:      *                                           'error'   => "\033[1;31m"
 59:      *                                       )
 60:      *   – 'base_indentation'     => (string) Describe what is a simple indentation, e.g. "\t".
 61:      *   – 'indent_tag'           => (string) Tag usable at the start or at the end of the message to add
 62:      *                                        one or more indentation level.
 63:      *   – 'unindent_tag'         => (string) Tag usable at the start or at the end of the message to remove
 64:      *                                        one or more indentation level.
 65:      *   – 'min_message_level'    => (string) Threshold required to log message, must be defined in \Psr\Log\LogLevel.
 66:      *   – 'reset_color_sequence' => (string) Concatenated sequence at the end of message when colors are used.
 67:      *                                        For example: "\033[0m".
 68:      *   – 'color_tag_prefix'     => (string) Prefix used in placeholders to distinguish standard context from colors.
 69:      *
 70:      * @var array
 71:      */
 72:     private static $aDefaultConfig = array(
 73:         'colors'               => array(),
 74:         'base_indentation'     => "\033[0;30m┆\033[0m   ",
 75:         'indent_tag'           => '+++',
 76:         'unindent_tag'         => '---',
 77:         'min_message_level'    => LogLevel::DEBUG,
 78:         'reset_color_sequence' => "\033[0m",
 79:         'color_tag_prefix'     => 'C.'
 80:     );
 81: 
 82:     /**
 83:      * Current configuration.
 84:      * @var array
 85:      * @see ColoredIndentedLogger::$aDefaultConfig
 86:      */
 87:     private $aConfig;
 88: 
 89:     /**
 90:      * Constructor.
 91:      *
 92:      * @param array $aConfig see self::$aDefaultConfig
 93:      * @throws \Psr\Log\InvalidArgumentException if calling this method with a level not defined in \Psr\Log\LogLevel
 94:      */
 95:     public function __construct (array $aConfig = array())
 96:     {
 97:         $this->aConfig = Helpers::arrayMergeRecursiveDistinct(self::$aDefaultConfig, $aConfig);
 98:         parent::__construct($this->aConfig['min_message_level']);
 99: 
100:         $this->iIndentTagLength = strlen($this->aConfig['indent_tag']);
101:         $this->iUnindentTagLength = strlen($this->aConfig['unindent_tag']);
102:         $this->iIndentationLevel = 0;
103:         $this->buildColorTags();
104:     }
105: 
106:     /**
107:      * Build full length color tags by adding prefix to user define colors.
108:      * @see ColoredIndentedLogger::aColorTags
109:      * @see 'color_tag_prefix' key of ColoredIndentedLogger::$aDefaultConfig
110:      */
111:     private function buildColorTags ()
112:     {
113:         $this->aColorTags = array();
114:         foreach ($this->aConfig['colors'] as $sRawName => $sSequence) {
115:             $sName = '{' . $this->aConfig['color_tag_prefix'] . $sRawName . '}';
116:             $this->aColorTags[$sName] = $sSequence;
117:         }
118:     }
119: 
120:     /**
121:      * Update indentation level according to leading indentation tags
122:      * and remove them from the returned string.
123:      *
124:      * @param string $sMessage
125:      * @return string specified message without any leading indentation tag
126:      * @see ColoredIndentedLogger::iIndentationLevel
127:      */
128:     private function processLeadingIndentationTags ($sMessage)
129:     {
130:         $bTagFound = true;
131:         while ($bTagFound && strlen($sMessage) > 0) {
132:             if (substr($sMessage, 0, $this->iIndentTagLength) == $this->aConfig['indent_tag']) {
133:                 $this->iIndentationLevel++;
134:                 $sMessage = substr($sMessage, $this->iIndentTagLength);
135:             } elseif (substr($sMessage, 0, $this->iUnindentTagLength) == $this->aConfig['unindent_tag']) {
136:                 $this->iIndentationLevel = max(0, $this->iIndentationLevel-1);
137:                 $sMessage = substr($sMessage, $this->iUnindentTagLength);
138:             } else {
139:                 $bTagFound = false;
140:             }
141:         }
142:         return $sMessage;
143:     }
144: 
145:     /**
146:      * Update indentation level according to trailing indentation tags
147:      * and remove them from the returned string.
148:      *
149:      * @param string $sMessage
150:      * @return string specified message without any trailing indentation tag
151:      * @see ColoredIndentedLogger::iIndentationLevel
152:      */
153:     private function processTrailingIndentationTags ($sMessage)
154:     {
155:         $bTagFound = true;
156:         while ($bTagFound && strlen($sMessage) > 0) {
157:             if (substr($sMessage, -$this->iIndentTagLength) == $this->aConfig['indent_tag']) {
158:                 $this->iIndentationLevel++;
159:                 $sMessage = substr($sMessage, 0, -$this->iIndentTagLength);
160:             } elseif (substr($sMessage, -$this->iUnindentTagLength) == $this->aConfig['unindent_tag']) {
161:                 $this->iIndentationLevel = max(0, $this->iIndentationLevel-1);
162:                 $sMessage = substr($sMessage, 0, -$this->iUnindentTagLength);
163:             } else {
164:                 $bTagFound = false;
165:             }
166:         }
167:         return $sMessage;
168:     }
169: 
170:     /**
171:      * Logs with an arbitrary level.
172:      *
173:      * Allows adjustment of the indentation whith multiple leading or trailing tags:
174:      * see $this->sIndentTag and $this->sUnindentTag
175:      *
176:      * Allows insertion of bash colors via placeholders and context array.
177:      *
178:      * @param mixed $sMsgLevel message level, must be defined in \Psr\Log\LogLevel
179:      * @param string $sMessage message with placeholders
180:      * @param array $aContext context array
181:      * @throws \Psr\Log\InvalidArgumentException if calling this method with a level not defined in \Psr\Log\LogLevel
182:      */
183:     public function log ($sMsgLevel, $sMessage, array $aContext = array())
184:     {
185:         $this->checkMsgLevel($sMsgLevel);
186:         if (self::$aIntLevels[$sMsgLevel] >= $this->iMinMsgLevel) {
187:             $sMessage = $this->processLeadingIndentationTags($sMessage);
188:             $iCurrIndentationLvl = $this->iIndentationLevel;
189:             $sMessage = $this->processTrailingIndentationTags($sMessage);
190: 
191:             if (strlen($sMessage) > 0) {
192:                 if (isset($this->aConfig['colors'][$sMsgLevel])
193:                     || isset($aContext[$this->aConfig['color_tag_prefix'] . $sMsgLevel])
194:                 ) {
195:                     $sImplicitColor = '{' . $this->aConfig['color_tag_prefix'] . $sMsgLevel . '}';
196:                     $sMessage = $sImplicitColor . $sMessage;
197:                 } else {
198:                     $iNbColorTags = preg_match_all('/{C.[A-Za-z0-9_.]+}/', $sMessage, $aMatches);
199:                     $sImplicitColor = '';
200:                 }
201:                 $sMessage = $this->interpolateContext($sMessage, $aContext);
202:                 $sIndent = str_repeat($this->aConfig['base_indentation'], $iCurrIndentationLvl);
203:                 $sMessage = $sIndent . str_replace("\n", "\n$sIndent$sImplicitColor", $sMessage);
204:                 $sMessage = strtr($sMessage, $this->aColorTags);
205:                 if ($sImplicitColor != ''
206:                     || (
207:                         $iNbColorTags > 0
208:                         && preg_match_all('/{C.[A-Za-z0-9_.]+}/', $sMessage, $aMatches) < $iNbColorTags
209:                     )
210:                 ) {
211:                     $sMessage .= $this->aConfig['reset_color_sequence'];
212:                 }
213: 
214:                 echo $sMessage . PHP_EOL;
215:             }
216:         }
217:     }
218: }
219: 
Platform for Automatized Deployments with pOwerful Concise Configuration API documentation generated by ApiGen 2.8.0