PageRenderTime 83ms CodeModel.GetById 5ms app.highlight 58ms RepoModel.GetById 0ms app.codeStats 2ms

/php-lib/div.php

https://github.com/pragres/cubay
PHP | 7863 lines | 6206 code | 802 blank | 855 comment | 1077 complexity | 196bfc3d1ac8a7d77e5a643527217da6 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2
   3/**
   4 * [[]] Div PHP Template Engine
   5 *
   6 * Div (division) is a template engine for PHP 5.x or higher and it is a social project
   7 * without spirit of lucre financed by Pragres (http://pragres.com)
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful, but
  14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  16 * for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program as the file LICENSE.txt; if not, please see
  20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  21 *
  22 * @author Rafael Rodriguez Ramirez <rafa@pragres.com>
  23 * @version : 4.5
  24 * @link http://divengine.com
  25 */
  26/**
  27 * Constants
  28 *
  29 * PACKAGES The path of templates's root directory.
  30 * DIV_DEFAULT_TPL_FILE_EXT The default extension for template files
  31 * DIV_DEFAULT_DATA_FILE_EXT The default extension for data files
  32 * DIV_MAX_PARSE_CYCLES The max number of cycles of the parser (to prevent infinite loop and more)
  33 * DIV_MAX_FILENAME_SIZE The max size of file name or dir name in your operating system
  34 */
  35if (! defined('PACKAGES'))
  36	define('PACKAGES', './');
  37if (! defined('DIV_DEFAULT_TPL_FILE_EXT'))
  38	define('DIV_DEFAULT_TPL_FILE_EXT', 'tpl');
  39if (! defined('DIV_DEFAULT_DATA_FILE_EXT'))
  40	define('DIV_DEFAULT_DATA_FILE_EXT', 'json');
  41if (! defined('DIV_MAX_PARSE_CYCLES'))
  42	define('DIV_MAX_PARSE_CYCLES', 100);
  43if (! defined('DIV_MAX_FILENAME_SIZE'))
  44	define('DIV_MAX_FILENAME_SIZE', 250);
  45
  46define('DIV_PHP_ALLOWED_FUNCTIONS', 'isset,empty,is_null,is_numeric,is_bool,is_integer,is_double,' . 'sizeof,is_finite,is_float,is_infinite,is_int,is_long,is_nan,' . 'is_real,is_scalar,is_string,mt_rand,mt_srand,mt_getrandmax,' . 'rand,urlencode,urldecode,uniqid,date,time,intval,htmlspecialchars,' . 'htmlspecialchars_decode,strtr,strpos,str_replace,str_ireplace,' . 'substr,sprintf,abs,acos,acosh,asin,atan2,atanh,base_convert,' . 'bindec,ceil,cos,cosh,decbin,dechex,decoct,deg2rad,exp,expm1,' . 'floor,fmod,getrandmax,hexdec,hypot,lcg_value,log10,log1p,log,' . 'max,min,octdec,pi,pow,rad2deg,rand,round,sin,sinh,sqrt,srand,' . 'tan,tanh,cal_days_in_month,cal_from_jd,cal_info,cal_to_jd,' . 'easter_date,easter_days,frenchtojd,gregoriantojd,jddayofweek,' . 'jdmonthname,jdtofrench,jdtogregorian,jdtojewish,jdtojulian,' . 'jdtounix,jewishtojd,jewishtojd,unixtojd,checkdate,' . 'date_default_timezone_get,strtotime,date_sunset,gmdate,gmmktime,' . 'gmstrftime,idate,microtime,mktime,strftime,strptime,strtotime,' . 'timezone_name_from_abbr,timezone_version_get,bcadd,bccomp,' . 'bcdiv,bcmod,bcmul,bcpow,bcpowmod,bcscale,bcsqrt,bcsub,addcslashes,' . 'addslashes,bin2hex,chop,chr,chunk_split,convert_cyr_string,' . 'convert_uudecode,convert_uuencode,count,count_chars,crc32,crypt,' . 'hebrev,hebrevc,hex2bin,html_entity_decode,htmlentities,' . 'htmlspecialchars_decode,htmlspecialchars,lcfirst,levenshtein,' . 'ltrim,md5,metaphone,money_format,nl_langinfo,nl2br,number_format,' . 'ord,quoted_printable_decode,quoted_printable_encode,quotemeta,' . 'rtrim,sha1,similar_text,soundex,sprintf,str_pad,str_repeat,' . 'str_rot13,str_shuffle,strcasecmp,strchr,strcmp,strcoll,strcspn,' . 'strip_tags,stripcslashes,stripos,stripslashes,stristr,strlen,' . 'strnatcasecmp,strnatcmp,strncasecmp,strncmp,strpbrk,strrchr,' . 'strrev,strripos,strrpos,strspn,strtolower,strtoupper,strtr,' . 'substr_compare,substr_count,substr_replace,trim,ucfirst,ucwords,' . 'wordwrap,floatval,strval,implode,explode');
  47
  48define('DIV_PHP_VALID_TOKENS_FOR_EXPRESSIONS', 'T_ARRAY,T_ARRAY_CAST,T_BOOLEAN_AND,T_BOOLEAN_OR,T_BOOL_CAST,' . 'T_CHARACTER,T_CONSTANT_ENCAPSED_STRING,T_DNUMBER,T_DOUBLE_CAST,' . 'T_EMPTY,T_INT_CAST,T_ISSET,T_IS_EQUAL,T_IS_GREATER_OR_EQUAL,' . 'T_SR,T_IS_IDENTICAL,T_IS_NOT_EQUAL,T_IS_NOT_IDENTICAL,' . 'T_IS_SMALLER_OR_EQUAL,T_LNUMBER,T_LOGICAL_AND,T_LOGICAL_OR,T_LOGICAL_XOR,' . 'T_SL,T_SL_EQUAL,T_SR_EQUAL,T_STRING_CAST,T_STRING_VARNAME,T_VARIABLE,' . 'T_WHITESPACE,T_CURLY_OPEN,T_INC,T_COMMENT,T_DOUBLE_ARROW,' . 'T_ENCAPSED_AND_WHITESPACE');
  49
  50define('DIV_PHP_VALID_TOKENS_FOR_MACROS', 'T_AS,T_DO,T_DOUBLE_COLON,T_ECHO,T_ELSE,T_ELSEIF,T_FOR,T_FOREACH,T_IF,' . 'T_MOD_EQUAL,T_MUL_EQUAL,T_OBJECT_OPERATOR,T_NUM_STRING,T_OR_EQUAL,' . 'T_PAAMAYIM_NEKUDOTAYIM,T_PLUS_EQUAL,T_PRINT,' . 'T_START_HEREDOC,T_SWITCH,T_WHILE,' . 'T_ENDIF,T_ENDFOR,T_ENDFOREACH,T_ENDSWITCH,T_ENDWHILE,T_END_HEREDOC,' . 'T_PAAMAYIM_NEKUDOTAYIM');
  51
  52define('DIV_PHP_ALLOWED_METHODS', 'getRanges,asThis,atLeastOneString,getLastKeyOfArray,getCountOfParagraphs,getCountOfSentences,getCountOfWords,' . 'htmlToText,isArrayOfArray,isArrayOfObjects,isCli,isNumericList,jsonDecode,jsonEncode,isString,mixedBool');
  53
  54define('DIV_ERROR_WARNING', 'WARNING');
  55define('DIV_ERROR_FATAL', 'FATAL');
  56define('DIV_METHOD_NOT_EXISTS', 'DIV_METHOD_NOT_EXISTS');
  57define('DIV_UNICODE_ERROR', - 1);
  58
  59define('DIV_MOMENT_BEFORE_PARSE', 'DIV_MOMENT_BEFORE_PARSE');
  60define('DIV_MOMENT_AFTER_PARSE', 'DIV_MOMENT_AFTER_PARSE');
  61define('DIV_MOMENT_AFTER_INCLUDE', 'DIV_MOMENT_AFTER_INCLUDE');
  62define('DIV_MOMENT_AFTER_REPLACE', 'DIV_MOMENT_AFTER_REPLACE');
  63
  64// ------------------------------------- D E F A U L T D I A L E C T --------------------------------------//
  65if (! defined('DIV_TAG_REPLACEMENT_PREFIX'))
  66	define('DIV_TAG_REPLACEMENT_PREFIX', '{'); // Variables
  67if (! defined('DIV_TAG_REPLACEMENT_SUFFIX'))
  68	define('DIV_TAG_REPLACEMENT_SUFFIX', '}');
  69if (! defined('DIV_TAG_MULTI_MODIFIERS_PREFIX'))
  70	define('DIV_TAG_MULTI_MODIFIERS_PREFIX', '{$');
  71if (! defined('DIV_TAG_MULTI_MODIFIERS_OPERATOR'))
  72	define('DIV_TAG_MULTI_MODIFIERS_OPERATOR', '|');
  73if (! defined('DIV_TAG_MULTI_MODIFIERS_SEPARATOR'))
  74	define('DIV_TAG_MULTI_MODIFIERS_SEPARATOR', '|');
  75if (! defined('DIV_TAG_MULTI_MODIFIERS_SUFFIX'))
  76	define('DIV_TAG_MULTI_MODIFIERS_SUFFIX', '|}');
  77if (! defined('DIV_TAG_SUBMATCH_SEPARATOR'))
  78	define('DIV_TAG_SUBMATCH_SEPARATOR', ':');
  79if (! defined('DIV_TAG_MODIFIER_SIMPLE'))
  80	define('DIV_TAG_MODIFIER_SIMPLE', '$'); // Variable's modifiers
  81if (! defined('DIV_TAG_MODIFIER_CAPITALIZE_FIRST'))
  82	define('DIV_TAG_MODIFIER_CAPITALIZE_FIRST', '^');
  83if (! defined('DIV_TAG_MODIFIER_CAPITALIZE_WORDS'))
  84	define('DIV_TAG_MODIFIER_CAPITALIZE_WORDS', '^^');
  85if (! defined('DIV_TAG_MODIFIER_UPPERCASE'))
  86	define('DIV_TAG_MODIFIER_UPPERCASE', '^^^');
  87if (! defined('DIV_TAG_MODIFIER_LOWERCASE'))
  88	define('DIV_TAG_MODIFIER_LOWERCASE', '_');
  89if (! defined('DIV_TAG_MODIFIER_LENGTH'))
  90	define('DIV_TAG_MODIFIER_LENGTH', '%');
  91if (! defined('DIV_TAG_MODIFIER_COUNT_WORDS'))
  92	define('DIV_TAG_MODIFIER_COUNT_WORDS', '%%');
  93if (! defined('DIV_TAG_MODIFIER_COUNT_SENTENCES'))
  94	define('DIV_TAG_MODIFIER_COUNT_SENTENCES', '%%%');
  95if (! defined('DIV_TAG_MODIFIER_COUNT_PARAGRAPHS'))
  96	define('DIV_TAG_MODIFIER_COUNT_PARAGRAPHS', '%%%%');
  97if (! defined('DIV_TAG_MODIFIER_ENCODE_URL'))
  98	define('DIV_TAG_MODIFIER_ENCODE_URL', '&');
  99if (! defined('DIV_TAG_MODIFIER_ENCODE_RAW_URL'))
 100	define('DIV_TAG_MODIFIER_ENCODE_RAW_URL', '&&');
 101if (! defined('DIV_TAG_MODIFIER_ENCODE_JSON'))
 102	define('DIV_TAG_MODIFIER_ENCODE_JSON', 'json:');
 103if (! defined('DIV_TAG_MODIFIER_HTML_ENTITIES'))
 104	define('DIV_TAG_MODIFIER_HTML_ENTITIES', 'html:');
 105if (! defined('DIV_TAG_MODIFIER_NL2BR'))
 106	define('DIV_TAG_MODIFIER_NL2BR', 'br:');
 107if (! defined('DIV_TAG_MODIFIER_TRUNCATE'))
 108	define('DIV_TAG_MODIFIER_TRUNCATE', '~');
 109if (! defined('DIV_TAG_MODIFIER_WORDWRAP'))
 110	define('DIV_TAG_MODIFIER_WORDWRAP', '/');
 111if (! defined('DIV_TAG_MODIFIER_SUBSTRING_SEPARATOR'))
 112	define('DIV_TAG_MODIFIER_SUBSTRING_SEPARATOR', ',');
 113if (! defined('DIV_TAG_MODIFIER_SINGLE_QUOTES'))
 114	define('DIV_TAG_MODIFIER_SINGLE_QUOTES', "'");
 115if (! defined('DIV_TAG_MODIFIER_JS'))
 116	define('DIV_TAG_MODIFIER_JS', "js:");
 117if (! defined('DIV_TAG_MODIFIER_FORMAT'))
 118	define('DIV_TAG_MODIFIER_FORMAT', '');
 119if (! defined('DIV_TAG_DATE_FORMAT_PREFIX'))
 120	define('DIV_TAG_DATE_FORMAT_PREFIX', '{/'); // Data format
 121if (! defined('DIV_TAG_DATE_FORMAT_SUFFIX'))
 122	define('DIV_TAG_DATE_FORMAT_SUFFIX', '/}');
 123if (! defined('DIV_TAG_DATE_FORMAT_SEPARATOR'))
 124	define('DIV_TAG_DATE_FORMAT_SEPARATOR', ':');
 125if (! defined('DIV_TAG_NUMBER_FORMAT_PREFIX'))
 126	define('DIV_TAG_NUMBER_FORMAT_PREFIX', '{#');
 127if (! defined('DIV_TAG_NUMBER_FORMAT_SUFFIX'))
 128	define('DIV_TAG_NUMBER_FORMAT_SUFFIX', '#}');
 129if (! defined('DIV_TAG_NUMBER_FORMAT_SEPARATOR'))
 130	define('DIV_TAG_NUMBER_FORMAT_SEPARATOR', ':');
 131if (! defined('DIV_TAG_FORMULA_BEGIN'))
 132	define('DIV_TAG_FORMULA_BEGIN', '(#'); // Formulas
 133if (! defined('DIV_TAG_FORMULA_END'))
 134	define('DIV_TAG_FORMULA_END', '#)');
 135if (! defined('DIV_TAG_FORMULA_FORMAT_SEPARATOR'))
 136	define('DIV_TAG_FORMULA_FORMAT_SEPARATOR', ':');
 137if (! defined('DIV_TAG_SUBPARSER_BEGIN_PREFIX'))
 138	define('DIV_TAG_SUBPARSER_BEGIN_PREFIX', '{'); // Sub-parsers
 139if (! defined('DIV_TAG_SUBPARSER_BEGIN_SUFFIX'))
 140	define('DIV_TAG_SUBPARSER_BEGIN_SUFFIX', '}');
 141if (! defined('DIV_TAG_SUBPARSER_END_PREFIX'))
 142	define('DIV_TAG_SUBPARSER_END_PREFIX', '{/');
 143if (! defined('DIV_TAG_SUBPARSER_END_SUFFIX'))
 144	define('DIV_TAG_SUBPARSER_END_SUFFIX', '}');
 145if (! defined('DIV_TAG_IGNORE_BEGIN'))
 146	define('DIV_TAG_IGNORE_BEGIN', '{ignore}'); // Ignored parts
 147if (! defined('DIV_TAG_IGNORE_END'))
 148	define('DIV_TAG_IGNORE_END', '{/ignore}');
 149if (! defined('DIV_TAG_COMMENT_BEGIN'))
 150	define('DIV_TAG_COMMENT_BEGIN', '<!--{'); // Comments
 151if (! defined('DIV_TAG_COMMENT_END'))
 152	define('DIV_TAG_COMMENT_END', '}-->');
 153if (! defined('DIV_TAG_TXT_BEGIN'))
 154	define('DIV_TAG_TXT_BEGIN', '{txt}'); // HTML to Plain text
 155if (! defined('DIV_TAG_TXT_END'))
 156	define('DIV_TAG_TXT_END', '{/txt}');
 157if (! defined('DIV_TAG_TXT_WIDTH_SEPARATOR'))
 158	define('DIV_TAG_TXT_WIDTH_SEPARATOR', '=>');
 159if (! defined('DIV_TAG_STRIP_BEGIN'))
 160	define('DIV_TAG_STRIP_BEGIN', '{strip}'); // Strip
 161if (! defined('DIV_TAG_STRIP_END'))
 162	define('DIV_TAG_STRIP_END', '{/strip}');
 163if (! defined('DIV_TAG_LOOP_BEGIN_PREFIX'))
 164	define('DIV_TAG_LOOP_BEGIN_PREFIX', '[$'); // Loops
 165if (! defined('DIV_TAG_LOOP_BEGIN_SUFFIX'))
 166	define('DIV_TAG_LOOP_BEGIN_SUFFIX', ']');
 167if (! defined('DIV_TAG_LOOP_END_PREFIX'))
 168	define('DIV_TAG_LOOP_END_PREFIX', '[/$');
 169if (! defined('DIV_TAG_LOOP_END_SUFFIX'))
 170	define('DIV_TAG_LOOP_END_SUFFIX', ']');
 171if (! defined('DIV_TAG_EMPTY'))
 172	define('DIV_TAG_EMPTY', '@empty@');
 173if (! defined('DIV_TAG_BREAK'))
 174	define('DIV_TAG_BREAK', '@break@');
 175if (! defined('DIV_TAG_LOOP_VAR_SEPARATOR'))
 176	define('DIV_TAG_LOOP_VAR_SEPARATOR', '=>');
 177if (! defined('DIV_TAG_ITERATION_BEGIN_PREFIX'))
 178	define('DIV_TAG_ITERATION_BEGIN_PREFIX', '[:'); // Iterations
 179if (! defined('DIV_TAG_ITERATION_BEGIN_SUFFIX'))
 180	define('DIV_TAG_ITERATION_BEGIN_SUFFIX', ':]');
 181if (! defined('DIV_TAG_ITERATION_END'))
 182	define('DIV_TAG_ITERATION_END', '[/]');
 183if (! defined('DIV_TAG_ITERATION_PARAM_SEPARATOR'))
 184	define('DIV_TAG_ITERATION_PARAM_SEPARATOR', ',');
 185if (! defined('DIV_TAG_CONDITIONAL_TRUE_BEGIN_PREFIX'))
 186	define('DIV_TAG_CONDITIONAL_TRUE_BEGIN_PREFIX', '?$'); // Conditional parts
 187if (! defined('DIV_TAG_CONDITIONAL_TRUE_BEGIN_SUFFIX'))
 188	define('DIV_TAG_CONDITIONAL_TRUE_BEGIN_SUFFIX', '');
 189if (! defined('DIV_TAG_CONDITIONAL_TRUE_END_PREFIX'))
 190	define('DIV_TAG_CONDITIONAL_TRUE_END_PREFIX', '$');
 191if (! defined('DIV_TAG_CONDITIONAL_TRUE_END_SUFFIX'))
 192	define('DIV_TAG_CONDITIONAL_TRUE_END_SUFFIX', '?');
 193if (! defined('DIV_TAG_CONDITIONAL_FALSE_BEGIN_PREFIX'))
 194	define('DIV_TAG_CONDITIONAL_FALSE_BEGIN_PREFIX', '!$');
 195if (! defined('DIV_TAG_CONDITIONAL_FALSE_BEGIN_SUFFIX'))
 196	define('DIV_TAG_CONDITIONAL_FALSE_BEGIN_SUFFIX', '');
 197if (! defined('DIV_TAG_CONDITIONAL_FALSE_END_PREFIX'))
 198	define('DIV_TAG_CONDITIONAL_FALSE_END_PREFIX', '$');
 199if (! defined('DIV_TAG_CONDITIONAL_FALSE_END_SUFFIX'))
 200	define('DIV_TAG_CONDITIONAL_FALSE_END_SUFFIX', '!');
 201if (! defined('DIV_TAG_ELSE'))
 202	define('DIV_TAG_ELSE', '@else@');
 203if (! defined('DIV_TAG_CONDITIONS_BEGIN_PREFIX'))
 204	define('DIV_TAG_CONDITIONS_BEGIN_PREFIX', '{?('); // Conditions
 205if (! defined('DIV_TAG_CONDITIONS_BEGIN_SUFFIX'))
 206	define('DIV_TAG_CONDITIONS_BEGIN_SUFFIX', ')?}');
 207if (! defined('DIV_TAG_CONDITIONS_END'))
 208	define('DIV_TAG_CONDITIONS_END', '{/?}');
 209if (! defined('DIV_TAG_TPLVAR_BEGIN'))
 210	define('DIV_TAG_TPLVAR_BEGIN', '{='); // Template vars
 211if (! defined('DIV_TAG_TPLVAR_END'))
 212	define('DIV_TAG_TPLVAR_END', '=}');
 213if (! defined('DIV_TAG_TPLVAR_ASSIGN_OPERATOR'))
 214	define('DIV_TAG_TPLVAR_ASSIGN_OPERATOR', ':');
 215if (! defined('DIV_TAG_TPLVAR_PROTECTOR'))
 216	define('DIV_TAG_TPLVAR_PROTECTOR', '*');
 217if (! defined('DIV_TAG_DEFAULT_REPLACEMENT_BEGIN'))
 218	define('DIV_TAG_DEFAULT_REPLACEMENT_BEGIN', '{@'); // Default replacement
 219if (! defined('DIV_TAG_DEFAULT_REPLACEMENT_END'))
 220	define('DIV_TAG_DEFAULT_REPLACEMENT_END', '@}');
 221if (! defined('DIV_TAG_INCLUDE_BEGIN'))
 222	define('DIV_TAG_INCLUDE_BEGIN', '{% '); // Includes
 223if (! defined('DIV_TAG_INCLUDE_END'))
 224	define('DIV_TAG_INCLUDE_END', ' %}');
 225if (! defined('DIV_TAG_PREPROCESSED_BEGIN'))
 226	define('DIV_TAG_PREPROCESSED_BEGIN', '{%% '); // Pre-processed
 227if (! defined('DIV_TAG_PREPROCESSED_END'))
 228	define('DIV_TAG_PREPROCESSED_END', ' %%}');
 229if (! defined('DIV_TAG_CAPSULE_BEGIN_PREFIX'))
 230	define('DIV_TAG_CAPSULE_BEGIN_PREFIX', '[['); // Capsules
 231if (! defined('DIV_TAG_CAPSULE_BEGIN_SUFFIX'))
 232	define('DIV_TAG_CAPSULE_BEGIN_SUFFIX', '');
 233if (! defined('DIV_TAG_CAPSULE_END_PREFIX'))
 234	define('DIV_TAG_CAPSULE_END_PREFIX', '');
 235if (! defined('DIV_TAG_CAPSULE_END_SUFFIX'))
 236	define('DIV_TAG_CAPSULE_END_SUFFIX', ']]');
 237if (! defined('DIV_TAG_MULTI_REPLACEMENT_BEGIN_PREFIX'))
 238	define('DIV_TAG_MULTI_REPLACEMENT_BEGIN_PREFIX', '{:'); // Multi replacements
 239if (! defined('DIV_TAG_MULTI_REPLACEMENT_BEGIN_SUFFIX'))
 240	define('DIV_TAG_MULTI_REPLACEMENT_BEGIN_SUFFIX', '}');
 241if (! defined('DIV_TAG_MULTI_REPLACEMENT_END_PREFIX'))
 242	define('DIV_TAG_MULTI_REPLACEMENT_END_PREFIX', '{:/');
 243if (! defined('DIV_TAG_MULTI_REPLACEMENT_END_SUFFIX'))
 244	define('DIV_TAG_MULTI_REPLACEMENT_END_SUFFIX', '}');
 245if (! defined('DIV_TAG_FRIENDLY_BEGIN'))
 246	define('DIV_TAG_FRIENDLY_BEGIN', '<!--|'); // Friendly tags
 247if (! defined('DIV_TAG_FRIENDLY_END'))
 248	define('DIV_TAG_FRIENDLY_END', '|-->');
 249if (! defined('DIV_TAG_AGGREGATE_FUNCTION_COUNT'))
 250	define('DIV_TAG_AGGREGATE_FUNCTION_COUNT', 'count'); // Aggregate functions
 251if (! defined('DIV_TAG_AGGREGATE_FUNCTION_MAX'))
 252	define('DIV_TAG_AGGREGATE_FUNCTION_MAX', 'max');
 253if (! defined('DIV_TAG_AGGREGATE_FUNCTION_MIN'))
 254	define('DIV_TAG_AGGREGATE_FUNCTION_MIN', 'min');
 255if (! defined('DIV_TAG_AGGREGATE_FUNCTION_SUM'))
 256	define('DIV_TAG_AGGREGATE_FUNCTION_SUM', 'sum');
 257if (! defined('DIV_TAG_AGGREGATE_FUNCTION_AVG'))
 258	define('DIV_TAG_AGGREGATE_FUNCTION_AVG', 'avg');
 259if (! defined('DIV_TAG_AGGREGATE_FUNCTION_SEPARATOR'))
 260	define('DIV_TAG_AGGREGATE_FUNCTION_SEPARATOR', ':');
 261if (! defined('DIV_TAG_AGGREGATE_FUNCTION_PROPERTY_SEPARATOR'))
 262	define('DIV_TAG_AGGREGATE_FUNCTION_PROPERTY_SEPARATOR', '-');
 263if (! defined('DIV_TAG_LOCATION_BEGIN'))
 264	define('DIV_TAG_LOCATION_BEGIN', '(( '); // Locations
 265if (! defined('DIV_TAG_LOCATION_END'))
 266	define('DIV_TAG_LOCATION_END', ' ))');
 267if (! defined('DIV_TAG_LOCATION_CONTENT_BEGIN_PREFIX'))
 268	define('DIV_TAG_LOCATION_CONTENT_BEGIN_PREFIX', '{{');
 269if (! defined('DIV_TAG_LOCATION_CONTENT_BEGIN_SUFFIX'))
 270	define('DIV_TAG_LOCATION_CONTENT_BEGIN_SUFFIX', '');
 271if (! defined('DIV_TAG_LOCATION_CONTENT_END_PREFIX'))
 272	define('DIV_TAG_LOCATION_CONTENT_END_PREFIX', '');
 273if (! defined('DIV_TAG_LOCATION_CONTENT_END_SUFFIX'))
 274	define('DIV_TAG_LOCATION_CONTENT_END_SUFFIX', '}}');
 275if (! defined('DIV_TAG_MACRO_BEGIN'))
 276	define('DIV_TAG_MACRO_BEGIN', '<?'); // Macros
 277if (! defined('DIV_TAG_MACRO_END'))
 278	define('DIV_TAG_MACRO_END', '?>');
 279if (! defined('DIV_TAG_SPECIAL_REPLACE_NEW_LINE'))
 280	define('DIV_TAG_SPECIAL_REPLACE_NEW_LINE', '{\n}'); // Special replacements
 281if (! defined('DIV_TAG_SPECIAL_REPLACE_CAR_RETURN'))
 282	define('DIV_TAG_SPECIAL_REPLACE_CAR_RETURN', '{\r}');
 283if (! defined('DIV_TAG_SPECIAL_REPLACE_HORIZONTAL_TAB'))
 284	define('DIV_TAG_SPECIAL_REPLACE_HORIZONTAL_TAB', '{\t}');
 285if (! defined('DIV_TAG_SPECIAL_REPLACE_VERTICAL_TAB'))
 286	define('DIV_TAG_SPECIAL_REPLACE_VERTICAL_TAB', '{\v}');
 287if (! defined('DIV_TAG_SPECIAL_REPLACE_NEXT_PAGE'))
 288	define('DIV_TAG_SPECIAL_REPLACE_NEXT_PAGE', '{\f}');
 289if (! defined('DIV_TAG_SPECIAL_REPLACE_DOLLAR_SYMBOL'))
 290	define('DIV_TAG_SPECIAL_REPLACE_DOLLAR_SYMBOL', '{\$}');
 291if (! defined('DIV_TAG_TEASER_BREAK'))
 292	define('DIV_TAG_TEASER_BREAK', '<!--break-->');
 293
 294define('DIV_DEFAULT_DIALECT', '{
 295		\'DIV_TAG_REPLACEMENT_PREFIX\' : \'{\',		    \'DIV_TAG_REPLACEMENT_SUFFIX\' : \'}\',
 296		\'DIV_TAG_MULTI_MODIFIERS_PREFIX\' : \'{$\',	\'DIV_TAG_MULTI_MODIFIERS_SEPARATOR\' : \'|\',
 297		\'DIV_TAG_MULTI_MODIFIERS_OPERATOR\' : \'|\',	\'DIV_TAG_MULTI_MODIFIERS_SUFFIX\' : \'|}\',
 298		\'DIV_TAG_SUBMATCH_SEPARATOR\' : \':\',		    \'DIV_TAG_MODIFIER_SIMPLE\' : \'$\',
 299		\'DIV_TAG_MODIFIER_CAPITALIZE_FIRST\' : \'^\',	\'DIV_TAG_MODIFIER_CAPITALIZE_WORDS\' : \'^^\',
 300		\'DIV_TAG_MODIFIER_UPPERCASE\' : \'^^^\',		\'DIV_TAG_MODIFIER_LOWERCASE\' : \'_\',
 301		\'DIV_TAG_MODIFIER_LENGTH\' : \'%\',		    \'DIV_TAG_MODIFIER_COUNT_WORDS\' : \'%%\',
 302		\'DIV_TAG_MODIFIER_COUNT_SENTENCES\' : \'%%%\',	\'DIV_TAG_MODIFIER_COUNT_PARAGRAPHS\' : \'%%%%\',
 303		\'DIV_TAG_MODIFIER_ENCODE_URL\' : \'&\',		\'DIV_TAG_MODIFIER_ENCODE_RAW_URL\' : \'&&\',
 304		\'DIV_TAG_MODIFIER_ENCODE_JSON\' : \'json:\',	\'DIV_TAG_MODIFIER_HTML_ENTITIES\' : \'html:\',
 305		\'DIV_TAG_MODIFIER_NL2BR\' : \'br:\',		    \'DIV_TAG_MODIFIER_TRUNCATE\' : \'~\',
 306		\'DIV_TAG_MODIFIER_WORDWRAP\' : \'/\',		    \'DIV_TAG_MODIFIER_SUBSTRING_SEPARATOR\' : \',\',
 307		\'DIV_TAG_MODIFIER_SINGLE_QUOTES\' : "\'",		\'DIV_TAG_MODIFIER_JS\' :  \'js:\',
 308		\'DIV_TAG_MODIFIER_FORMAT\' : \'\',		        \'DIV_TAG_DATE_FORMAT_PREFIX\' : \'{/\',
 309		\'DIV_TAG_DATE_FORMAT_SUFFIX\' : \'/}\',		\'DIV_TAG_DATE_FORMAT_SEPARATOR\' : \':\',
 310		\'DIV_TAG_NUMBER_FORMAT_PREFIX\' : \'{#\',		\'DIV_TAG_NUMBER_FORMAT_SUFFIX\' : \'#}\',
 311		\'DIV_TAG_NUMBER_FORMAT_SEPARATOR\' : \':\',	\'DIV_TAG_FORMULA_BEGIN\' : \'(#\',
 312		\'DIV_TAG_FORMULA_END\' : \'#)\',		        \'DIV_TAG_FORMULA_FORMAT_SEPARATOR\' : \':\',
 313		\'DIV_TAG_SUBPARSER_BEGIN_PREFIX\' : \'{\',		\'DIV_TAG_SUBPARSER_BEGIN_SUFFIX\' : \'}\',
 314		\'DIV_TAG_SUBPARSER_END_PREFIX\' : \'{/\',		\'DIV_TAG_SUBPARSER_END_SUFFIX\' : \'}\',
 315		\'DIV_TAG_IGNORE_BEGIN\' : \'{ignore}\',		\'DIV_TAG_IGNORE_END\' : \'{/ignore}\',
 316		\'DIV_TAG_COMMENT_BEGIN\' : \'<!--{\',		    \'DIV_TAG_COMMENT_END\' : \'}-->\',
 317		\'DIV_TAG_TXT_BEGIN\' : \'{txt}\',		        \'DIV_TAG_TXT_END\' : \'{/txt}\',			
 318		\'DIV_TAG_TXT_WIDTH_SEPARATOR\' : \'=>\',		\'DIV_TAG_STRIP_BEGIN\' : \'{strip}\',
 319		\'DIV_TAG_STRIP_END\' : \'{/strip}\',		    \'DIV_TAG_LOOP_BEGIN_PREFIX\' : \'[$\',
 320		\'DIV_TAG_LOOP_BEGIN_SUFFIX\' : \']\',		    \'DIV_TAG_LOOP_END_PREFIX\' : \'[/$\',
 321		\'DIV_TAG_LOOP_END_SUFFIX\' : \']\',		    \'DIV_TAG_EMPTY\' : \'@empty@\',
 322		\'DIV_TAG_BREAK\' : \'@break@\',		        \'DIV_TAG_LOOP_VAR_SEPARATOR\' : \'=>\',
 323		\'DIV_TAG_ITERATION_BEGIN_PREFIX\' : \'[:\',	\'DIV_TAG_ITERATION_BEGIN_SUFFIX\' : \':]\',
 324		\'DIV_TAG_ITERATION_END\' : \'[/]\',		                \'DIV_TAG_ITERATION_PARAM_SEPARATOR\' : \',\',
 325		\'DIV_TAG_CONDITIONAL_TRUE_BEGIN_PREFIX\' :  \'?$\',	    \'DIV_TAG_CONDITIONAL_TRUE_BEGIN_SUFFIX\' : \'\',
 326		\'DIV_TAG_CONDITIONAL_TRUE_END_PREFIX\' :    \'$\',		    \'DIV_TAG_CONDITIONAL_TRUE_END_SUFFIX\' : \'?\',
 327		\'DIV_TAG_CONDITIONAL_FALSE_BEGIN_PREFIX\' : \'!$\',	    \'DIV_TAG_CONDITIONAL_FALSE_BEGIN_SUFFIX\' : \'\',
 328		\'DIV_TAG_CONDITIONAL_FALSE_END_PREFIX\' :   \'$\',	        \'DIV_TAG_CONDITIONAL_FALSE_END_SUFFIX\' : \'!\',
 329		\'DIV_TAG_ELSE\' : \'@else@\',		                        \'DIV_TAG_CONDITIONS_BEGIN_PREFIX\' : \'{?(\',
 330		\'DIV_TAG_CONDITIONS_BEGIN_SUFFIX\' : \')?}\',		        \'DIV_TAG_CONDITIONS_END\' : \'{/?}\',
 331		\'DIV_TAG_TPLVAR_BEGIN\' : \'{=\',		                    \'DIV_TAG_TPLVAR_END\' : \'=}\',
 332		\'DIV_TAG_TPLVAR_ASSIGN_OPERATOR\' : \':\',		            \'DIV_TAG_TPLVAR_PROTECTOR\' : \'*\',
 333		\'DIV_TAG_DEFAULT_REPLACEMENT_BEGIN\' : \'{@\',		        \'DIV_TAG_DEFAULT_REPLACEMENT_END\' : \'@}\',
 334		\'DIV_TAG_INCLUDE_BEGIN\' : \'{% \',		                \'DIV_TAG_INCLUDE_END\' : \' %}\',
 335		\'DIV_TAG_PREPROCESSED_BEGIN\' : \'{%% \',		            \'DIV_TAG_PREPROCESSED_END\' : \' %%}\',
 336		\'DIV_TAG_CAPSULE_BEGIN_PREFIX\' : \'[[\',		            \'DIV_TAG_CAPSULE_BEGIN_SUFFIX\' : \'\',
 337		\'DIV_TAG_CAPSULE_END_PREFIX\' : \'\',		                \'DIV_TAG_CAPSULE_END_SUFFIX\' : \']]\',
 338		\'DIV_TAG_MULTI_REPLACEMENT_BEGIN_PREFIX\' : \'{:\', 	    \'DIV_TAG_MULTI_REPLACEMENT_BEGIN_SUFFIX\' : \'}\',
 339		\'DIV_TAG_MULTI_REPLACEMENT_END_PREFIX\' : \'{:/\',		    \'DIV_TAG_MULTI_REPLACEMENT_END_SUFFIX\' : \'}\',
 340		\'DIV_TAG_FRIENDLY_BEGIN\' : \'<!--|\',		                \'DIV_TAG_FRIENDLY_END\' : \'|-->\',
 341		\'DIV_TAG_AGGREGATE_FUNCTION_COUNT\' : \'count\',		    \'DIV_TAG_AGGREGATE_FUNCTION_MAX\' : \'max\',
 342		\'DIV_TAG_AGGREGATE_FUNCTION_MIN\' : \'min\',		        \'DIV_TAG_AGGREGATE_FUNCTION_SUM\' : \'sum\',
 343		\'DIV_TAG_AGGREGATE_FUNCTION_AVG\' : \'avg\',		        \'DIV_TAG_AGGREGATE_FUNCTION_SEPARATOR\' : \':\',
 344		\'DIV_TAG_AGGREGATE_FUNCTION_PROPERTY_SEPARATOR\' : \'-\',	\'DIV_TAG_LOCATION_BEGIN\' : \'(( \',
 345		\'DIV_TAG_LOCATION_END\' : \' ))\',		                    \'DIV_TAG_LOCATION_CONTENT_BEGIN_PREFIX\' : \'{{\',
 346		\'DIV_TAG_LOCATION_CONTENT_BEGIN_SUFFIX\' : \'\',		    \'DIV_TAG_LOCATION_CONTENT_END_PREFIX\' : \'\',
 347		\'DIV_TAG_LOCATION_CONTENT_END_SUFFIX\' : \'}}\',		    \'DIV_TAG_MACRO_BEGIN\' : \'<?\',
 348		\'DIV_TAG_MACRO_END\' : \'?>\',		                        \'DIV_TAG_SPECIAL_REPLACE_NEW_LINE\' : \'{\\n}\',
 349		\'DIV_TAG_SPECIAL_REPLACE_CAR_RETURN\' : \'{\\r}\',		    \'DIV_TAG_SPECIAL_REPLACE_HORIZONTAL_TAB\' : \'{\\t}\',
 350		\'DIV_TAG_SPECIAL_REPLACE_VERTICAL_TAB\' : \'{\\v}\',		\'DIV_TAG_SPECIAL_REPLACE_NEXT_PAGE\' : \'{\\f}\',
 351		\'DIV_TAG_SPECIAL_REPLACE_DOLLAR_SYMBOL\' : \'{\\$}\',		\'DIV_TAG_TEASER_BREAK\' : \'<!--break-->\'
 352		}');
 353
 354// --------------------------------------------------------------------------------------------------------------------------------------//
 355
 356define('DIV_TEMPLATE_FOR_DOCS', '
 357@_DIALECT = ' . uniqid() . '
 358<html>
 359	<head>
 360		<title>{$title}</title>
 361		<style type="text/css">
 362			body          {background: #656565; font-family: Verdana;}
 363			div.section   {background: white;	margin-top: 20px; padding: 10px; width: 780px;}
 364			.section h2   {color: white; font-size: 24px;font-weight: bold; margin-left: -30px;padding-bottom: 5px; padding-left: 30px;padding-top: 5px; background: black; border-left: 10px solid gray;}	
 365			h1            {color: white;}
 366			table.data td {padding: 5px;border-bottom: 1px solid gray; border-right: 1px solid gray;}
 367			table.data th {padding: 5px;color: white; background: black;}
 368			.code         {padding: 0px; margin: 0px; background: #eeeeee; color: black; font-family: "Courier New"; text-align: left; font-size: 13px;}					
 369			.code .line   {text-align:right; background: gray; color: white; border-right: 2px solid black; padding-right: 5px;}
 370			table.index, table.index a, table.index a:visited {color:white;}					
 371			div.header    {color: white;}
 372			.template-description{background: #eeeeee; padding: 10px;}
 373		</style>
 374	</head>
 375	<body>
 376		<label><a href="#header" style="position: fixed; bottom: 5px; right: 5px;color: white;">Index</a></label>
 377		<table width="750" align="center"><tr><td valign="top">
 378		<div id = "header" class = "header">
 379		<h1>{$title}</h1>
 380		<p>Generated by Div at {/div.now:Y-m-d H:i:s/}</p>
 381		<h2>Index</h2>
 382		<table class="index data" width="100%">
 383			<tr><th></th><th>Name</th><th>Description</th><th>Version</th></tr>
 384			[$docs]
 385				<tr><td>{$_order}</td>
 386				<td><a href="#{$_key}">?$name {$name} $name?</a></td>
 387				<td>?$description {$description} $description?</td>
 388				<td>?$version {$version} $version?</td></tr>
 389			[/$docs]
 390		</table>
 391		</div>
 392		
 393		{= repl1: [["<",""],[">",""]] =}
 394		
 395		[$docs]
 396			<div class="section">
 397				<h2 id = "{$_key}">?$icon {$icon} $icon? {$name}</h2>
 398				<table width="100%">
 399				<tr><td align="right">Path:</td><td>{$_key} </td></tr>
 400				?$type    <tr><td align="right" width="150">Type:</td><td><b>{$type}</b></td></tr>$type?
 401				?$author  <tr><td align="right" width="150">Author:</td><td><b>{html:author}</b></td></tr> $author?
 402				?$version <tr><td align="right" width="150">Version:</td><td><b>{$version}</b></td></tr> $version?
 403				?$update  <tr><td align="right" width="150">Last update:</td><td>{$update} </td></tr>$update?
 404				</table>
 405				<br/>
 406				?$description <p class="template-description">{$description}</p>$description?
 407				?$vars
 408					<h3>Template\'s Variables ({$vars})</h3>
 409					<table class="data">
 410					<tr><th></th><th></th><th>Type</th><th>Name</th><th>Description</th></tr>
 411					[$vars]
 412					
 413						{?( trim("{\'value}") !== "" )?}
 414						<?
 415							$value = trim(str_replace(array("\t","\n","\r")," ", $value));	
 416							while(strpos($value, "  ")) $value = str_replace("  "," ", $value);
 417							$pars = explode(" ", $value, 4);
 418						?>
 419						<tr>
 420							<td>{$_order}</td>
 421							[$pars]
 422							<td>{:repl1}{$value}{:/repl1}</td>
 423							[/$pars]
 424						</tr>
 425						{/?}
 426					[/$vars]
 427					</table>
 428				$vars?
 429				?$include
 430					<h3>Include:</h3>
 431					[$include]
 432						{$_order}. <a href="#{$value}">{$value}</a><br/>
 433					[/$include]
 434				$include?
 435				?$example
 436					<h3>Example:</h3>
 437					<table width = "100%" class="code" cellspacing="0" cellpadding="0">
 438					[$example]
 439							<tr>
 440							<td class="line" width="30">{$_order}</td>
 441							<td><pre class="code">{html_wysiwyg:afterReplace}{$value}{/html_wysiwyg:afterReplace}</pre></td>
 442							</tr>
 443					[/$example]
 444					</table> 
 445				$example?
 446			</div>
 447		[/$docs]
 448		</td></tr></table>
 449	</body>
 450</html>');
 451
 452/**
 453 * The div class is the complete implementation of Div.
 454 *
 455 * See the following example:
 456 *
 457 * echo new div('Hello {$name}', array('name' => 'Peter Pan'));
 458 */
 459class div {
 460	
 461	// Public
 462	public $__src = null;
 463	// template source
 464	public $__src_original = null;
 465	// original template source
 466	public $__items = array();
 467	// template variables
 468	public $__items_orig = array();
 469	// original template variables
 470	public $__memory = array();
 471	// to remember the template variables
 472	public $__path = '';
 473	// path to current template file
 474	public $__ignore = array();
 475	// template variables to ignore
 476	public $__restore = array();
 477	// template's parts to restore after parse
 478	public $__packages = PACKAGES;
 479	// path of current templates's root folder
 480	public $__properties = array();
 481	// properties of the template
 482	// Private
 483	private $__id = null;
 484	// template id
 485	private $__temp = array();
 486	// temporal vars
 487	private $__crc = null;
 488	// template cheksum
 489	// Globals
 490	private static $__custom_modifiers = array();
 491	// custom variable's modifiers
 492	private static $__globals = array();
 493	// global template's variables
 494	private static $__globals_design = array();
 495	// global template's variables defined in the design
 496	private static $__globals_design_protected = array();
 497	// global and protected template variables defined in the design
 498	private static $__defaults = array();
 499	// default value for another value
 500	private static $__defaults_by_var = array();
 501	// default value for another value by variable
 502	private static $__system_data = null;
 503	// system data
 504	private static $__system_data_allowed = array(
 505			'div.version' => true,
 506			'div.post' => true,
 507			'div.get' => true,
 508			'div.now' => true
 509	);
 510	private static $__discard_file_system = false;
 511	// do not load code from files
 512	private static $__allowed_functions = array();
 513	// list of allowed custom functions
 514	private static $__allowed_methods = null;
 515	// list of allowed class's methods
 516	private static $__sub_parsers = array();
 517	// list of subparsers
 518	private static $__docs = array();
 519	// template's documentation
 520	private static $__docs_on = false;
 521	// on/off documentation
 522	private static $__includes_historial = array();
 523	// includes's historial
 524	// Internals
 525	private static $__version = '4.5';
 526	// current version of Div
 527	private static $__super_class = null;
 528	// name of the super class
 529	private static $__parent_method_names = array();
 530	// name of parent class's methods
 531	private static $__method_names = null;
 532	// name of current methods
 533	private static $__parse_duration = null;
 534	// duration of parser
 535	private static $__parse_level = 0;
 536	// current level of parser
 537	private static $__engine = null;
 538	// auxiliary engine
 539	private static $__modifiers = array( // variable's modifiers
 540			DIV_TAG_MODIFIER_SIMPLE,
 541			DIV_TAG_MODIFIER_CAPITALIZE_FIRST,
 542			DIV_TAG_MODIFIER_CAPITALIZE_WORDS,
 543			DIV_TAG_MODIFIER_UPPERCASE,
 544			DIV_TAG_MODIFIER_LOWERCASE,
 545			DIV_TAG_MODIFIER_LENGTH,
 546			DIV_TAG_MODIFIER_COUNT_WORDS,
 547			DIV_TAG_MODIFIER_COUNT_SENTENCES,
 548			DIV_TAG_MODIFIER_COUNT_PARAGRAPHS,
 549			DIV_TAG_MODIFIER_ENCODE_URL,
 550			DIV_TAG_MODIFIER_ENCODE_RAW_URL,
 551			DIV_TAG_MODIFIER_HTML_ENTITIES,
 552			DIV_TAG_MODIFIER_NL2BR,
 553			DIV_TAG_MODIFIER_ENCODE_JSON,
 554			DIV_TAG_MODIFIER_SINGLE_QUOTES,
 555			DIV_TAG_MODIFIER_JS
 556	);
 557	private static $__dialect_checked = false;
 558	// is current dialect checked?
 559	private static $__allowed_php_functions = null;
 560	// allowed PHP functions
 561	private static $__log_mode = false;
 562	// is log mode?
 563	private static $__log_file = null;
 564	// the log filename
 565	private static $__is_cli = null;
 566	// is PHP cli?
 567	private static $__ignored_parts = array();
 568	// ignored parts
 569	private static $__last_id = 0;
 570	// last template id
 571	private static $__remember = array();
 572	// remember previous work
 573	private static $__dont_remember_it = array();
 574	// do not remember it work
 575	private static $__errors = array();
 576	// errors historial
 577	private static $__include_paths = null;
 578	private static $__packages_by_class = array();
 579	
 580	/**
 581	 * Constructor
 582	 *
 583	 * @param string $src
 584	 * @param mixed $items
 585	 * @param array $ignore
 586	 * @return div
 587	 */
 588	public function __construct($src = null, $items = null, $ignore = array()){
 589		
 590		// Validate the current dialect
 591		if (self::$__dialect_checked == false) {
 592			$r = self::isValidCurrentDialect();
 593			if ($r !== true)
 594				self::error('Current dialect is invalid: ' . $r, DIV_ERROR_FATAL);
 595			self::$__dialect_checked = true;
 596		}
 597		
 598		$classname = get_class($this);
 599		
 600		self::$__packages_by_class[$classname] = $this->__packages;
 601		
 602		if (is_null(self::$__super_class))
 603			self::$__super_class = $this->getSuperParent();
 604		if (is_null(self::$__parent_method_names))
 605			self::$__parent_method_names = get_class_methods(self::$__super_class);
 606		
 607		$this->__id = ++ self::$__last_id;
 608		
 609		if (self::$__log_mode)
 610			$this->logger('Building instance #' . $this->__id . ' of ' . $classname . '...');
 611			
 612			// Calling the beforeBuild hook
 613		$this->beforeBuild($src, $items);
 614		
 615		if (is_null($items) && ! is_null($this->__items))
 616			$items = $this->__items;
 617		
 618		$this->__items_orig = $items;
 619		
 620		$decode = true;
 621		
 622		$discardfs = self::$__discard_file_system;
 623		
 624		if (is_null($src)) {
 625			if ($classname != self::$__super_class && is_null($this->__src))
 626				$src = $classname;
 627			if (! is_null($this->__src))
 628				$src = $this->__src;
 629		}
 630		
 631		if (is_null($items)) {
 632			$items = $src;
 633			$items = str_replace('.' . DIV_DEFAULT_TPL_FILE_EXT, '', $items);
 634			$decode = false;
 635		}
 636		
 637		if (! $discardfs) {
 638			if (self::isString($items))
 639				if (strlen($items . '.' . DIV_DEFAULT_DATA_FILE_EXT) < 255) {
 640					$exists = false;
 641					
 642					if (self::fileExists($items)) {
 643						$items = self::getFileContents($items);
 644						$exists = true;
 645					} elseif (self::fileExists($items . '.' . DIV_DEFAULT_DATA_FILE_EXT)) {
 646						$items = self::getFileContents($items . '.' . DIV_DEFAULT_DATA_FILE_EXT);
 647						$exists = true;
 648					}
 649					
 650					if ($exists === true || $decode === true)
 651						$items = self::jsonDecode($items);
 652					if ($exists === true)
 653						break;
 654				}
 655		}
 656		
 657		if (is_object($items)) {
 658			if (method_exists($items, '__toString')) {
 659				$itemstr = "$items";
 660				if (! isset($items->value))
 661					$items->value = $itemstr;
 662				$items->_to_string = $itemstr;
 663			}
 664			$items = get_object_vars($items);
 665		}
 666		
 667		if (! $discardfs)
 668			$src = $this->loadTemplate($src);
 669		
 670		if (! is_array($items))
 671			$items = array();
 672		
 673		$this->__src = $src;
 674		$this->__src_original = $src;
 675		$this->__items = $items;
 676		
 677		if (self::isString($ignore))
 678			$ignore = explode(',', $ignore);
 679		if (isset($ignore[0]))
 680			foreach ( $ignore as $key => $val )
 681				$this->__ignore[$val] = true;
 682			
 683			// Calling the afterBuild hook
 684		$this->afterBuild();
 685		
 686		// Enabling methods
 687		if (is_null(self::$__allowed_methods)) {
 688			$keys = explode(",", DIV_PHP_ALLOWED_METHODS);
 689			;
 690			self::$__allowed_methods = array_combine($keys, $keys);
 691			
 692			if (self::$__super_class != $classname) {
 693				$keys = array_diff(get_class_methods($classname), get_class_methods(self::$__super_class));
 694				if (isset($keys[0]))
 695					self::$__allowed_methods = array_merge(self::$__allowed_methods, array_combine($keys, $keys));
 696			}
 697		}
 698		
 699		// Pre-defined subparsers
 700		
 701		self::setSubParser('parse', 'subParse_parse');
 702		self::setSubParser('html_wysiwyg', 'subParse_html_wysiwyg');
 703	}
 704	
 705	/**
 706	 * Return a list of include_path setting + the PACKAGES
 707	 *
 708	 * @return array
 709	 */
 710	final static function getIncludePaths($packages = PACKAGES){
 711		if (is_null(self::$__include_paths)) {
 712			$os = self::getOperatingSystem();
 713			self::$__include_paths = explode(($os == "win32" ? ";" : ":"), ini_get("include_path"));
 714			self::$__include_paths[] = $packages;
 715		}
 716		return self::$__include_paths;
 717	}
 718	
 719	/**
 720	 * Return the current operating system
 721	 *
 722	 * @return string (win32/linux/unix)
 723	 */
 724	final static function getOperatingSystem(){
 725		if (isset($_SERVER['SERVER_SOFTWARE'])) {
 726			if (isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE)
 727				return "win32";
 728			if (! isset($_SERVER['WINDIR']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Linux') !== FALSE)
 729				return "linux";
 730		}
 731		
 732		if (file_exists("C:\Windows"))
 733			return "win32";
 734		
 735		return "unix";
 736	}
 737	
 738	/**
 739	 * Return the super parent class name
 740	 *
 741	 * @param string $classname
 742	 * @return string
 743	 */
 744	final public function getSuperParent($classname = null){
 745		if (is_null($classname))
 746			$classname = get_class($this);
 747		$parent = get_parent_class($classname);
 748		if ($parent === false)
 749			return $classname;
 750		return $this->getSuperParent($parent);
 751		;
 752	}
 753	
 754	/**
 755	 * Return the current template's id
 756	 *
 757	 * @return integer
 758	 */
 759	final public function getId(){
 760		return $this->__id;
 761	}
 762	
 763	/**
 764	 * Create an auxiliar instance (as singleton)
 765	 *
 766	 * @param string $classname
 767	 */
 768	final static function createAuxiliarEngine(&$from = null){
 769		if (is_null($from))
 770			$classname = self::$__super_class;
 771		else
 772			$classname = get_class($from);
 773		if (! is_null(self::$__engine))
 774			if (get_class(self::$__engine) != $classname)
 775				self::$__engine = null;
 776		if (is_null(self::$__engine)) {
 777			if (self::$__log_mode)
 778				self::log("createAuxiliarEngine: A new $classname instance will be created ...");
 779			$tmp = self::$__discard_file_system;
 780			self::$__discard_file_system = true;
 781			self::$__engine = new $classname("", array());
 782			if (! is_null($from)) {
 783				self::$__engine->__items = $from->__items;
 784				self::$__engine->__items_orig = $from->__items_orig;
 785			}
 786			self::$__discard_file_system = $tmp;
 787		}
 788	}
 789	
 790	/**
 791	 * Create a clone of auxiliary
 792	 *
 793	 * @return div
 794	 */
 795	final static function getAuxiliaryEngineClone(&$items = null, &$items_orig = null){
 796		$obj = clone self::$__engine;
 797		
 798		if (self::$__log_mode)
 799			self::log("getAuxiliaryEngineClone: New auxiliary #" . $obj->getId());
 800		if (! is_null($items))
 801			$obj->__items = $items;
 802		if (! is_null($items_orig))
 803			$obj->__items_orig = $items_orig;
 804		
 805		return $obj;
 806	}
 807	
 808	/**
 809	 * Save parser's operationsd
 810	 *
 811	 * @param array $params
 812	 */
 813	final public function saveOperation($params = array()){
 814		if (! isset(self::$__remember[$this->__crc]))
 815			self::$__remember[$this->__crc] = array();
 816		$id = crc32(serialize($params));
 817		if (! isset(self::$__remember[$this->__crc][$id]))
 818			self::$__remember[$this->__crc][$id] = $params;
 819	}
 820	
 821	/**
 822	 * Add a custom variable's modifier
 823	 *
 824	 * @param string $prefix
 825	 * @param string $function
 826	 */
 827	final static function addCustomModifier($prefix, $function){
 828		self::$__custom_modifiers[$prefix] = array(
 829				$prefix,
 830				$function
 831		);
 832		self::$__modifiers[] = $prefix;
 833	}
 834	
 835	/**
 836	 * Enable system var for utility
 837	 *
 838	 * @param string $var
 839	 */
 840	final static function enableSystemVar($var){
 841		self::$__system_data_allowed[$var] = true;
 842	}
 843	
 844	/**
 845	 * Disable system var for performance
 846	 *
 847	 * @param string $var
 848	 */
 849	final static function disableSystemVar($var){
 850		if (isset(self::$__system_data_allowed[$var]))
 851			unset(self::$__system_data_allowed[$var]);
 852	}
 853	
 854	/**
 855	 * Return the loaded data from the system
 856	 *
 857	 * @return array
 858	 */
 859	final static function getSystemData(){
 860		if (self::$__system_data == null) {
 861			self::$__system_data = array();
 862			if (isset(self::$__system_data_allowed['div.ascii'])) {
 863				$ascii = array();
 864				for($i = 0; $i <= 255; $i ++)
 865					$ascii[$i] = chr($i);
 866				self::$__system_data['div.ascii'] = $ascii;
 867			}
 868			if (isset(self::$__system_data_allowed['div.now']))
 869				self::$__system_data['div.now'] = time();
 870			if (isset(self::$__system_data_allowed['div.post']))
 871				self::$__system_data['div.post'] = $_POST;
 872			if (isset(self::$__system_data_allowed['div.get']))
 873				self::$__system_data['div.get'] = $_GET;
 874			if (isset(self::$__system_data_allowed['div.server']))
 875				self::$__system_data['div.server'] = $_SERVER;
 876			if (isset(self::$__system_data_allowed['div.session']))
 877				self::$__system_data['div.session'] = isset($_SESSION) ? $_SESSION : array();
 878			if (isset(self::$__system_data_allowed['div.version']))
 879				self::$__system_data['div.version'] = self::$__version;
 880			if (isset(self::$__system_data_allowed['div.script_name'])) {
 881				$script_name = explode('/', $_SERVER['SCRIPT_NAME']);
 882				$script_name = $script_name[count($script_name) - 1];
 883				self::$__system_data['div.script_name'] = $script_name;
 884			}
 885		}
 886		return self::$__system_data;
 887	}
 888	
 889	/**
 890	 * Set allowed function
 891	 *
 892	 * @param string $funcname
 893	 */
 894	final static function setAllowedFunction($funcname){
 895		self::$__allowed_functions[$funcname] = true;
 896	}
 897	
 898	/**
 899	 * Unset allowed function
 900	 *
 901	 * @param string $funcname
 902	 */
 903	final static function unsetAllowedFunction($funcname){
 904		self::$__allowed_functions[$funcname] = false;
 905	}
 906	
 907	/**
 908	 * Add or set a global var
 909	 *
 910	 * @param string $var
 911	 * @param mixed $value
 912	 */
 913	final static function setGlobal($var, $value){
 914		self::$__globals[$var] = $value;
 915	}
 916	
 917	/**
 918	 * Remove a global var
 919	 *
 920	 * @param string $var
 921	 */
 922	final static function delGlobal($var){
 923		unset(self::$__globals[$var]);
 924	}
 925	
 926	/**
 927	 * Add or set a default replacement of value
 928	 *
 929	 * @param mixed $search
 930	 * @param mixed $replace
 931	 */
 932	final static function setDefault($search, $replace){
 933		self::$__defaults[serialize($search)] = $replace;
 934	}
 935	
 936	/**
 937	 * Add or set a default replacement of value for a specific var
 938	 *
 939	 * @param string $var
 940	 * @param mixed $search
 941	 * @param mixed $replace
 942	 * @param boolean $update
 943	 */
 944	final static function setDefaultByVar($var, $search, $replace, $update = true){
 945		$id = serialize($search);
 946		if (! isset(self::$__defaults_by_var[$var]))
 947			self::$__defaults_by_var[$var] = array();
 948		if (! isset(self::$__defaults_by_var[$var][$id]) && $update === true)
 949			self::$__defaults_by_var[$var][$id] = $replace;
 950	}
 951	
 952	/**
 953	 * Set a sub-parser
 954	 *
 955	 * @param string $name
 956	 * @param string $function
 957	 */
 958	final static function setSubParser($name, $function = null){
 959		if (is_array($name)) {
 960			if (is_null($function)) {
 961				foreach ( $name as $key => $value ) {
 962					if (is_numeric($key))
 963						self::$__sub_parsers[$value] = $value;
 964					else
 965						self::$__sub_parsers[$key] = $value;
 966				}
 967			} elseif (is_array($function)) {
 968				foreach ( $name as $key => $value )
 969					self::$__sub_parsers[$value] = $function[$key];
 970			} else {
 971				foreach ( $name as $key => $value )
 972					self::$__sub_parsers[$value] = $function;
 973			}
 974		} else {
 975			if (is_null($function))
 976				$function = $name;
 977			self::$__sub_parsers[$name] = $function;
 978		}
 979		self::repairSubparsers();
 980	}
 981	
 982	/**
 983	 * Repair the subparsers and their events
 984	 */
 985	final static function repairSubparsers(){
 986		$events = array(
 987				'beforeParse',
 988				'afterInclude',
 989				'afterParse',
 990				'afterReplace'
 991		);
 992		$news = array();
 993		
 994		foreach ( self::$__sub_parsers as $parser => $function ) {
 995			$arr = explode(":", $parser);
 996			
 997			if (isset($arr[1])) {
 998				$last = array_pop($arr);
 999				if (array_search($last, $events) !== false)
1000					continue;
1001			}
1002			
1003			foreach ( $events as $event )
1004				if (! isset(self::$__sub_parsers["$parser:$event"])) {
1005					$news["$parser:$event"] = $function;
1006				}
1007		}
1008		
1009		self::$__sub_parsers = array_merge(self::$__sub_parsers, $news);
1010	}
1011	
1012	/**
1013	 * Load template from filesystem
1014	 *
1015	 * @param string $path
1016	 * @return string
1017	 */
1018	final public function loadTemplate($path){
1019		if (self::$__log_mode === true)
1020			$this->logger("Loading the template: $path");
1021		
1022		$src = $path;
1023		
1024		if (strlen($path) < 255) {
1025			$paths = array(
1026					$path,
1027					$path . '.' . DIV_DEFAULT_TPL_FILE_EXT,
1028					$path,
1029					$path . '.' . DIV_DEFAULT_TPL_FILE_EXT
1030			);
1031			
1032			foreach ( $paths as $pathx ) {
1033				if (strlen($pathx) < 255)
1034					if (self::fileExists($pathx)) {
1035						$src = self::getFileContents($pathx);
1036						$this->__path = $pathx;
1037						break;
1038					}
1039			}
1040		}
1041		
1042		return $src;
1043	}
1044	
1045	/**
1046	 * Change the template and the original template
1047	 *
1048	 * @param string $src
1049	 */
1050	final public function changeTemplate($src = null){
1051		$decode = true;
1052		$classname = get_class($this);
1053		$discardfs = self::$__discard_file_system;
1054		
1055		if (is_null($src)) {
1056			if ($classname != self::$__super_class && is_null($this->__src))
1057				$src = $classname;
1058			if (! is_null($this->__src))
1059				$src = $this->__src;
1060		}
1061		
1062		if (! $discardfs)
1063			$src = $this->loadTemplate($src);
1064		
1065		$this->__src = $src;
1066		$this->__src_original = $src;
1067	}
1068	
1069	/**
1070	 * Return the code of current template
1071	 *
1072	 * @return string
1073	 */
1074	final public function getTemplate(){
1075		return $this->__src;
1076	}
1077	
1078	/**
1079	 * Return the original code of template
1080	 *
1081	 * @return string
1082	 */
1083	final public function getOriginalTemplate(){
1084		return $this->__src_original;
1085	}
1086	
1087	/**
1088	 * Remove a default replacement
1089	 *
1090	 * @param mixed $search
1091	 */
1092	final static function delDefault($search){
1093		$id = serialize($search);
1094		if (isset(self::$__defaults[$id]))
1095			unset(self::$__defaults[$id]);
1096	}
1097	
1098	/**
1099	 * Remove a default replacement by var
1100	 *
1101	 * @param string $var
1102	 * @param mixed $search
1103	 */
1104	final static function delDefaultByVar($var, $search){
1105		if (isset(self::$__defaults_by_var[$var])) {
1106			$id = serialize($search);
1107			if (isset(self::$__defaults_by_var[$var][$id]))
1108				unset(self::$__defaults_by_var[$var][$id]);
1109		}
1110	}
1111	
1112	/**
1113	 * Add or Set item of information
1114	 *
1115	 * @param string $var
1116	 * @param mixed $value
1117	 * @return mixed
1118	 */
1119	final public function setItem($var, $value = null){
1120		if (is_array($var)) {
1121			$r = array();
1122			foreach ( $var as $idx => $val ) {
1123				if (self::issetVar($idx, $this->__items))
1124					$r[$idx] = self::getVarValue($idx, $this->__items);
1125				else
1126					$r[$idx] = null;
1127				
1128				self::setVarValue($idx, $val, $this->__items);
1129			}
1130			
1131			return $r;
1132		}
1133		
1134		if (self::issetVar($var, $this->__items))
1135			$item = self::getVarValue($var, $this->__items);
1136		else
1137			$item = null;
1138		
1139		self::setVarValue($var, $value, $this->__items);
1140		
1141		return $item;
1142	}
1143	
1144	/**
1145	 * Delete an item of information
1146	 *
1147	 * @param string $var
1148	 * @return boolean
1149	 */
1150	final public function delItem($var){
1151		return self::unsetVar($var, $this->__items);
1152	}
1153	
1154	/**
1155	 * Return an item
1156	 *
1157	 * @param array $array
1158	 * @param mixed $index
1159	 * @param mixed $default
1160	 * @return mixed
1161	 */
1162	final public function getItem($var, $default = null){
1163		if (! self::issetVar($var, $this->__items))
1164			return $default;
1165		return self::getVarValue($var, $this->__items);
1166	}
1167	
1168	/**
1169	 * Return a list of block's ranges
1170	 *
1171	 * @param string $tagini
1172	 * @param string $tagend
1173	 * @param boolean $onlyfirst
1174	 * @param integer $pos
1175	 * @return array
1176	 */
1177	final public function getRanges($tagini, $tagend, $src = null, $onlyfirst = false, $pos = 0){
1178		$ranges = array();
1179		if (is_null($src))
1180			if (isset($this))
1181				$src = $this->__src;
1182		if (! is_null($src))
1183			if (isset($src[0]) && ! empty($src)) {
1184				$ltagini = strlen($tagini);
1185				$ltagend = strlen($tagend);
1186				do {
1187					$ini = strpos($src, $tagini, $pos);
1188					if ($ini !== false) {
1189						if (isset($src[$ini + $ltagini])) {
1190							$fin = strpos($src, $tagend, $ini + $ltagini);
1191							if ($fin !== false) {
1192								$l = strlen($src);
1193								$last_pos = - 1;
1194								while ( true ) {
1195									$ini = strpos($src, $tagini, $pos);
1196									if ($ini === false || ($ini !== false && $pos == $last_pos))
1197										break;
1198									$end = false;
1199									$plus = 1;
1200									$posi = $ini + $ltagini;
1201									$last_posi = $posi - 1;
1202									
1203									while ( true ) {
1204										$open = strpos($src, $tagini, $posi);
1205										$close = strpos($src, $tagend, $posi);
1206										
1207										if ($open === false && $close === false)
1208											break; // not open and not close
1209										if ($open === false && $close !== false && $posi === $last_posi)
1210											break; // close and not open
1211										if ($open !== false && $close === false && $posi === $last_posi)
1212											break; // open and not close
1213										
1214										if ($open !== false || $close !== false) { // open or close
1215											if (($close < $open || $open === false) && $close !== false) { // close if is closed and before open or not open
1216												$last_posi = $posi;
1217												$posi = $close + $ltagend;
1218												$plus --;
1219												// IMPORTANT! Don't separate elseif
1220											} elseif (($open < $close || $close === false) && $open !== false) { // open if is opened and before close or not close
1221												$last_posi = $posi;
1222												$posi = $open + $ltagini;
1223												$plus ++;
1224											}
1225										}
1226										
1227										if ($plus === 0) { // all opens are closed
1228											$end = $close;
1229											break;
1230										}
1231										
1232										if ($open >= $l)
1233											break;
1234									}
1235									
1236									$last_pos = $pos;
1237									
1238									if ($end != false) {
1239										$ranges[] = array(
1240												$ini,
1241												$end
1242										);
1243										if ($onlyfirst == true)
1244											break;
1245										$pos = $ini + $ltagini;
1246										continue;
1247									}
1248								}
1249							}
1250						}
1251					}
1252					
1253					if (! isset($ranges[0]) && $ini !== false) {
1254						if (self::$__log_mode)
1255							if (isset($this)) {
1256								foreach ( $this->__items as $key => $value )
1257									if (strpos($tagini, $key) !== false) {
1258										$this->logger('Unclosed tag ' . $tagini . ' at ' . $ini . ' character', DIV_ERROR_WARNING);
1259										break;
1260									}
1261							}
1262						
1263						$pos = $ini + 1;
1264						
1265						continue;
1266					}
1267					
1268					break;
1269				} while ( true );
1270			}
1271		return $ranges;
1272	}
1273	
1274	/**
1275	 * Return a list of ranges of blocks
1276	 *
1277	 * @param string $src
1278	 * @param string $begin_prefix
1279	 * @param string $begin_suffix
1280	 * @param string $end_prefix
1281	 * @param string $end_suffix
1282	 * @param integer $after
1283	 * @param integer $before
1284	 * @return array
1285	 */
1286	final public function getBlockRanges($src = null, $begin_prefix = '{', $begin_suffix = '}', $end_prefix = '{/', $end_suffix = '}', $after = 0, $before = null, $onlyfirst = false){
1287		if (is_null($src))
1288			$src = $this->__src;
1289		if (! is_null($before))
1290			$src = substr($src, 0, $before);
1291		
1292		$l = strlen($src);
1293		$l1 = strlen($begin_prefix);
1294		$tagsya = array();
1295		$ranges = array();
1296		$from = $after;
1297		
1298		do {
1299			$prefix_pos = strpos($src, $begin_prefix, $from);
1300			if ($prefix_pos !== false) {
1301				if (isset($src[$prefix_pos + 1])) {
1302					
1303					if ($begin_suffix != '' && ! is_null($begin_suffix)) {
1304						$suffix_pos = strpos($src, $begin_suffix, $prefix_pos + 1);
1305					} else {
1306						
1307						$stopchars = array(
1308								' ',
1309								"\n",
1310								"\r",
1311								"\t",
1312								"<",
1313								">"
1314						);
1315						$stoppos = array();
1316						
1317						foreach ( $stopchars as $k => $v ) {
1318							$pp = strpos($src, $v, $prefix_pos);
1319							if ($pp === false)
1320								continue;
1321							$stoppos[] = $pp;
1322						}
1323						
1324						$suffix_pos = false;
1325						if (count($stoppos) > 0)
1326							$suffix_pos = min($stoppos);
1327					}
1328					
1329					$key = '';
1330					if ($suffix_pos < $l && $suffix_pos !== false) {
1331						$key = substr($src, $prefix_pos + $l1, $suffix_pos - $prefix_pos - $l1);
1332					}
1333					
1334					if ($key !== '' && ! isset($tagsya[$key])) {
1335						$tag_begin = $begin_prefix . $key . $begin_suffix;
1336						$tag_end = $end_prefix . $key . $end_suffix;
1337						$rs = $this->getRanges($tag_begin, $tag_end, $src, $onlyfirst, $from);
1338						$l2 = strlen($tag_begin);
1339						foreach ( $rs as $k => $v ) {
1340							$rs[$k][2] = $key;
1341							$rs[$k][3] = substr($src, $v[0] + $l2, $v[1] - $v[0] - $l2);
1342						}
1343						$ranges = array_merge($ranges, $rs);
1344						
1345						// Only the first...
1346						if ($onlyfirst)
1347							if (isset($ranges[0]))
1348								break;
1349						
1350						$tagsya[$key] = true;
1351					}
1352				}
1353				$from = $prefix_pos + 1;
1354			}
1355		} while ( $prefix_pos !== false );
1356		
1357		return $ranges;
1358	}
1359	
1360	/**
1361	 * Return a default replacement of value
1362	 *
1363	 * @param mixed $value
1364	 * @return mixed
1365	 */
1366	final static function getDefault($value){
1367		$id = serialize($value);
1368		if (isset(self::$__defaults[$id]))
1369			return self::$__defaults[$id];
1370		return $value;
1371	}
1372	
1373	/**
1374	 * Return a default replacement of value by var
1375	 *
1376	 * @param string $var
1377	 * @param mixed $value
1378	 * @return mixed
1379	 */
1380	final static function getDefaultByVar($var, $value){
1381		if (isset(self::$__defaults_by_var[$var])) {
1382			$id = serialize($value);
1383			if (isset(self::$__defaults_by_var[$var][$id])

Large files files are truncated, but you can click here to view the full file