DIR : /home/kozerus/public_html/dgs/include/filter_parser.php

/home/kozerus/public_html/dgs/include

<?php
/*
Dragon Go Server
Copyright (C) 2001-  Erik Ouchterlony, Rod Ival, Jens-Uwe Gaspar

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

$TranslateGroups[] = "Common";

 /* Author: Jens-Uwe Gaspar */

require_once 'include/quick_common.php';
require_once 'include/filter_functions.php';
require_once 'include/tokenizer.php';
require_once 'include/utilities.php';

 /*!
  * \file filter_parser.php
  *
  * \brief Classes and special functions to help in parsing texts and numerics; mainly used for filters.
  *
  * \see TokenizerConfig
  * \see BasicParser
  * \see   NumericParser
  * \see   TextParser
  * \see DateParser
  */

// constants for parsers

// the following consts use the same bitmask-scope (general scope 'PARSER_'):
//    express flags, so that omitting them is the default
define('PARSER_NOSWAP_REVERSE',       0x00000001); // if set, don't swap start/end if start > end
define('TEXTPARSER_FORBID_RANGE',     0x00001000); // for numeric/text/date-parser: if set, forbid range-syntax
define('TEXTPARSER_FORBID_WILD',      0x00002000); // for text-parser: if set, forbid wildcards
define('TEXTPARSER_ALLOW_START_WILD', 0x00004000); // for text-parser: if set, allow search-string to start with wildcard
define('TEXTPARSER_END_INCL',         0x00008000); // for text-parser: if not set, make end-range exclusive in the search to build '>' <-> '>='
define('TEXTPARSER_IMPLICIT_WILD',    0x00010000); // for text-parser: if set, implicit wildcards are added to start and end 'foo' -> '*foo*' (forces TEXTPARSER_FORBID_RANGE and TEXTPARSER_ALLOW_START_WILD)

define('PFLAG_WILDCARD',      0x00000001); // if set, indicates that parsed value contained wildcard
define('PFLAG_EXCL_START',    0x00000002); // if set, indicates that parsed start-value should use exclusive SQL-comparator
define('PFLAG_EXCL_END',      0x00000004); // if set, indicates that parsed end-value should use exclusive SQL-comparator
define('PFLAG_SPECIAL_QUERY', 0x00000008); // if set, indicates that special query-template to be used (is filter specific)



/*!
 * \brief returns token-array with range: val1-val2, -val2, val1-
 * signature: ( Token1, Token2 ) = extract_range(token_array)
 */
function extract_range( $arr )
{
   if ( count($arr) == 3 )
      return array( $arr[0]->get_token(), $arr[2]->get_token() );

   if ($arr[0]->get_type() == TOK_SEPARATOR)
      return array( '', $arr[1]->get_token() );
   else
      return array( $arr[0]->get_token(), '' );
}

/*!
 * \brief constructs StringTokenizer
 * signature: StringTokenizer createStringTokenizer( TokenizerConfig tok_config, string special_chars, int flags)
 * param flags: TEXTPARSER_FORBID_RANGE
 */
function create_StringTokenizer( TokenizerConfig $tc, $spec_chars, $flags = 0 )
{
   $sep = ( $flags & TEXTPARSER_FORBID_RANGE ) ? '' : $tc->sep;
   $tokenizer = new StringTokenizer($tc->quotetype, $sep, $spec_chars, $tc->escape_chars, $tc->quote_chars);
   return $tokenizer;
}



 /*!
  * \class TokenizerConfig
  *
  * \brief Configuration used for StringTokenizer.
  */
class TokenizerConfig
{
   /*! \brief quote-type. */
   public $quotetype;
   /*! \brief separator, default is '-' */
   public $sep;
   /*! \brief wildcard-char, default is '*' */
   public $wild;
   /*! \brief chars used to quote; default are "" */
   public $quote_chars;
   /*! \brief chars to escape; default are \\ */
   public $escape_chars;

   /*! \brief Additional config-array: ( key => val ). */
   public $config = array();

