%PDF- %PDF-
Direktori : /www/loslex_o/tracker/core/classes/ |
Current File : /www/loslex_o/tracker/core/classes/ConfigParser.class.php |
<?php # MantisBT - A PHP based bugtracking system # MantisBT is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # MantisBT is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with MantisBT. If not, see <http://www.gnu.org/licenses/>. /** * Configuration Parser class. * @copyright Copyright 2016 MantisBT Team - mantisbt-dev@lists.sourceforge.net * @link http://www.mantisbt.org * @package MantisBT * @subpackage classes */ /** * Configuration Parser class * * Simple PHP code parser for scalar and array types * * @package MantisBT * @subpackage classes * * @uses Tokenizer */ class ConfigParser { /** * Define how extra tokens should be handled by parse() method */ const EXTRA_TOKENS_IGNORE = 0; const EXTRA_TOKENS_ERROR = 1; /** * @var Tokenizer $tokens */ protected $tokens; /** * Parser constructor. * @param string $p_code PHP code to parse */ public function __construct( $p_code ) { $this->tokens = new Tokenizer( $p_code ); } /** * Parse the code for a variable assignment. * Handles scalar types, and various array types (simple, associative, * multi-dimensional) * @param integer $p_extra_tokens Define how extra tokens should be handled * - EXTRA_TOKENS_IGNORE silently ignore any * extra code given after the first token * - EXTRA_TOKENS_ERROR (default) throws an * exception if extra code is found * @return mixed variable * @throws Exception when there are unexpected or extra tokens */ public function parse( $p_extra_tokens = self::EXTRA_TOKENS_ERROR ) { switch( $this->tokens->type() ) { case T_ARRAY: $t_result = $this->process_array(); break; case T_CONSTANT_ENCAPSED_STRING: case T_STRING: case T_LNUMBER: case T_DNUMBER: case '-': case '+': $t_result = $this->process_value(); break; default: throw new Exception( 'Unexpected token "' . $this->tokens->value() . '"' ); } # Make sure we have processed all tokens if( $p_extra_tokens == self::EXTRA_TOKENS_ERROR && !$this->tokens->is_empty() ) { throw new Exception( 'Extra tokens found "' . $this->tokens->get_string() .'":' ); } return $t_result; } /** * Check if the passed string is a constant and returns its value if yes, * or the string itself if not * @param string $p_name String to check. * @return mixed|string value of constant $p_name, or $p_name itself */ public static function constant_replace( $p_name ) { $t_name = trim( $p_name ); if( is_string( $t_name ) && defined( $t_name ) ) { # we have a constant return constant( $t_name ); } return $t_name; } /** * Recursively process array declarations. * @return array * @throws Exception when there's an invalid token */ protected function process_array() { $t_array = array(); $t_count = 0; $this->tokens->ensure_matches( T_ARRAY ); $this->tokens->ensure_matches( '(' ); # Loop until we reach the end of the array while( !$this->tokens->matches( ')' ) ) { # A comma is required before each element except the first one if ($t_count > 0) { $this->tokens->ensure_matches(','); } switch( $this->tokens->type() ) { # Nested array case T_ARRAY: $t_array[] = $this->process_array(); break; # Value case T_CONSTANT_ENCAPSED_STRING: case T_STRING: case T_LNUMBER: case T_DNUMBER: $t_str = $this->process_value(); if( $this->tokens->matches( T_DOUBLE_ARROW ) ) { # key => value $this->tokens->pop(); if( $this->tokens->matches( T_ARRAY ) ) { $t_array[$t_str] = $this->process_array(); } else { $t_array[$t_str] = $this->process_value(); } } else { # Simple value $t_array[] = $t_str; } break; case ')': # Cover the trailing ',' case break; default: throw new Exception("Invalid token '" . $this->tokens->value() . "'"); } $t_count++; } $this->tokens->ensure_matches( ')' ); return $t_array; } /** * Process a scalar value. * Handles string literals including defined constants * @return mixed * @throws Exception when there's an unexpected value */ protected function process_value() { # String literals if( $this->tokens->matches( T_STRING ) ) { $t_token = $this->tokens->pop(); $t_value = $t_token[1]; # PHP Standard string literals switch (strtolower($t_value)) { case 'null': return null; case 'true': return true; case 'false': return false; } # Defined constants $t_value = $this->constant_replace( $t_value ); if( $t_value !== $t_token[1] ) { return $t_value; } throw new Exception("Unknown string literal '$t_value'"); } # Strings if( $this->tokens->matches( T_CONSTANT_ENCAPSED_STRING ) ) { $t_value = $this->tokens->pop(); return (string)stripslashes( substr( $t_value[1], 1, -1 ) ); } # Numbers $t_negate = 1; if( $this->tokens->matches( '-' ) ) { $this->tokens->pop(); $t_negate = -1; } if( $this->tokens->matches( '+' ) ) { $this->tokens->pop(); } # Integers if( $this->tokens->matches( T_LNUMBER ) ) { $t_value = $this->tokens->pop(); return $t_negate * (int)$t_value[1]; } # Floating point if( $this->tokens->matches( T_DNUMBER ) ) { $t_value = $this->tokens->pop(); return $t_negate * (float)$t_value[1]; } # Anything else throw new Exception( "Unexpected value" . $this->tokens->value() ); } }