W3TPL/archive/code

From Woozle Writes Code
< W3TPL‎ | archive
Revision as of 16:49, 8 January 2009 by Woozle (talk | contribs) (version 0.20)
Jump to navigation Jump to search

Preface

This is just a snapshot from my editor, but it does work except for the <w3tpl> tag, which is in development. Parser interactions may make it difficult to use the existing tags for complex applications, but you can get around many issues by using the "copy" attribute and $variable indirection (to be documented).

Code

<php><?php <?php /*

HISTORY:

0.01 (Wzl) Mainly proof-of-concept; parser should later be optimized for execution time by using PHP intrinsic string fx instead of PHP-code loop 0.02 (Wzl) Kluge to let <xploop> pull #var value under MW <1.12

TO DO: If page is not protected, pre should be forced FALSE and post should be forced TRUE

"pre" can do weird things "post" set false allows raw HTML 0.03 (Wzl) <func> and related tags seem to be working 0.04 (Wzl) Some debugging; now works with v1.12 {{#tag}} function and template parameters (but not very well) names are always lowercased because sometimes the parser does it for you names are always trimmed, because sometimes the parser includes extra spaces 0.05 (Wzl) Added variable indirection ($); removed now-redundant "namer" attribute from <let> can we do something similar with pre-parsing? (i.e. a character to indicate the need for it -- @(stuff to parse)) <if> can now make more sense, i.e. using actual values instead of assuming variable names 0.06 (Wzl) xploop now using variable indirection; removed listvar parameter 0.07 (Wzl) Execution trace in <dump> 0.08 (Wzl) <trace> to set trace options; "input" option in <call> 0.09 (Wzl) <echo> tag; <call> does not output its contents 0.10 (Wzl) Code runs ok; still writing <w3tpl> tag 0.11 (Wzl) Added detection of page-protection, and "raw" attribute for <echo> 0.12 (Wzl) Fixed minor incompatibilities with MW 1.10 0.13 (Wzl) <for> tag seems to be working, at least for simple stuff 0.14 (Wzl) <load> tag fails gracefully when title doesn't exist 0.15 (Wzl) Support for brackets in variable names, to reference arrays 0.16 (Wzl) No SQL on unprotected pages; "limit" attribute for retrieving partial data 0.17 (Wzl) Removed some undefined-var warnings which pop up under certain mysterious circumstances 0.18 (Wzl) Lots of under-the-hood changes; var names are now parsed by the class clsW3VarName, which may later get renamed to clsW3Var and integrated with the full-blown parser to be written. There's still some ambiguity about the exact circumstances under which <let> overwrites existing data and when it operates on the variable's current value. 0.19 (Wzl) $wgW3TPLSettings['raw-ok'] now allows raw output even if page not protected 0.20 (Wzl) added "pre" as a deprecated alias for "parse", for backwards compatibility

BUGS:

$wgW3_func needs to be an array, so you can do <call...><arg><arg></call> and then pass the return value as an argument to another function (2008-10-15: in retrospect, I'm not sure how making it an array would help, though functions probably do need to have the ability to return values)

ELEMENTS:

<hide>: Runs the parser on everything in between the tags, but doesn't display the result. Useful for doing a lot of "programmish" stuff, so you can format it nicely and comment it without messing up your display <let>, <get>: much like PageVars extension, but using XML tags instead of {{#parser}} functions <func>: defines a function which can be called with arguments later <arg>: optional method of passing arguments to a function <call>: call a previously defined function <dump>: show list of all variables (with values) and functions (with code) <if>, <else>: control structure <xploop list="\demarcated\list" repl=string-to-replace sep=separator></xploop>: Same as {{#xploop}}, but uses varname instead of $s$ TO-DO <w3tpl></w3tpl>: The language itself

  • /

$wgExtensionCredits['other'][] = array(

       'name' => 'W3TPL',
       'description' => 'Woozle\'s Wacky Wiki Text Processing Language',
       'author' => 'Woozle (Nick) Staddon',

'url' => 'http://htyp.org/W3TPL', 'version' => '0.20 2009-01-08 (in progress)' );

define('ksFuncInit','efW3TPLInit');

//Avoid unstubbing $wgParser on setHook() too early on modern (1.12+) MW versions, as per r35980 if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {

       $wgHooks['ParserFirstCallInit'][] = ksFuncInit;

} else { // Otherwise do things the old fashioned way

       $wgExtensionFunctions[] = ksFuncInit;

} $wgHooks['LanguageGetMagic'][] = 'efW3_LanguageGetMagic';


function efW3TPLInit() {

       global $wgParser;

global $wgExtW3TPL; global $wgW3RawOk;

// hook in <tag>-style functions:

       $wgParser->setHook( 'hide',	'efW3Hide' );
       $wgParser->setHook( 'let',	'efW3Let' );
       $wgParser->setHook( 'get',	'efW3Get' );
       $wgParser->setHook( 'echo',	'efW3Echo' );
       $wgParser->setHook( 'dump',	'efW3Dump' );
       $wgParser->setHook( 'trace',	'efW3Trace' );
       $wgParser->setHook( 'if',	'efW3If' );
       $wgParser->setHook( 'else',	'efW3Else' );
       $wgParser->setHook( 'for',	'efW3For' );
       $wgParser->setHook( 'func',	'efW3Func' );
       $wgParser->setHook( 'call',	'efW3Call' );
       $wgParser->setHook( 'arg',	'efW3Arg' );
       $wgParser->setHook( 'load',	'efW3Load' );
       $wgParser->setHook( 'xploop',	'efW3Xploop' );
       $wgParser->setHook( 'w3tpl',	'efW3TPLRender' );

// hook in {{#parser}}-style functions: /* MW 1.13 is totally not happy with "let", and I don't know why. Abandoning these for now; they didn't turn out to be useful in getting past the parser. $wgExtW3TPL = new W3TPL_fx ( ); $wgParser->setFunctionHook ( 'w3xploop', array ( &$wgExtW3TPL, 'runXploop' ) ); $wgParser->setFunctionHook ( 'w3xpcount', array ( &$wgExtW3TPL, 'runXpCount' ) ); $wgParser->setFunctionHook ( 'let', array ( &$wgExtW3TPL, 'runLet' ) ); $wgParser->setFunctionHook ( 'get', array ( &$wgExtW3TPL, 'runGet' ) );

  • /
       return true;

} function efW3_LanguageGetMagic( &$magicWords, $langCode = "en" ) {

   switch ( $langCode ) {
       default:
           $magicWords['w3xploop']	= array ( 0, 'w3xploop' );
           $magicWords['w3xpcount']	= array ( 0, 'w3xpcount' );
   }
   return true;

}


function TrueFalse($iVar) { return $iVar?'TRUE':'FALSE'; } function W3VarExists($iName) { global $wgW3Vars;

$strName = strtolower($iName); return isset($wgW3Vars[$strName]); } function W3KillVar($iName) { global $wgW3Vars;

$strName = strtolower($iName); unset($wgW3Vars[$strName]); } function W3SetVar($iName, $iValue, $iAppend = FALSE) { global $wgW3Vars, $wgW3_doTrace_vars;

$strName = strtolower($iName); if ($iAppend && isset($wgW3Vars[$strName])) { $wgW3Vars[$strName] .= $iValue; if ($wgW3_doTrace_vars) { W3AddTrace(' $['.ShowHTML($strName).'] += ['.$iValue.'] => ['.$wgW3Vars[$strName].']'); } } else { $wgW3Vars[$strName] = $iValue; if ($wgW3_doTrace_vars) { W3AddTrace(' $['.ShowHTML($strName).'] = ['.$iValue.']'); } } } function W3GetSysData($iName) { global $wgParser,$wgTitle; global $wgW3_doTrace_vars; global $wgW3_data;

$strName = strtolower($iName); $strParts = explode('.', $strName); switch ($strParts[0]) { case 'title': switch ($strParts[1]) { case 'id': $out = $wgTitle->getArticleID(); break; } case 'subject': $out = $wgTitle->getText(); break; break; case 'row': $out = $wgW3_data[$strParts[1]]->$strParts[2]; break; case 'mem': $out = memory_get_usage(TRUE); break; } if ($wgW3_doTrace_vars) { W3AddTrace(' GETSYSDATA ['.ShowHTML($iName).']: ['.$out.']'); } return $out; } function W3SetSysData($iName,$iValue) { global $wgOut; global $wgW3Trace_indent;

W3AddTrace(' SETSYSDATA ['.$iName.':'.$iValue.']'); $strName = strtolower($iName); $strParts = explode('.', $strName); switch ($strParts[0]) { case 'catg': $wgW3Trace_indent++; W3AddTrace('CATG'); $wgW3Trace_indent--; $wgOut->mCategoryLinks = array(); break; } } function W3GetExpr($iName) { // check expression for $, meaning it's actually a reference to a variable // If found, return value of variable - otherwise return original string. $objVar = new clsW3VarName($iName); $objVar->Trace(); $objVar->Fetch(); $strOut = $objVar->Value; return $strOut;

} function W3GetVal($iName,$iIndex=NULL) { // gets value of given variable // checks function arguments, if function is defined $objVar = new clsW3VarName(); $objVar->ParseName($iName); if (!is_null($iIndex)) { $objVar->SetIndex($iIndex); } $objVar->Trace(); $objVar->Fetch(); $strVal = $objVar->Value; return $strVal; } function W3GetEcho() { global $wgW3_echoOutput, $wgW3_echoDepth; if (isset($wgW3_echoOutput[$wgW3_echoDepth])) { $out = $wgW3_echoOutput[$wgW3_echoDepth]; W3AddTrace('ECHO('.$wgW3_echoDepth.'): CLEARING ['.ShowHTML($out).']'); unset($wgW3_echoOutput[$wgW3_echoDepth]); } else { W3AddTrace('ECHO('.$wgW3_echoDepth.'): nothing there'); $out = NULL; } return $out; } function W3AddEcho($iVal) { global $wgW3_echoOutput, $wgW3_echoDepth;

if (isset($wgW3_echoOutput[$wgW3_echoDepth])) { W3AddTrace('ECHO('.$wgW3_echoDepth.') was ['.ShowHTML($wgW3_echoOutput[$wgW3_echoDepth]).'], adding ['.$iVal.']'); $wgW3_echoOutput[$wgW3_echoDepth] .= $iVal; W3AddTrace('ECHO('.$wgW3_echoDepth.') now is ['.ShowHTML($wgW3_echoOutput[$wgW3_echoDepth]).']'); } else { $wgW3_echoOutput[$wgW3_echoDepth] = $iVal; W3AddTrace('ECHO('.$wgW3_echoDepth.') is ['.ShowHTML($iVal).']'); } } function W3AddTrace($iLine,$iInd=0) { global $wgW3Trace, $wgW3Trace_indents, $wgW3Trace_indent; global $wgW3_doTrace; global $wgW3_TraceCount;

if ($wgW3_doTrace) { if ($wgW3_TraceCount < 1000) { $wgW3Trace[] = $iLine; $wgW3Trace_indents[] = $wgW3Trace_indent; $wgW3Trace_indent += $iInd; } $wgW3_TraceCount++; } /**/ } function W3Status_RawOk() { global $wgTitle; global $wgW3_func; global $wgW3TPLSettings;

if ($wgW3TPLSettings['raw-ok']) { $isProt = TRUE; } else { $isProt = $wgTitle->isProtected ('edit'); } if (!$isProt) { if (is_object($wgW3_func)) { $isProt = $wgW3_func->isOkRaw; } } W3AddTrace('IS RAW ok in ['.$wgTitle->getFullText().']: '.TrueFalse($isProt)); return $isProt; } function W3Status_SQLOk() { global $wgTitle; global $wgW3_func;

$isProt = $wgTitle->isProtected ('edit'); if (!$isProt) { if (is_object($wgW3_func)) { $isProt = $wgW3_func->isOkSQL; } } W3AddTrace('IS SQL allowed in ['.$wgTitle->getFullText().']: '.TrueFalse($isProt)); return $isProt; } function efW3Hide( $input, $args, $parser ) { $parser->recursiveTagParse( $input ); return NULL; } function W3Let_scalar( $iVar, $iArgs, $input, $parser ) { global $wgRequest; global $wgW3_func;

$strRepl = $iArgs->GetVal('repl'); $strWith = $iArgs->GetVal('with'); $doRepl = !is_null($strRepl) || !is_null($strWith); $doAppend = $iArgs->Exists('append');

// TRACING: $strTrace = ' - LET scalar:'; if (!is_null($strRepl)) { $strTrace .= ' repl=“'.$strRepl.'”'; } if (!is_null($strWith)) { $strTrace .= ' repl=“'.$strWith.'”'; } if ($doAppend) { $strTrace .= ' APPEND'; } W3AddTrace($strTrace);

if ($iArgs->Exists('val')) { $iVar->Value = $iArgs->GetExpr('val'); $strTrace = ' - LET VAL: expr=['.ShowHTML($iVar->Value).']'; W3AddTrace($strTrace); } elseif ($iArgs->Exists('arg')) { $strCopy = $iArgs->vArgs['arg']; // don't do any indirection from user input (possible security hole) $parser->disableCache(); $iVar->Value = $wgRequest->getVal($strCopy); // , $strDefault) -- maybe add feature later } elseif ($iArgs->Exists('farg')) { if (is_null($wgW3_func)) { W3AddTrace(' - ERROR: no function active to provide arg ['.$strName.']'); } else { $strName = strtolower($iArgs->GetExpr('farg')); if ($wgW3_func->HasArg($strName)) { $iVar->Value = $wgW3_func->ArgVal($strName); W3AddTrace(' - ARG['.$strName.'] => “'.$iVar->Value.'”'); } else { W3AddTrace(' - ERROR: function ['.$wgW3_func->Name.'] has no argument named ['.$strName.'].'); } } } elseif ($iArgs->Exists('chr')) { $iVar->Value = chr($iArgs->GetExpr('chr')); }

// AT THIS POINT, $this->Value is loaded with the value we want to operate on.

// later, we may want inc/dec to imply self-operation if there is no other input... // but this needs to be thought through carefully. For now, require "self" to increment self.

// do processing on current value: if ($iArgs->Exists('inc')) { $iVar->Value++; } if ($iArgs->Exists('dec')) { $iVar->Value--; }

if ($iArgs->Exists('parse') || $iArgs->Exists('pre')) { // restoring "pre" for backwards compatibility $iVar->Value = $parser->recursiveTagParse($iVar->Value); } if ($iArgs->Exists('ucase')) { $iVar->Value = strtoupper($iVar->Value); } if ($iArgs->Exists('lcase')) { $iVar->Value = strtolower($iVar->Value); } if ($iArgs->Exists('ucfirst')) { $iVar->Value = ucfirst($iVar->Value); } if ($iArgs->Exists('lcfirst')) { $iVar->Value = lcfirst($iVar->Value); } if ($iArgs->Exists('trim')) { $iVar->Value = trim($iVar->Value); } if ($iArgs->Exists('len')) { $strLen = $iArgs->GetExpr('len'); if (is_numeric($strLen)) { $iVar->Value = substr($iVar->Value,0,$strLen); } } if ($doRepl) { if (is_null($strRepl)) { $strRepl = $input; } elseif (is_null($strWith)) { $strWith = $input; } $strRes = str_replace($strRepl,$strWith,$iVar->Value); W3AddTrace('LET REPLACE ['.$strRepl.'] WITH ['.$strWith.'] => ['.$strRes.'] in “'.$iVar->Value.'”'); $iVar->Value = $strRes; } W3AddTrace('LET ['.$iVar->Name.'] <= “'.$iVar->Value.'”');

// AT THIS POINT, we have the semi-final value to be stored // -- if it's being appended, then get the old value and prepend it to the new:

if ($doAppend) { $valNew = $iVar->Value; // save the newly-calculated value off to one side

W3AddTrace(' - APPEND “'.$valNew.'”'); $iVar->Fetch(); // restore the prior value $iVar->Value .= $valNew; // append the new value to the prior value } } function W3Let_array ( $iVar, $iArgs, $input, $parser ) { $doSort = $iArgs->Exists('sort');

if ($doSort) { $iVar->DoSort($iArgs->Exists('rev'),$iArgs->Exists('val')); } } function efW3Let( $input, $args, $parser ) {

       global $wgRequest;

global $wgW3Vars,$wgW3_func;

$strCopy = NULL; $objArgs = new W3HookArgs($args); $strNameRaw = $objArgs->GetVal('name');

// trim whitespace and normalize name: $strName = strtolower(trim($strNameRaw)); $objVar = new clsW3VarName(); $objVar->ParseName($strName); // resolve any indirection (e.g. $var)

if (isset($args['index'])) { $strIdx = W3GetExpr($args['index']); $objVar->SetIndex($strIdx); } $strName = $objVar->Name; W3AddTrace('LET name=['.$strNameRaw.'] parsed to ['.$strName.']');

if (isset($args['null'])) { // if "null" option, then nothing else matters $objVar->Value = NULL; } else { // "copy" option works for any data type: if ($objVar->CheckCopy($objArgs)) { // do nothing; work already done } else { if (is_null($input) or isset($args['self'])) { $objVar->Fetch(); W3AddTrace(' - from self: ['.$objVar->Value.']'); } else { $objVar->Value = $input; W3AddTrace(' - from input: ['.$objVar->Value.']'); } } if ($objVar->IsArray()) { W3Let_array ( $objVar, $objArgs, $input, $parser ); } else { W3Let_scalar ( $objVar, $objArgs, $input, $parser ); } }

$objVar->Store();

// (optional) print the results: if (isset($args['echo'])) { return $objVar->Value; } else { return NULL; } /**/ } function efW3Get( $input, $args, $parser ) {

       global $wgRequest;

$objArgs = new W3HookArgs($args); W3AddTrace('GET:');

if (isset($args['default'])) { $strDefault = $args['default']; } else { $strDefault = NULL; } if (isset($args['val'])) { $strVal = $args['val']; $strVal = W3GetExpr($strVal); // check for redirections } elseif (isset($args['arg'])) { $parser->disableCache(); $strVal = $wgRequest->getVal($strName, $strDefault); } else { $strName = strtolower($args['name']); W3AddTrace(' - name=['.$strName.']');

$strIdx = $objArgs->GetExpr('index',TRUE); $strVal = W3GetVal($strName,$strIdx); } if (isset($args['codes'])) { $strVal = ShowHTML($strVal); } else { $doRaw = FALSE; if (isset($args['raw'])) { if (W3Status_RawOk()) { $doRaw = TRUE; } } if (!$doRaw) { $strVal = $parser->recursiveTagParse($strVal); } } if (isset($args['len'])) { $strVal = substr($strVal,0,$args['len']); } if (isset($args['ucase'])) { $strVal = strtoupper($strVal); } if (isset($args['lcase'])) { $strVal = strtolower($strVal); } return $strVal; } function efW3Echo( $input, $args, $parser ) { global $wgW3_echoDepth;

W3AddTrace('{ECHO('.$wgW3_echoDepth.'):'); if (!isset($wgW3_echoDepth)) { $wgW3_echoDepth = 0; }

if (isset($args['chr'])) { $valIn = chr($args['chr']); } else { $valIn = $input; }

if (isset($args['strip'])) { $out = ShowHTML($valIn); } $doRaw = FALSE; if (isset($args['raw'])) { if (W3Status_RawOk()) { $doRaw = TRUE; } } $doNow = isset($args['now']); W3AddTrace(' ('.$wgW3_echoDepth.') input:['.ShowHTML($valIn).']'); if ($doRaw) { $out = $valIn; } else { $wgW3_echoDepth++; $out = $parser->recursiveTagParse($valIn); W3AddTrace(' ('.$wgW3_echoDepth.') PARSING returned ['.ShowHTML($out).']'); $wgW3_echoDepth--; // W3AddEcho($tmp); }

W3AddTrace(' ('.$wgW3_echoDepth.') output: ['.ShowHTML($out).'] ECHO}'); if ($doNow) { return $out; } else { W3AddEcho($out); } } function efW3Dump( $input, $args, $parser ) { global $wgW3Vars, $wgW3_funcs; global $wgW3_doTrace, $wgW3_doTrace_vars; // tracing options global $wgW3Trace, $wgW3Trace_indents; // tracing data global $wgW3_TraceCount;

$out = '

    '; $doOnly = isset($args['only']); // default to NOT showing everything $doTrace = !$doOnly || isset($args['trace']); // show trace log $doVars = !$doOnly || isset($args['vars']); // show all variables $doFuncs = !$doOnly || isset($args['funcs']); // show function definitions $doMem = !$doOnly || isset($args['mem']); // show memory usage $wgW3_doTrace = $doTrace; $wgW3_doTrace_vars = $doTrace && $doVars; if ($doMem) { $out .= '
  • Memory usage before: '.memory_get_usage(TRUE).' bytes'; } if ($input != ) { $out = $parser->recursiveTagParse($input); } if ($doMem) { $out .= '
  • Memory usage after: '.memory_get_usage(TRUE).' bytes'; } if ($doVars) { if (is_array($wgW3Vars)) { $out .= '
  • Variables:
      '; foreach ($wgW3Vars as $name => $value) { if (is_array($value)) { $out .= '
    • ['.$name.']: array'; $out .= '
        '; foreach ($value as $akey => $aval) { $out .= '
      • '.$name.'['.$akey.'] = ['.ShowHTML($aval).']'; } $out .= '
      ';

      } else {

      $out .= '
    • ['.$name.'] = ['.$value.']'; } } $out .= '
    ';

    } else {

    $out .= '
  • No variables set'; } } if ($doFuncs) { if (is_array($wgW3_funcs)) { $out .= '
  • Functions:
      '; foreach ($wgW3_funcs as $name => $obj) { $out .= '
    • '.$obj->dump(); } $out .= '
    ';

    } else {

    $out .= '
  • No functions defined'; } } if ($doTrace) { if (is_array($wgW3Trace)) { $out .= '
  • Trace ('.$wgW3_TraceCount.' events):
      '; $indCur = 0; foreach ($wgW3Trace as $idx => $line) { $indLine = $wgW3Trace_indents[$idx]; if ($indLine > $indCur) { $out .= '-'.$indLine.'-
        '; } elseif ($indLine < $indCur) { $out .= '
      ';

      } $indCur = $indLine; /**/

      $out .= '
    • '.$idx.' '.$line; } $out .= '
    ';

    } else {

    $out .= '
  • '.$wgW3_TraceCount.' trace events'; } } $out .= '

';

return $out; } /* function efW3Trace( $input, $args, $parser ) { global $wgW3_doTrace_vars;

$wgW3_doTrace_vars = isset($args['assigns']); }

  • /

function efW3If( $input, $args, $parser ) { global $wgW3_ifFlag,$wgW3_ifDepth;

$doHide = isset($args['hide']); // only output <echo> sections

$ifFlag = false; if (!$wgW3_ifDepth) { $wgW3_ifDepth = 0; } if (isset($args['flag'])) { $strName = $args['flag']; $strVal = W3GetVal($strName); if (is_null($strVal) || ($strVal == )) { $ifFlag = FALSE; $dbgType = 'blank'; } else if (is_numeric($strVal)) { $ifFlag = ($strVal != 0); $dbgType = 'numeric'; } else { $ifFlag = TRUE; $dbgType = ; } W3AddTrace('IF(@'.$wgW3_ifDepth.'): ['.$strVal.']  != 0: ['.TrueFalse($ifFlag).']:'.$dbgType); } elseif (isset($args['comp'])) { // We need to be able to pass either constants or variables via these parameters, so use GetExpr not GetVal $strName = $args['comp']; $strVal1 = W3GetExpr($strName); $strTrace = '('.$strName.'="'.$strVal1.'")'; $strName = $args['with']; $strVal2 = W3GetExpr($strName); $strTrace .= '('.$strName.'="'.$strVal2.'")'; if (isset($args['pre'])) { $wgW3_ifDepth++; $strVal1 = $parser->recursiveTagParse($strVal1); $strVal2 = $parser->recursiveTagParse($strVal2); $wgW3_ifDepth--; // $strVal1 = $parser->replaceVariables($strVal1); // $strVal2 = $parser->replaceVariables($strVal2);

} $ifFlag = ($strVal1 == $strVal2); W3AddTrace('IF(@'.$wgW3_ifDepth.')'.$strTrace.':'.TrueFalse($ifFlag)); } if (isset($args['not'])) { $ifFlag = !$ifFlag; // invert the flag } $wgW3_ifFlag[$wgW3_ifDepth] = $ifFlag; if ($ifFlag) { $wgW3_ifDepth++; $out = $parser->recursiveTagParse($input); $wgW3_ifDepth--; } else { $out = NULL; }

if ($doHide) { $out = W3GetEcho(); return $out; } else { return $out; } } function efW3Else( $input, $args, $parser ) { global $wgW3_ifFlag, $wgW3_ifDepth;

$doHide = isset($args['hide']); // only output <echo> sections

$ifFlag = $wgW3_ifFlag[$wgW3_ifDepth]; W3AddTrace(' ELSE('.$wgW3_ifDepth.'): ['.$ifFlag.']'); if ($ifFlag) { W3AddTrace('ELSE skipped'); $out = NULL; } else { W3AddTrace('ELSE executed'); $wgW3_ifDepth++; $out = $parser->recursiveTagParse($input); $wgW3_ifDepth--; W3AddTrace('ELSE: OUT = ['.$out.']('.ShowHTML($out).')'); }

if ($doHide) { $out = W3GetEcho(); return $out; } else { return $out; } } function efW3For( $input, $args, $parser ) { global $wgW3_data; global $wgW3_echoDepth; global $wgW3Vars;

$objArgs = new W3HookArgs($args);

W3AddTrace('FOR:'); $doHide = isset($args['hide']); // only output <echo> sections $doArr = isset($args['array']); if ($doArr) { $strArr = $args['array']; } if (W3Status_SQLOk()) { // for now, only look for SQL stuff if page is protected // later, display error message on unprotected pages if SQL is used $doTbl = isset($args['table']); if ($doTbl) { $strTbl = $args['table']; } $strWhere = $objArgs->GetExpr('where', TRUE); } $strSort = $objArgs->GetExpr('sort', TRUE); $strLimit = $objArgs->GetExpr('limit', TRUE); $strName = $objArgs->GetVal('name'); // name of variable for storing data $strEmpty = $objArgs->GetVal('empty'); // string to return if there is no data if ($doTbl) { $dbr =& wfGetDB( DB_SLAVE ); if ($dbr->tableExists($strTbl)) { $sqlWhat = $strTbl; } else { } if ($strWhere != ) { // $sqlWhere = $dbr->addQuotes($strWhere); $sqlWhere = $strWhere; // TODO: need some way to harden against injection attack } $sqlFull = 'SELECT * FROM '.$sqlWhat; if ($sqlWhere) { $sqlFull .= ' WHERE '.$sqlWhere; } if ($strSort) { $sqlFull .= ' ORDER BY '.$strSort; } if ($strLimit) { $sqlFull .= ' LIMIT '.$strLimit; } W3AddTrace(' - SQL=['.$sqlFull.']'); try { // $res = $dbr->query($sqlWhat,$sqlWhere); $res = $dbr->query($sqlFull); } catch (Exception $e) { $sqlSim = 'SELECT * FROM '.$sqlWhat; if ($sqlWhere) { $sqlSim .= ' WHERE '.$sqlWhere; } $out = "W3TPL encountered a database error - ".$dbr->lastError()." - from this SQL:\n* ".$sqlSim; return $parser->recursiveTagParse($out); } W3AddTrace(' - rows: '.$dbr->numRows( $res )); if ($dbr->numRows( $res ) <= 0) { $dbr->freeResult( $res ); return $parser->recursiveTagParse($strEmpty); } $out = NULL; while( $row = $dbr->fetchObject ( $res ) ) { W3AddTrace('FOR: row->['.$strName.']'); $wgW3_data[$strName] = $row; $strParsed = $parser->recursiveTagParse($input); if ($doHide) { $out .= W3GetEcho(); W3AddTrace(' - FOR echo: ['.ShowHTML($out).']'); } else { $out .= $strParsed; W3AddTrace(' - FOR parse: ['.ShowHTML($out).']'); } } //$dbr->freeResult( $res ); // this actually causes *more* memory to be used //unset($wgW3_data); // and so does this! } if ($doArr) { if (isset($args['index'])) { $strIdxName = $args['index']; } //$wgW3Vars[$strArr][0] = 'zero'; $arr = $wgW3Vars[$strArr]; if (is_array($arr)) { $idx = 0; foreach ($arr as $name => $value) { $idx++; if ($strLimit) { if ($idx > $strLimit) { break; } } $strTrace = 'FOR: row->['.$strArr.']'; if ($strIdxName) { $wgW3Vars[$strIdxName] = (string)$name; $strTrace .= ' INDEX=['.$name.']=>['.$strIdxName.']'; } $strParsed = $parser->recursiveTagParse($input); W3AddTrace($strTrace); if (!isset($out)) { $out = NULL; } if ($doHide) { $out .= W3GetEcho(); W3AddTrace('FOR echo: ['.ShowHTML($out).']'); } else { $out .= $strParsed; W3AddTrace('FOR parse: ['.ShowHTML($out).']'); } } } else { W3AddTrace('FOR array=['.$strArr.']: not an array!'); } } return $out; } function efW3Func( $input, $args, $parser ) { global $wgW3_funcs;

$pcnt = 0; $funcArgs = NULL; // declare var in case there are no args foreach ($args as $name => $value) { if ($pcnt) { /* The parser apparently sets the argument's value to its name if no value is specified. This is a sort of bug for this purpose, but maybe it makes sense in other contexts. The real way to get around it is to use <w3tpl> block syntax instead of the <func> tag.

  • /

if ($value != $name) { $funcArgs[$name] = $value; } else { $funcArgs[$name] = null; } } else { $funcName = strtolower($name); } $pcnt++; } W3AddTrace('FUNC “'.$funcName.'”'); $objFunc = new clsW3Function($parser,$funcName,$funcArgs,$input); $wgW3_funcs[$funcName] = $objFunc; return NULL; } function efW3Call( $input, $args, $parser ) { global $wgW3_funcs,$wgW3_func;

W3AddTrace('{CALL:'); $pcnt = 0; $strTrace = NULL; // $wgW3_echoOutput = NULL; foreach ($args as $name => $value) { $strName = strtolower(trim($name)); if ($pcnt) { $strVal = W3GetExpr($value); $strTrace .= $objFunc->LoadArg($strVal,$strName); $strTrace .= ' '; $strTrace .= ')'; } else { $funcName = $strName; W3AddTrace(' - (CALL) '.$funcName); $objFunc = $wgW3_funcs[$funcName]; $wgW3_func = $objFunc; if (!is_object($objFunc)) { $out = 'W3TPL ERROR: Function "'.$funcName.'" is undefined.'; return $out; } $objFunc->ResetArgs(); } $pcnt++; } if ($input) { // $strTrace .= ' INPUT: {'.ShowHTML($input).'}'; $res = $parser->recursiveTagParse($input); // $strTrace .= ' PARSED: {'.ShowHTML($res).'}'; } $out = $objFunc->execute(); W3AddTrace($strTrace.' CALL}'); $out = W3GetEcho(); $wgW3_func = NULL; // no active function (is this still used?) return $out; } function efW3Arg( $input, $args, $parser ) { global $wgW3_func;

if (isset($args['name'])) { $name = $args['name']; } else { $name = ; } if (isset($args['pre'])) { $value = $parser->recursiveTagParse($input); } else { $value = $input; } $strTrace = ' +ARG: '.$wgW3_func->LoadArg($value,$name); W3AddTrace($strTrace); } function efW3Load( $input, $args, $parser ) { /* NOTE: Some pages apparently don't create the parser; if this code needs to run on one of those pages, then this may need to create $wgParser if it doesn't exist. For now, we assume optimistically.

  TO DO:

Add "let=" option to assign page contents to a variable Make parsing optional for protected pages

  • /

global $wgTitle;

$strTitle = $args['page']; W3AddTrace('LOAD: page={'.$strTitle.'}'); $strTitle = W3GetExpr($strTitle); $doEcho = isset($args['echo']);

W3AddTrace('LOAD -> {'.$strTitle.'}');


$objTitle = Title::newFromText($strTitle); if (is_object($objTitle)) { $objArticle = new Article($objTitle); $txtContent = $objArticle->getContent(); // eventually we will have a way to retrieve the contents via a variable // until then, the "raw" option is just for debugging if (isset($args['raw'])) { $out = $txtContent; } else { if (isset($args['local'])) { // parse title in its own context, not in the parent page's context W3AddTrace(' - LOAD as LOCAL'); // temporarily replace $wgTitle with the page we're parsing $objTitleOuter = $wgTitle; $wgTitle = $objTitle; $out = $parser->recursiveTagParse($txtContent); /* $objOut = $parser->parse( $txtContent, $objTitle, $objOpts ); */ $wgTitle = $objTitleOuter; //$out = $objOut->getText(); // restore $wgTitle's original value } else { // strip out all category tags // there should be a more elegant way to do this, but for now we have to get ugly //$txtContent = preg_replace('/\[\[category:.+\]\]/i','blah!',$txtContent); $out = $parser->recursiveTagParse($txtContent); //} } if (isset($args['nocat'])) { // clear out any categories added by parsing of loaded text $parser->mOutput->mCategories = array(); //$parser->mOutput->setCategoryLinks(NULL); } } } else { $out = 'Title ['.ShowHTML($strTitle).'] does not exist.'; // change this to a proper system message at some point } if (isset($args['let'])) { $strName = $args['let']; W3SetVar($strName, $out); } W3AddTrace('LOAD END'); if ($doEcho) { return $out; } else { return NULL; } } function efW3Xploop( $input, $args, $parser ) { global $wgW3Vars;

$objArgs = new W3HookArgs($args);

$strListRaw = $objArgs->GetVal('list'); $strList = W3GetExpr($strListRaw); $strTok = $objArgs->GetVal('repl'); $doEcho = isset($args['echo']);

if (isset($args['var'])) { $strVar = strtolower($args['var']); } else { $strVar = NULL; } $sepStr = $objArgs->GetVal('sep');

if ($strTok) { // doing a straight token replacement $strTrace = 'XPLOOP replace ('.ShowHTML($strTok).') <= “'.ShowHTML($strList).'”'; } else { // setting variable value $strTrace = 'XPLOOP set ('.ShowHTML($strVar).') <= “'.ShowHTML($strList).'”'; } if ($strList != $strListRaw) { $strTrace .= '<=“'.$strListRaw.'”'; } W3AddTrace($strTrace); if (isset($args['parselist'])) { $strList = $parser->recursiveTagParse( $strList ); }

$tok = substr ( $strList, 0, 1); // token for splitting if ($tok) { $tks = substr ( $strList, 1 ); // tokenized string $list = explode ( $tok, $tks ); // split the string $out = ; } else { return NULL; } if ($strTok) { // doing a straight token replacement foreach ($list as $value) { if ($out) { $out .= $sepStr; } $out .= str_replace( $strTok, $value, $input ); } $out = CharacterEscapes::charUnesc( $out, array(), $parser ); $out = $parser->recursiveTagParse( $out ); } else { foreach ($list as $value) { if ($out) { $out .= $sepStr; } $wgW3Vars[$strVar] = $value; W3AddTrace(' - XP: ['.$strVar.'] <- ['.$value.']'); $out .= $parser->recursiveTagParse( $input ); } } if ($doEcho) { return $out ; } else { $out = W3GetEcho(); return $out; } }

function efW3TPLRender( $input, $args, $parser ) { global $w3step;

$out = $input; if (isset($args['step'])) { $w3step = true; // show each line of code before it is executed } if (isset($args['pre'])) { $out = $parser->recursiveTagParse( $out ); } if (!isset($args['notpl'])) { $out = ActualRender($out,$args); } if (isset($args['post'])) { $out = $parser->recursiveTagParse( $out ); } $out = ActualRender($out); return $out; } /*

Each of these classes is initialized by passing it the remaining text
They each parse that text into an array of objects, and return any remaining text for the caller to finish parsing.
  • /

abstract class clsW3Code { private $vText;

public function __construct($iText) { $this->vText = $iText; } public function Dump() { return $vText; } } abstract class clsW3Code_sub extends clsW3Code { // Code with ending delimiter, after which remaining text must be parsed by caller private $vCloser; public $strRemain;

public function __construct($iText,$iCloser=) { $this->vText = $iText; $this->vCloser = $iCloser; } } class clsW3Code_body extends clsW3Code { private $vLines;

public function parse() { $strToParse = $this->vText;

$objChunk = NULL; while ($strToParse != ) { $objLine = new clsW3Code_line($strToParse); $strToParse = $objLine->strRemain; $this->vLines[] = $objLine; } } public function Dump() {

$out = '

    '; foreach ($this->vLines as $line) { $out .= '
  • '.$line->Dump(); } $out .= '

';

return $out; } } class clsW3Code_line extends clsW3Code_sub { private $vTokens;

public function parse() { $strToParse = $this->vText; $isDone = FALSE; $objChunk = NULL; for ($i = 0; ($ch=substr($strToParse,$i,1)) && !$isDone; $i++) { $doAdd = TRUE; // TRUE = add this character to the token buffer $isTok = FALSE; // TRUE = a token has been completed; save it and clear buffer switch ($ch) { // whitespace case ' ': // space case "\t": // tab $isTok = TRUE; $doAdd = FALSE; // don't include unquoted whitespace break; case '"': $isTok = TRUE; $doAdd = FALSE; // don't include paren in token $objChunk = new clsW3_qstring(substr($input,$i+1)); $strToParse = $objChunk->strRemain; break; case '(': $isTok = TRUE; // start new token $doAdd = FALSE; // don't include paren in token $objChunk = new clsW3Code_line(substr($input,$i+1),')'); $strToParse = $objChunk->strRemain; break; case '{': $isTok = TRUE; // start new token $doAdd = FALSE; // don't include braces in token $objChunk = new clsW3Code_body(substr($input,$i+1),'}'); $strToParse = $objChunk->strRemain; break; case ';': $isTok = TRUE; // start new token $doAdd = FALSE; // don't include braces in token $isDone = TRUE; break; case "\n": $doAdd = false; // don't include linebreaks in $clause break; default: $isDone = ($ch == $this->vCloser); } if ($doAdd) { $token .= $ch; } if ($isTok) { // TRUE = a token has been completed; save it and clear buffer if ($token) { $objTok = new clsW3_token($token); $this->vTokens[] = $objTok; } $token = NULL; } if (is_object($objChunk)) { $this->vTokens[] = $objChunk; $objChunk = NULL; } } $this->strRemain = substr($strToParse,$i+1); } } class clsW3_token extends clsW3Code {

} class clsW3_phrase extends clsW3Code { private $vList;

} /* class clsW3Token_rawexp extends clsW3Token { public __construct($iText) { } }

  • /

class clsW3_qstring extends clsW3Code { public function parse() { $isDone = FALSE; for ($i = 0; ($ch=substr($input,$i,1)) && !$isDone; $i++) { switch ($ch) { case '\\': $inEsc = true; break; case '"': $isDone = !$inEsc; } } } }


function ActualRender($input) { // break the code up into separate commands if ($doLine) { // TRUE = line is complete //W3AddTrace('TPL: LINE=['.$strDbgLine.']'); $out .= $cmdObj->execute($lines); } // final semicolon not required: if ($line) { $out .= $cmdObj->execute($line,$clause); } return $out; }

/*

TOKEN TYPES - for future use:

() phrase {} brace phrase non-quoted expression quoted string

  • /

class clsW3ParsedLine { private $tokens;

public function __construct($iTokens) { $this->tokens = $iTokens; } } class clsW3ParsedChunk { private $lines; // array of clsW3ParsedLines

public function __construct($iLines) { $this->lines = $iLines; } }

class clsW3Command { private $statemt; private $clause;

public function clsW3Command($iStatemt=, $iClause=) { $this->init($iStatemt, $iClause); } public function init($iStatemt, $iClause) { $this->statemt = trim($iStatemt); $this->clause = $iClause; } public function execute($iStatemt, $iClause) { // init + exec $this->init($iStatemt, $iClause); return $this->exec(); } public function exec() { global $w3step;

$strStmt = $this->statemt; if ($w3step) { $out = '
CMD: {'.$strStmt.'} CLAUSE: {'.$this->clause.'}'; } /* A command is in any of these forms: variable action-operator expression; expression; keyword (expression) {clause} [keyword (expression) {clause} ... ]; An expression is in any of these forms: function(expression[, expression[, ...]]) variable compare-operator expression variable constant A constant is either a quoted string or a number A variable is invoked by name


  • /

// parse the command: for ($i = 0; $ch=substr($strStmt,$i,1); $i++) { $isArgs = FALSE; if ($isTok) { //if (!$inQuo) { if ($cmd == ) { $cmd = $phrase; $phrase = ; } } elseif ($isArgs) { $args = $phrase; $phrase = ; } else { $phrase .= $ch; } } W3AddTrace('TPL layer 2: CMD=['.$cmd.'] ARGS=['.$args.'] leftover=['.$phrase.']'); // return $out; } } // TO DO: Change name to ShowMarkup, because it handles HTML, wikitext, and partly-parsed wikitext function ShowHTML($iText, $iRepNewLine=TRUE) {

/*/ // DEBUGGING - explode string by inserting space between each character: $cpLen = strlen($iText); $out2 = ; for ($i = 0; $i <= $cpLen; $i++) { $out2 .= substr($iText,$i,1).' '; } $out = $out2; /**/ // $out = 'LENGTH='.strlen($iText);

$out = $iText; $out = str_replace ( '<','<',$out ); $out = str_replace ( '>','>',$out); $out = str_replace ( '[','[',$out ); $out = str_replace ( ']',']',$out ); $out = str_replace ( chr(7),'^G',$out); $out = str_replace ( chr(127),'del',$out); if ($iRepNewLine) { $out = str_replace ( chr(10),'^J',$out); $out = str_replace ( chr(13),'^M',$out); } return $out; }

/* class w3expr { private $text; abstract function Parse($iTask); } */

class clsW3Function { var $vParser; var $isOkRaw, $isOkSQL; var $Name, $vParams, $vCode; var $vArgs, $vArgIdx;

public function __construct($iParser, $iName, $iParams, $iCode) { $this->vParser = $iParser; $this->Name = $iName; $this->vParams = $iParams; $this->vCode = $iCode; $this->isOkRaw = W3Status_RawOk(); $this->isOkSQL = W3Status_SQLOk(); } public function dump() { $out = ''.$this->Name.'('; if (is_array($this->vParams)) { $pcnt = 0; foreach ($this->vParams as $name => $value) { if ($pcnt) { $out .= ', '; } $out .= ''.$name.''; if (isset($value)) { $out .= '='.$value; } $pcnt++; } } $out .= ') {'; $strCode = ShowHTML($this->vCode,FALSE);

$out .= '

'.$strCode.'

}';

return $out; } public function ResetArgs() { $this->vArgIdx = 0; unset($this->vArgs); } public function LoadArg($iValue,$iName=) { if ($iName) { $strName = strtolower($iName); } else { $strName = $this->ParamName($this->vArgIdx); $this->vArgIdx++; } $this->vArgs[$strName] = $iValue; return '['.$strName.']=“'.$iValue.'”'; } public function HasArg($iName) { return isset($this->vArgs[$iName]); } public function ArgVal($iName) { return $this->vArgs[$iName]; } public function ParamName($iIndex) { $keys = array_keys($this->vParams); $key = $keys[$iIndex]; return $key; } public function execute() { // set variables from passed arguments

$useArgs = FALSE; if (isset($this->vArgs)) { if (is_array($this->vArgs)) { $useArgs = TRUE; } } if ($useArgs) { foreach ($this->vArgs as $name => $value) { if (W3VarExists($name)) { $oldVars[$name] = W3GetVal($name); } W3SetVar($name, $value); } } // parse (execute) the function code $out = $this->vParser->recursiveTagParse( $this->vCode ); // restore original variables (old value if any, or remove from list) if ($useArgs) { foreach ($this->vArgs as $name => $value) { if (isset($oldVars[$name])) { W3SetVar($name, $oldVars[$name]); } else { W3KillVar($name); } } } return $out; } }

class clsW3VarName { /*

  • An *expression* can be:
    • a literal value - "this is a string"
    • a reference to a variable - "$theVar"
    • a reference to a special function - @row.fieldname
  • A variable reference can be:
    • scalar value - "$aScalar"
    • array index - "$anArray[index_expression]" where "index_expression" is an expression

We automatically find the value of all inner elements as needed, but leave the outermost unresolved in order to allow for different operations depending on context.

  • /

public $Expr; // code-expression to parse public $Name; // final name of variable or function being referenced public $Index; // (optional) index into variable array public $Value; // loaded value of variable or function, for operations public $isFunc;

public function __construct($iExpr = NULL) { $this->isFunc = FALSE; W3AddTrace('clsW3VarName: init=['.$iExpr.']'); if (!is_null($iExpr)) { $this->ParseExpr($iExpr); } }

public function ParseExpr($iExpr) { global $wgW3_doTrace_vars; global $wgW3Trace_indent;

$wgW3Trace_indent++; $strExpr = $iExpr; if ($wgW3_doTrace_vars) { W3AddTrace(' {PARSE-EXPR ['.ShowHTML($iExpr).']'); } $chFirst = substr($strExpr,0,1); switch ($chFirst) { case '$': $strRef = strtolower(substr($strExpr,1)); $this->ParseName($strRef); break; case '@': $strRef = strtolower(substr($strExpr,1)); $this->ParseName($strRef); $this->isFunc = TRUE; break; default: // it's a literal, so the string is the value $this->Value = $strExpr; } if ($wgW3_doTrace_vars) { W3AddTrace(' => ['.ShowHTML($strExpr).'] EXPR}'); } $wgW3Trace_indent--; return $strExpr; }

public function ParseName($iName) { global $wgW3_doTrace_vars; global $wgW3Trace_indent; $strName = $iName; $wgW3Trace_indent++; if ($wgW3_doTrace_vars) { W3AddTrace('{PARSE-NAME ['.ShowHTML($iName).']'); }

if (substr($strName,0,1) == '@') { $this->isFunc = TRUE; $this->Name = strtolower(substr($strName,1)); W3AddTrace(' - is func ['.$this->Name.']'); } else { if (substr($strName, -1) == ']') { // name includes index offset $idxOpen = strpos($strName,'['); if ($idxOpen) { $idxShut = strpos($strName,']',$idxOpen); $vIndex = substr($strName,$idxOpen+1,$idxShut-$idxOpen-1); $strTrace = 'INDEX['.$vIndex.'] (@'.$idxOpen.'-'.$idxShut.' in ['.$strName.']) -> ['; $strTrace .= $vIndex.']'; $objIdx = new clsW3VarName($vIndex); $strName = substr($strName,0,$idxOpen); $objIdx->Fetch(); // calculate value of index expression $this->Index = $objIdx->Value; $strTrace .= ' NEW NAME=['.$strName.']'; W3AddTrace($strTrace); } } $objVar = new clsW3VarName($strName); $objVar->Fetch(); $this->Name = $objVar->Value; } if ($wgW3_doTrace_vars) { W3AddTrace('name:['.ShowHTML($this->Name).'] = val:['.ShowHTML($this->Value).'] NAME}'); } $wgW3Trace_indent--; /**/ }

public function SetIndex($iValue) { $this->Index = $iValue; W3AddTrace('clsW3VarName.SetIndex of ('.$this->Name.') to ['.$iValue.']'); } public function IsElem() { // is element of an array? return !is_null($this->Index); } public function IsVar() { return !is_null($this->Name) && !$this->isFunc; } public function IsArray() { return is_array($this->Value); } public function Fetch() { global $wgW3Vars;

$strName = strtolower($this->Name); if ($this->isFunc) { $this->Value = W3GetSysData($this->Name); } elseif ($this->IsVar()) { if ($this->IsElem()) { $strIndex = $this->Index; if (isset($wgW3Vars[$strName][$strIndex])) { $this->Value = $wgW3Vars[$strName][$strIndex]; W3AddTrace('clsW3VarName.Fetch ('.$strName.')['.$strIndex.']=>“'.$this->Value.'”'); } else { $this->Value = NULL; W3AddTrace('clsW3VarName.Fetch ('.$strName.')['.$strIndex.']=>NULL'); } } else { if (isset($wgW3Vars[$strName])) { $this->Value = $wgW3Vars[$strName]; W3AddTrace('clsW3VarName.Fetch ('.$strName.')=>“'.$this->Value.'”'); } else { $this->Value = NULL; W3AddTrace('clsW3VarName.Fetch ('.$strName.')=>NULL'); } } } else { // literal value - already set. } W3AddTrace('clsW3VarName.Fetch: value=['.$this->Value.']'); $this->Trace(); }

public function Store() { global $wgW3Vars;

$strName = $this->Name; $strVal = $this->Value; if ($this->isFunc) { W3SetSysData($strName,$strVal); } elseif ($strName) { if ($this->isElem()) { $strIndex = $this->Index; $wgW3Vars[$strName][$strIndex] = $strVal; W3AddTrace('clsW3VarName.Store: '.$strName.'['.$strIndex.'] <= “'.$strVal.'”'); } else { $wgW3Vars[$strName] = $strVal; W3AddTrace('clsW3VarName.Store: ['.$strName.'] <= “'.$strVal.'”'); } $this->Trace(); } else { W3AddTrace('clsW3VarName.Store: ERROR: no name for value “'.$strVal.'”'); $this->Trace(); } }

public function DoSort($iRev=FALSE, $iVal=FALSE) { if (is_array($this->Value)) { if ($iVal) { // sort by value if ($iRev) { $ok = arsort($this->Value); } else { $ok = asort($this->Value); } } else { if ($iRev) { $ok = arsort($this->Value); } else { $ok = ksort($this->Value); } } if ($ok) { W3AddTrace('LET sort ['.$this->Name.'] OK'); } else { W3AddTrace('LET sort ['.$this->Name.'] ERROR: failed.'); } } else { W3AddTrace('LET sort ERROR: ['.$this->Name.'] is not an array.'); } }

public function CheckCopy($iArgs) { if ($iArgs->Exists('copy')) { $strSrce = $iArgs->GetVal('copy'); $this->Value = W3GetVal($strSrce); W3AddTrace('CheckCopy from ['.$strSrce.']'); // show raw input $this->Trace(); // show result return TRUE; } else { return FALSE; } }

public function Trace() { if (is_array($this->Value)) { $strVal = 'array!'; } else { $strVal = $this->Value; }

W3AddTrace('clsW3VarName.Trace: '. 'Name=['.$this->Name.'] '. 'Val=['.$strVal.'] '. 'Index=['.$this->Index.'] '. TrueFalseHTML('is var',$this->IsVar()).' '. TrueFalseHTML('is element',$this->IsElem()).' '. TrueFalseHTML('is func',$this->isFunc) ); } }

function TrueFalseHTML($iName, $iVal) { if ($iVal) { return ''.$iName.''; } else { return ''.$iName.''; } }

class W3HookArgs { var $vArgs;

public function __construct($iArgs) { $this->vArgs = $iArgs; } public function Exists($iName) { return isset($this->vArgs[$iName]); } public function GetVal($iName) { if (isset($this->vArgs[$iName])) { return $this->vArgs[$iName]; } else { return NULL; } } public function GetExpr($iName, $iTrace = FALSE) { if (isset($this->vArgs[$iName])) { $strArg = $this->vArgs[$iName]; $strOut = W3GetExpr($strArg); if ($iTrace) { W3AddTrace(' - '.strtoupper($iName).'=['.$strArg.'] -> ['.$strOut.']'); } return $strOut; } else { return NULL; } } }

/* class W3TPL_fx { function runXploop ( &$parser, $inStr = , $inTplt = '$s$', $inSep = ) { $tok = substr ( $inStr, 0, 1); // token for splitting if ($tok) { $tks = substr ( $inStr, 1 ); // tokenized string $list = explode ( $tok, $tks ); // split the string $sep = CharacterEscapes::charUnesc( $inSep, array(), $parser ); $tplt = CharacterEscapes::charUnesc( $inTplt, array(), $parser ); $out = ; foreach ($list as $value) { // $lcnt++; if ($out) { $out .= $sep; } $out .= str_replace( '$s$', $value, $tplt ); } return $parser->recursiveTagParse($out); // return array($out, 'noparse' => false, 'isHTML' => false); } else { return NULL; } } function runXpCount ( &$parser, $inStr = ) { $tok = substr ( $inStr, 0, 1); return substr_count($inStr, $tok); } function runLet ( &$parser, $iName = , $iVal = ) { global $wgW3Vars;

$strName = strtolower($iName); $strName = W3GetVal($strName); // check for indirection ($) $wgW3Vars[$strName] .= $iVal; } function runGet ( &$parser, $iName = ) { $strName = strtolower($iName); $strVal = W3GetVal('$'.$strName); return $parser->recursiveTagParse($strVal); } }

  • /</php>