   /*!
    * \brief Constructs TokenizerConfig( QUOTETYPE_..., [string separator-char='-'], [quote_chars="''"], [esc_chars='\\\\'] )
    * \param $quotetype QUOTETYPE_..-const
    * \param $sep separator-char to represent range-syntax; if null, default is '-'
    * \param $wild wildcard-char; if null, default is '*'
    * \param $quote_chars start- and end-quote-char; if null, default is "''" (single-quotes)
    * \param $esc_chars escape-from- and escape-to-char; if null, default is \\ (backslash)
    */
   public function __construct( $quotetype, $sep = null, $wild = null, $quote_chars = null, $esc_chars = null )
   {
      $this->quotetype = $quotetype;
      $this->sep       = (is_null($sep)) ? '-' : $sep;
      $this->wild      = (is_null($wild)) ? TEXT_WILD_M : $wild;
      $this->quote_chars  = (is_null($quote_chars)) ? "''" : $quote_chars;
      $this->escape_chars = (is_null($esc_chars)) ? '\\\\' : $esc_chars;
   }

   /*!
    * \brief Adds config as key-value-pair.
    * signature: add_config( string key, string val)
    */
   public function add_config( $key, $val )
   {
      $this->config[$key] = $val;
   }

   /*!
    * \brief Returns configuration for key; if not set, return empty string.
    * signature: mixed get_config( string key, [mixed defval=''] )
    */
   public function get_config( $key, $defval = '' )
   {
      return (isset($this->config[$key])) ? $this->config[$key] : $defval;
   }

} // end of 'TokenizerConfig'



 /*!
  * \class BasicParser
  *
  * \brief abstract Basic-Parser providing some basic vars and functions used to support syntax for Filters.
  * Provides an interface-method 'parse(value,flags)' to parse a value follow some basic syntax.
  *
  * \note next layer of functions based on Tokenizers.
  *
  * Basic principle of Parser:
  *    Parser is constructed with configuration needed for parsing.
  *    $parser = new XYZParser( value, TokenizerConfig, int flags);
  *    $success = parse( input_string, parser_flags );
  *    if ( !$success )
  *       handle_errors( $parser->errormsg() );
  */
abstract class BasicParser
{
   /*! \brief orig-value to parse. */
   protected $value;
   /*! \brief TokenizerConfig */
   protected $tokconf;
   /*! \brief Flags for parsing, e.g.: PARSER_NOSWAP_REVERSE, TEXTPARSER_... */
   protected $flags;

   // parsed values and flags

   /*! \brief error-message if parsing-error occured; if non-empty, parsing-output is invalid. */
   protected $errormsg;
   /*! \brief start-range (>=) */
   public $p_start;
   /*! \brief end-range (<=) */
   public $p_end;
   /*! \brief exact-value or wildcard-value */
   public $p_value;
   /*! \brief flags about parsed value: PFLAG_WILDCARD */
   public $p_flags;
   /*! \brief non-null array with search rx_terms. */
   public $p_terms;

   /*! \brief Constructs BasicParser for specified value, TokenizerConfig and flags. */
   protected function __construct( $value, TokenizerConfig $tokconf, $flags = 0 )
   {
      $this->init_parse( $value, $flags );
      $this->tokconf = $tokconf;

      // abstract $this->parse($value);
   }

   /*!
    * \brief reset values for parsing; value is trimmed.
    * signature: init_parse(string val)
    */
   protected function init_parse( $_value, $_flags = 0 )
   {
      $this->value = trim($_value);
      $this->flags = $_flags;
      $this->errormsg = '';

      $this->p_start = '';
      $this->p_end = '';
      $this->p_value = '';
      $this->p_flags = 0;
      $this->p_terms = array();
   }//init_parse

   /*!
    * \brief returns non-empty string, if parsing-error occured.
    * signature: string errormsg()
    */
   public function errormsg()
   {
      return $this->errormsg;
   }

