mirror of
https://github.com/ZeJMaN/LBCAlerte_ynh.git
synced 2025-06-08 05:25:30 +02:00
238 lines
7.1 KiB
PHP
238 lines
7.1 KiB
PHP
<?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.
|
|
*
|
|
* @package log4php
|
|
*/
|
|
|
|
/**
|
|
* Most of the work of the {@link LoggerPatternLayout} class
|
|
* is delegated to the {@link LoggerPatternParser} class.
|
|
*
|
|
* <p>It is this class that parses conversion patterns and creates
|
|
* a chained list of {@link LoggerPatternConverter} converters.</p>
|
|
*
|
|
* @version $Revision: 1395467 $
|
|
* @package log4php
|
|
* @subpackage helpers
|
|
*
|
|
* @since 0.3
|
|
*/
|
|
class LoggerPatternParser {
|
|
|
|
/** Escape character for conversion words in the conversion pattern. */
|
|
const ESCAPE_CHAR = '%';
|
|
|
|
/** Maps conversion words to relevant converters. */
|
|
private $converterMap;
|
|
|
|
/** Conversion pattern used in layout. */
|
|
private $pattern;
|
|
|
|
/** Regex pattern used for parsing the conversion pattern. */
|
|
private $regex;
|
|
|
|
/**
|
|
* First converter in the chain.
|
|
* @var LoggerPatternConverter
|
|
*/
|
|
private $head;
|
|
|
|
/** Last converter in the chain. */
|
|
private $tail;
|
|
|
|
public function __construct($pattern, $converterMap) {
|
|
$this->pattern = $pattern;
|
|
$this->converterMap = $converterMap;
|
|
|
|
// Construct the regex pattern
|
|
$this->regex =
|
|
'/' . // Starting regex pattern delimiter
|
|
self::ESCAPE_CHAR . // Character which marks the start of the conversion pattern
|
|
'(?P<modifiers>[0-9.-]*)' . // Format modifiers (optional)
|
|
'(?P<word>[a-zA-Z]+)' . // The conversion word
|
|
'(?P<option>{[^}]*})?' . // Conversion option in braces (optional)
|
|
'/'; // Ending regex pattern delimiter
|
|
}
|
|
|
|
/**
|
|
* Parses the conversion pattern string, converts it to a chain of pattern
|
|
* converters and returns the first converter in the chain.
|
|
*
|
|
* @return LoggerPatternConverter
|
|
*/
|
|
public function parse() {
|
|
|
|
// Skip parsing if the pattern is empty
|
|
if (empty($this->pattern)) {
|
|
$this->addLiteral('');
|
|
return $this->head;
|
|
}
|
|
|
|
// Find all conversion words in the conversion pattern
|
|
$count = preg_match_all($this->regex, $this->pattern, $matches, PREG_OFFSET_CAPTURE);
|
|
if ($count === false) {
|
|
$error = error_get_last();
|
|
throw new LoggerException("Failed parsing layotut pattern: {$error['message']}");
|
|
}
|
|
|
|
$prevEnd = 0;
|
|
|
|
foreach($matches[0] as $key => $item) {
|
|
|
|
// Locate where the conversion command starts and ends
|
|
$length = strlen($item[0]);
|
|
$start = $item[1];
|
|
$end = $item[1] + $length;
|
|
|
|
// Find any literal expressions between matched commands
|
|
if ($start > $prevEnd) {
|
|
$literal = substr($this->pattern, $prevEnd, $start - $prevEnd);
|
|
$this->addLiteral($literal);
|
|
}
|
|
|
|
// Extract the data from the matched command
|
|
$word = !empty($matches['word'][$key]) ? $matches['word'][$key][0] : null;
|
|
$modifiers = !empty($matches['modifiers'][$key]) ? $matches['modifiers'][$key][0] : null;
|
|
$option = !empty($matches['option'][$key]) ? $matches['option'][$key][0] : null;
|
|
|
|
// Create a converter and add it to the chain
|
|
$this->addConverter($word, $modifiers, $option);
|
|
|
|
$prevEnd = $end;
|
|
}
|
|
|
|
// Add any trailing literals
|
|
if ($end < strlen($this->pattern)) {
|
|
$literal = substr($this->pattern, $end);
|
|
$this->addLiteral($literal);
|
|
}
|
|
|
|
return $this->head;
|
|
}
|
|
|
|
/**
|
|
* Adds a literal converter to the converter chain.
|
|
* @param string $string The string for the literal converter.
|
|
*/
|
|
private function addLiteral($string) {
|
|
$converter = new LoggerPatternConverterLiteral($string);
|
|
$this->addToChain($converter);
|
|
}
|
|
|
|
/**
|
|
* Adds a non-literal converter to the converter chain.
|
|
*
|
|
* @param string $word The conversion word, used to determine which
|
|
* converter will be used.
|
|
* @param string $modifiers Formatting modifiers.
|
|
* @param string $option Option to pass to the converter.
|
|
*/
|
|
private function addConverter($word, $modifiers, $option) {
|
|
$formattingInfo = $this->parseModifiers($modifiers);
|
|
$option = trim($option, "{} ");
|
|
|
|
if (isset($this->converterMap[$word])) {
|
|
$converter = $this->getConverter($word, $formattingInfo, $option);
|
|
$this->addToChain($converter);
|
|
} else {
|
|
trigger_error("log4php: Invalid keyword '%$word' in converison pattern. Ignoring keyword.", E_USER_WARNING);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determines which converter to use based on the conversion word. Creates
|
|
* an instance of the converter using the provided formatting info and
|
|
* option and returns it.
|
|
*
|
|
* @param string $word The conversion word.
|
|
* @param LoggerFormattingInfo $info Formatting info.
|
|
* @param string $option Converter option.
|
|
*
|
|
* @throws LoggerException
|
|
*
|
|
* @return LoggerPatternConverter
|
|
*/
|
|
private function getConverter($word, $info, $option) {
|
|
if (!isset($this->converterMap[$word])) {
|
|
throw new LoggerException("Invalid keyword '%$word' in converison pattern. Ignoring keyword.");
|
|
}
|
|
|
|
$converterClass = $this->converterMap[$word];
|
|
if(!class_exists($converterClass)) {
|
|
throw new LoggerException("Class '$converterClass' does not exist.");
|
|
}
|
|
|
|
$converter = new $converterClass($info, $option);
|
|
if(!($converter instanceof LoggerPatternConverter)) {
|
|
throw new LoggerException("Class '$converterClass' is not an instance of LoggerPatternConverter.");
|
|
}
|
|
|
|
return $converter;
|
|
}
|
|
|
|
/** Adds a converter to the chain and updates $head and $tail pointers. */
|
|
private function addToChain(LoggerPatternConverter $converter) {
|
|
if (!isset($this->head)) {
|
|
$this->head = $converter;
|
|
$this->tail = $this->head;
|
|
} else {
|
|
$this->tail->next = $converter;
|
|
$this->tail = $this->tail->next;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parses the formatting modifiers and produces the corresponding
|
|
* LoggerFormattingInfo object.
|
|
*
|
|
* @param string $modifier
|
|
* @return LoggerFormattingInfo
|
|
* @throws LoggerException
|
|
*/
|
|
private function parseModifiers($modifiers) {
|
|
$info = new LoggerFormattingInfo();
|
|
|
|
// If no modifiers are given, return default values
|
|
if (empty($modifiers)) {
|
|
return $info;
|
|
}
|
|
|
|
// Validate
|
|
$pattern = '/^(-?[0-9]+)?\.?-?[0-9]+$/';
|
|
if (!preg_match($pattern, $modifiers)) {
|
|
trigger_error("log4php: Invalid modifier in conversion pattern: [$modifiers]. Ignoring modifier.", E_USER_WARNING);
|
|
return $info;
|
|
}
|
|
|
|
$parts = explode('.', $modifiers);
|
|
|
|
if (!empty($parts[0])) {
|
|
$minPart = (integer) $parts[0];
|
|
$info->min = abs($minPart);
|
|
$info->padLeft = ($minPart > 0);
|
|
}
|
|
|
|
if (!empty($parts[1])) {
|
|
$maxPart = (integer) $parts[1];
|
|
$info->max = abs($maxPart);
|
|
$info->trimLeft = ($maxPart < 0);
|
|
}
|
|
|
|
return $info;
|
|
}
|
|
}
|