   /*!
    * \brief Returns true, if specified flag in parsing-flags set.
    * signature: bool is_flags_set()
    */
   public function is_flags_set( $flag )
   {
      return (bool)( $this->flags & $flag );
   }

   /*!
    * \brief Returns null on error; otherwise bool indicating if specified flag in parsed-flags ($p_flags)
    * signature: bool|null = is_parsed_flags_set()
    */
   public function is_parsed_flags_set( $flag )
   {
      if ( $this->errormsg != '' )
         return null;
      return (bool)( $this->p_flags & $flag );
   }


   // interfaces

   /*!
    * \brief parses value with specified flags, updates: value, flags, errormsg, p_start/p_end/p_value/p_flags.
    * signature: interface bool success = parse(string value, int flags)
    */
   abstract public function parse( $value, $flags = 0 );


   // help-functions

   /*!
    * \brief Swaps p_start and p_end if range reversed and flag PARSER_NOSWAP_REVERSE set
    *        and returns true, if swapped; false otherwise.
    * signature: void handle_reverse_range([bool force = false])
    */
   public function handle_reverse_range( $force = false )
   {
      $swapped = false;
      if ( !$this->is_flags_set(PARSER_NOSWAP_REVERSE) || $force )
      {
         if ( $this->is_reverse_range() )
         {
            $this->swap_range_start_end();
            $swapped = true;
         }
      }
      return $swapped;
   }//handle_reverse_range

   /*!
    * \brief returns true, if p_start > p_end
    * signature: bool is_reverse_range()
    */
   protected function is_reverse_range()
   {
      if ( (string)$this->p_start != '' && (string)$this->p_end != '' )
         return ( $this->p_start > $this->p_end );
      else
         return false;
   }

   /*!
    * \brief swaps p_start and p_end
    * signature: void swap_range_start_end()
    */
   protected function swap_range_start_end()
   {
      swap( $this->p_start, $this->p_end );
   }

} // end of 'BasicParser'



 /*!
  * \class NumericParser
  *
  * \brief Parser to parse numeric values.
  *
  * Supported Flags: PARSER_NOSWAP_REVERSE
  * NOTE: parse numeric values only (at this moment)
  *
  * Parse-Syntax: 7, -7, 7-, 7-9
  */
class NumericParser extends BasicParser
{
   /*! \brief Constructs NumericParser( string value, TokenizerConfig tok_config, int flags ). */
   public function __construct( $value, TokenizerConfig $tok_config, $flags = 0 )
   {
      parent::__construct( $value, $tok_config, $flags );
      $this->parse($value, $flags);
   }

   /*!
    * \brief Parses value with specified $flags
    * signature: interface bool success = parse(string value, int flags)
    */
   public function parse( $value, $flags = 0 )
   {
      $this->init_parse($value, $flags);
      if ( $this->value == '' )
         return true; // empty (no-error)

      // tokenize
      $tokenizer = create_StringTokenizer( $this->tokconf, '', $this->flags);
      if ( !$tokenizer->parse($value) )
      {
         $this->errormsg = implode('; ', $tokenizer->get_errors());
         return false;
      }
      $arr = $tokenizer->tokens();
      $cnt = count($arr);
      // expected: 0 entries (''), 1 entry (val), 2 entries (sep val | val sep), 3 entries (start sep end)

      if ( $cnt == 0 )
         return true;

      if ( $cnt > 3 )
      {
         $this->errormsg = "[$value] " . T_('too many separators#filter') . " [{$this->tokconf->sep}]";
         return false;
      }

      if ( $cnt == 1 )
      { // exact syntax
         $v = $arr[0]->get_token();
         if ( empty($v) || is_numeric($v) )
            $this->p_value = $v;
         else
         {
            $this->errormsg = "[$v] " . T_('not numeric');
            return false;
         }
      }
      else
      { // range syntax
         list( $v1, $v2 ) = extract_range( $arr );
         if ( !empty($v1) && !is_numeric($v1) )
         {
            $this->errormsg = "[$v1] " . T_('not numeric');
            return false;
         }
         elseif ( !empty($v2) && !is_numeric($v2) )
         {
            $this->errormsg = "[$v2] " . T_('not numeric');
            return false;
         }
         else
         {
            $this->p_start = $v1;
            $this->p_end   = $v2;
         }
      }

      $this->handle_reverse_range();

      return true;
   }//parse

} // end of 'NumericParser'



 /*!
  * \class TextParser
  *
  * \brief Parser to parse text values.
  *
  * Supported Flags: PARSER_NOSWAP_REVERSE | TEXTPARSER_FORBID_RANGE |
  *                  TEXTPARSER_FORBID_WILD | TEXTPARSER_ALLOW_START_WILD |
  *                  TEXTPARSER_END_INCL | TEXTPARSER_IMPLICIT_WILD
  * Supported TokenizerConfig:
  *                  TEXTPARSER_CONF_STARTWILD_MINCHARS = 1..
  *                  TEXTPARSER_CONF_RX_NO_SEP = regex
  *                  TEXTPARSER_CONF_PRECEDENCE_SEP = 0|1
  *
  * note: wildcard supported: '*' (multi-char)
  * note: performs additional check of consecutive chars when value starts with wildcard
  *
  * result: var $p_terms contains array with search rx_terms when wildcard or exact-syntax.
  *
  * Parse-Syntax: x, -x, x-, x-y, x*, *x
  */

define('TEXT_WILD_M', '*'); // special char for wildcard (multi-char)

define('TEXTPARSER_CONF_STARTWILD_MINCHARS', 'startwild_minchars');
define('TEXTPARSER_CONF_RX_NO_SEP', 'txtpconf_rx_no_sep' ); // regex that overrules match for range-separator
define('TEXTPARSER_CONF_PRECEDENCE_SEP', 'precedence_sep'); // flag to indicate, that separator has higher precedence than other special-chars (wildcard)

define('STARTWILD_OPTMINCHARS', 4); // value for filter-config FC_START_WILD or above define (=no of chars to force when pattern starts with wildcard)

class TextParser extends BasicParser
{
   /*! \brief Constructs TextParser( string value, TokenizerConfig tok_config, int flags ). */
   public function __construct( $value, TokenizerConfig $tok_config, $flags = 0 )
   {
      if ( $flags & TEXTPARSER_IMPLICIT_WILD )
         $flags |= TEXTPARSER_FORBID_RANGE | TEXTPARSER_ALLOW_START_WILD;
      parent::__construct( $value, $tok_config, $flags );
      $this->parse($value, $this->flags);
   }

   /*!
    * \brief Parses value with specified $flags
    * signature: interface bool success = parse(string value, int flags)
    */
   public function parse( $value, $flags = 0 )
   {
      $this->init_parse($value, $flags);
      if ( $this->value == '' )
         return true; // empty (no-error)

      // init tokenizer
      $forbid_wild = $this->is_flags_set(TEXTPARSER_FORBID_WILD);
      $wild_char = $this->tokconf->wild;
      if ( $forbid_wild )
         $wild_char = '';
      $tokenizer = create_StringTokenizer( $this->tokconf, $wild_char, $this->flags);
      $rx_no_sep = $this->tokconf->get_config( TEXTPARSER_CONF_RX_NO_SEP );
      if ( $rx_no_sep != '' )
         $tokenizer->add_config( STRTOK_CONF_RX_NO_SEP, $rx_no_sep );

      // tokenize
      if ( !$tokenizer->parse($value) )
      {
         $this->errormsg = implode('; ', $tokenizer->get_errors());
         return false;
      }
      $arr = $tokenizer->tokens();
      $cnt = count($arr);
      // expected: 0 entries (''), 1 entry (val), 2 entries (sep val | val sep), 3 entries (start sep end)

      if ( $cnt == 0 )
         return true;

      if ( $cnt > 3 )
      {
         $this->errormsg = "[$value] " . T_('too many separators#filter') . " [{$this->tokconf->sep}]";
         return false;
      }

      // assure higher precedence of wildcard (over separator)
      $arr_wild_replace = array( $this->tokconf->wild => '%' );
      if ( $cnt != 1 && !$forbid_wild && !$this->is_flags_set(TEXTPARSER_CONF_PRECEDENCE_SEP) )
      {
         list( $v1, $v2 ) = extract_range( $arr );
         list( $sql, $cnt_wild1 ) = sql_replace_wildcards( $v1, $arr_wild_replace );
         list( $sql, $cnt_wild2 ) = sql_replace_wildcards( $v2, $arr_wild_replace );
         if ( $cnt_wild1 + $cnt_wild2 > 0 )
         {
            $merged_token = new Token(TOK_TEXT, 0, $v1 . $arr[1]->get_token() . $v2 );
            $arr = array( $merged_token );
            $cnt = 1;
         }
      }

      if ( $cnt == 1 )
      { // exact syntax or wildcard
         $v = $arr[0]->get_token();
         if ($v == '')
            return true;

         if ( $forbid_wild )
         {
            // wild can be treated as normal char, same goes for special-chars
            $this->p_value = $v;
            $term = preg_replace( "/[^\\w'\\s]+/", '', $v );
            $this->p_terms[]= $term;
         }
         else // allow-wild
         {
            // add wild as prefix and suffix to build substring-search
            if ( $this->is_flags_set(TEXTPARSER_IMPLICIT_WILD) )
            {
               if ( $v[0] != $wild_char )
                  $v = $wild_char . $v;
               if ( substr($v, -1) != $wild_char )
                  $v .= $wild_char;
            }

            if ( (string)$wild_char != '' )
               if (substr_count($v, $wild_char) == strlen($v)) // wildcards only (multi-char '*')
                  return true; // matching all (return '')

            // started with wildcard?
            if ( $v[0] == $wild_char )
            {
               if ( $this->is_flags_set(TEXTPARSER_ALLOW_START_WILD) ) // check min-chars
               {
                  $minchars = $this->tokconf->get_config(TEXTPARSER_CONF_STARTWILD_MINCHARS, STARTWILD_OPTMINCHARS);
                  $quote_wild = preg_quote( $wild_char, '/' );
                  if ( $minchars > 1 && !(preg_match("/^[{$quote_wild}]+([^{$quote_wild}]{".$minchars.",})/", $v)) )
                  {
                     $this->errormsg =
                        sprintf( T_('need at least %1$s characters when using text with starting wildcard [%2$s]'),
                           $minchars, $wild_char );
                     return false;
                  }
               }
               else
               { // forbid to start with wildcard
                  $this->errormsg = "[$wild_char] " . T_('not allowed as prefix#filter');
                  return false;
               }
            }

            // safely replace wildcards with SQL-wildcards
            list( $valsql, $cnt_wild ) = sql_replace_wildcards( $v, $arr_wild_replace );

            $this->p_value = $valsql;
            if ( $cnt_wild > 0 )
               $this->p_flags |= PFLAG_WILDCARD;
            $arr_terms = sql_extract_terms( $valsql );
            if ( count($arr_terms) > 0 )
               $this->p_terms = array_merge( $this->p_terms, $arr_terms );
         }
      }
      else
      { // range syntax (handle wildcard as normal chars)
         list( $v1, $v2 ) = extract_range( $arr );
         $this->p_start = $v1;
         $this->p_end   = $v2;
         $this->handle_reverse_range();

         if ( (string)$this->p_end != '' && !$this->is_flags_set(TEXTPARSER_END_INCL) )
            $this->p_end = make_text_end_exclusive( $this->p_end );
      }

      return true;
   }//parse

} // end of 'TextParser'



 /*!
  * \class DateParser
  *
  * \brief Parser to parse single date values without tokenizing.
  *
  * NOTE: tokenizing is done in FilterDate-class; \see FilterDate
  * NOTE: not extending from BasicParser
  *
  * Parse-Syntax: date = [ YYYY [ MM [ DD [ ' '? hh [ mm [ ss ] ] ] ] ] ]
  * Notes:
  * - if year omitted, use current year
  * - Completes missing date-parts for supporting searching start/end-ranges
  * - ':'-char is skipped while parsing date
  */

define('DP_RANGE_START', 0); // indicating range-start for DateParser
define('DP_RANGE_END',   1); // indicating range-end for DateParser

class DateParser
{
   /*! \brief original date passed to constructor. */
   public $origdate;
   /*! \brief original range-type passed to constructor. */
   private $rangetype;
   /*! \brief first error encountered while parsing. */
   private $errormsg = '';
   /*! \brief =getdate() on constructor-time */
   private $now;

   // for parsing

   /*! \brief Working copy of date for parsing. */
   private $datestr;
   /*! \brief array with error-datepart. */
   private $checkarr;
   /*! \brief resulting date, completed in format 'YYYY-MM-DD hh:mm:ss', only valid if no errormsg */
   private $dateval;
   /*! \brief unix-timestamp of completed-date without rangetype-processing (used for reverse-range-handling) */
   public $rawdate;

   // respective values during parsing
   private $year;
   private $month;
   private $day;
   private $hour;
   private $min;
   private $sec;


   /*!
    * \brief Constructs DateParser( string datestr, int rangetype ).
    * \param $rangetype: DP_RANGE_START | DP_RANGE_END
    */
   public function __construct( $datestr, $rangetype )
   {
      // check args
      if ( $rangetype != DP_RANGE_START && $rangetype != DP_RANGE_END )
         error('invalid_filter', "filter_parser.DateParser.invalid_arg.rangetype($rangetype)");

      $this->origdate = $datestr;
      $this->rangetype = $rangetype;
      global $NOW;
      $this->now = getdate($NOW);

      if ( $this->parse($this->origdate) )
         $this->complete_date();
   }//__construct

   /*!
    * \brief Returns error-message; '' if no error.
    * signature: string errormsg()
    */
   public function errormsg()
   {
      return $this->errormsg;
   }

   /*!
    * \brief Returns resulting date in format 'YYYY-MM-DD hh:mm:ss' if no error occured, '' otherwise.
    * signature: string get_completed_date()
    * \note only valid if no errormsg
    */
   public function get_completed_date()
   {
      return ( $this->errormsg ) ? '' : $this->dateval;
   }

   public function to_string()
   {
      return "DateParser('{$this->origdate}',{$this->rangetype})={ err=[{$this->errormsg}], "
         . "date=[{$this->datestr}], val=[{$this->dateval}], rawdate=[{$this->rawdate}]"
         . "y-m-d=[{$this->year}-{$this->month}-{$this->day}] "
         . "H:M:S=[{$this->hour}:{$this->min}:{$this->sec}] }";
   }

   /*!
    * \brief Creates unix-timestamp-snapshot of current year/month/day/hour/min/sec.
    * signature: void make_ts_snapshot()
    */
   public function make_ts_snapshot()
   {
      return mktime($this->hour, $this->min, $this->sec, $this->month, $this->day, $this->year);
   }


   /*!
    * \brief Checks passed value against specified range; if error -> add typepart in checkarr.
    * signature: bool error = check_datepart(string typepart, string datepart, int start, int end)
    */
   private function check_datepart($typepart, $dpart, $start, $end)
   {
      $error = 0;
      if ( $dpart == '' )
         return false; // ok, if empty
      if ( $dpart < $start )
         $error++;
      if ( $dpart > $end )
         $error++;
      if ( $error )
         $this->checkarr[]= $typepart;
      return (boolean)$error;
   }//check_datepart

   /*!
    * \brief Parses date.
    * signature: bool success = parse(string date)
    */
   public function parse( $date )
   {
      static $rxdate = '/^(\d{4})(\d\d)?(\d\d)?\s*(\d\d)?(\d\d)?(\d\d)?$/';

      // init parse
      $this->origdate = $date;
      $this->datestr  = str_replace( ':', '', $date ); // working copy (strip ';'-char)
      $this->dateval  = '';
      $this->errormsg = '';

      $this->checkarr = array(); // reset errors

      // parse into date-parts: YMD hms
      $out = array();
      if ( preg_match($rxdate, $this->datestr, $out) == 0)
      {
         $this->errormsg = "[$date] " . T_('invalid date-format#filter');
         return false;
      }

      // some basic range-checks (date-parts may be optional)
      @list(, $this->year, $this->month, $this->day, $this->hour, $this->min, $this->sec) = $out;
      $this->check_datepart('Y', $this->year,  1900, 2100);
      $this->check_datepart('M', $this->month, 1, 12);
      $this->check_datepart('D', $this->day,   1, 31);
      $this->check_datepart('h', $this->hour,  0, 23);
      $this->check_datepart('m', $this->min,   0, 59);
      $this->check_datepart('s', $this->sec,   0, 59);
      if ( count($this->checkarr) > 0)
      {
         $err_datepart = implode( '', $this->checkarr);
         $this->errormsg = "[$date] " . T_('has invalid date-part#filter') . " [".$err_datepart."]";
         return false;
      }

      // check year/month/day-combination
      $chk_day   = ( (string)$this->day   != '' ) ? $this->day   : 1; // maybe empty
      $chk_month = ( (string)$this->month != '' ) ? $this->month : 1; // maybe empty
      if ( !checkdate( $chk_month, $chk_day, $this->year ) )
      {
         $this->errormsg = "[$date] " . T_('invalid day#filter');
         return false;
      }

      return true;
   }//parse

   /*!
    * \brief Completes date according to rangetype, store in dateval; update of year/month/day/hour/min/sec if needed.
    * signature: void complete_date()
    * \note rangetype only DP_RANGE_START|END
    */
   private function complete_date()
   {
      // missing year + remaining ('YMDhms') -> use current year
      if ( $this->year == '' )
         $this->year = $this->now['year'];

      // missing month + remaining ('MDhms')
      if ( $this->month == '' )
      {
         $this->month = 1;
         $this->day = 1;
         $this->hour = $this->min = $this->sec = 0;
         $this->rawdate = $this->make_ts_snapshot();
         if ( $this->rangetype == DP_RANGE_END)
            $this->year++;
      }
      // missing day + remaining ('Dhms')
      elseif ( $this->day == '' )
      {
         $this->day = 1;
         $this->hour = $this->min = $this->sec = 0;
         $this->rawdate = $this->make_ts_snapshot();
         if ( $this->rangetype == DP_RANGE_END)
            $this->month++;
      }
      // missing hour + remaining ('hms')
      elseif ( $this->hour == '' )
      {
         $this->hour = $this->min = $this->sec = 0;
         $this->rawdate = $this->make_ts_snapshot();
         if ( $this->rangetype == DP_RANGE_END)
            $this->day++;
      }
      // missing minute + remaining ('ms')
      elseif ( $this->min == '' )
      {
         $this->min = $this->sec = 0;
         $this->rawdate = $this->make_ts_snapshot();
         if ( $this->rangetype == DP_RANGE_END)
            $this->hour++;
      }
      // missing sec + remaining ('s')
      elseif ( $this->sec == '' )
      {
         $this->sec = 0;
         $this->rawdate = $this->make_ts_snapshot();
         if ( $this->rangetype == DP_RANGE_END)
            $this->min++;
      }

      // handle exceeding of limits by increasing of date-parts
      $unixtime = $this->make_ts_snapshot();
      $this->dateval = date(DATE_FMT_QUICK, $unixtime);
   }//complete_date

} // end of 'DateParser'

?>
//


koh5_pano



Your browser does not support the HTML5 canvas element.


Drag mouse to navigate.

Navigation





17.Aug.2010, Martin Wengenmayer