XomwTemplateParser: Port XomwPPTemplateFrame_Hash [#632]

staging
gnosygnu 4 years ago
parent b56673c56e
commit 9809dfd6c7

@ -16,17 +16,34 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
import gplx.core.strings.*;
public class XophpArray_ {
// REF.PHP:https://www.php.net/manual/en/function.array-merge.php
public static XophpArray array_merge(XophpArray... vals) {
XophpArray rv = new XophpArray();
for (XophpArray ary : vals) {
XophpArrayItm[] itms = ary.To_ary();
for (XophpArrayItm itm : itms) {
array_add(rv, itm);
array_itm_add(rv, itm);
}
}
return rv;
}
private static void array_add(XophpArray ary, XophpArrayItm itm) {
// REF.PHP:https://www.php.net/manual/en/function.array-merge.php
// "If you want to append array elements from the second array to the first array while not overwriting the elements from the first array and not re-indexing, use the + array union operator:"
public static XophpArray array_add(XophpArray lhs, XophpArray... vals) {
for (XophpArray ary : vals) {
XophpArrayItm[] itms = ary.To_ary();
for (XophpArrayItm itm : itms) {
if (lhs.Has(itm.Key())) {
continue;
}
else {
lhs.Add(itm.Key(), itm.Val());
}
}
}
return lhs;
}
private static void array_itm_add(XophpArray ary, XophpArrayItm itm) {
if (itm.Key_is_int())
ary.Add(itm.Val());
else
@ -51,14 +68,14 @@ public class XophpArray_ {
// add src from 0 to bgn
for (int i = 0; i < bgn; i++) {
array_add(src, itms[i]);
array_itm_add(src, itms[i]);
}
// add repl
if (repl != null) {
XophpArrayItm[] repl_itms = repl.To_ary();
for (XophpArrayItm itm : repl_itms) {
array_add(src, itm);
array_itm_add(src, itm);
}
}
@ -79,13 +96,13 @@ public class XophpArray_ {
// add src from end to len
for (int i = end; i < src_len; i++) {
array_add(src, itms[i]);
array_itm_add(src, itms[i]);
}
// add del to rv
XophpArray rv = new XophpArray();
for (int i = bgn; i < end; i++) {
array_add(rv, itms[i]);
array_itm_add(rv, itms[i]);
}
return rv;
}
@ -100,6 +117,16 @@ public class XophpArray_ {
return rv;
}
public static XophpArray array_keys(XophpArray array) {
XophpArray rv = XophpArray.New();
int len = array.count();
for (int i = 0; i < len; i++) {
XophpArrayItm itm = array.Get_at_itm(i);
rv.Add(itm.Key());
}
return rv;
}
// DEPRECATE:use XophpArray
public static boolean popBoolOrN(List_adp list) {return Bool_.Cast(List_adp_.Pop_or(list, false));}
public static byte[] popBryOrNull(List_adp list) {return (byte[])List_adp_.Pop_or(list, null);}

@ -20,44 +20,51 @@ public class XophpArray__tst { // REF:https://www.php.net/manual/en/function.arr
@Test public void array_merge__basic() {
XophpArray ary1 = fxt.Make().Add("key1", "val1").Add("a");
XophpArray ary2 = fxt.Make().Add("key2", "val2").Add("b");
fxt.Test__array_merge
fxt.Test__eq
( fxt.Make().Add("key1", "val1").Add("a").Add("key2", "val2").Add("b")
, ary1, ary2);
, XophpArray_.array_merge(ary1, ary2));
}
@Test public void array_merge__same_key() {
XophpArray ary1 = fxt.Make().Add("key", "val1");
XophpArray ary2 = fxt.Make().Add("key", "val2");
fxt.Test__array_merge
fxt.Test__eq
( fxt.Make().Add("key", "val2")
, ary1, ary2);
, XophpArray_.array_merge(ary1, ary2));
}
@Test public void array_merge__same_idx() {
XophpArray ary1 = fxt.Make().Add(0, "a");
XophpArray ary2 = fxt.Make().Add(0, "b");
fxt.Test__array_merge
fxt.Test__eq
( fxt.Make().Add(0, "a").Add(1, "b")
, ary1, ary2);
, XophpArray_.array_merge(ary1, ary2));
}
@Test public void array_merge__renumber() {
XophpArray ary1 = fxt.Make().Add(3, "a");
XophpArray ary2 = fxt.Make().Add(2, "b");
fxt.Test__array_merge
fxt.Test__eq
( fxt.Make().Add(0, "a").Add(1, "b")
, ary1, ary2);
, XophpArray_.array_merge(ary1, ary2));
}
@Test public void array_merge__example_1() {
XophpArray ary1 = fxt.Make().Add("color", "red").Add_many(2, 4);
XophpArray ary2 = fxt.Make().Add_many("a", "b").Add("color", "green").Add("shape", "trapezoid").Add(4);
fxt.Test__array_merge
fxt.Test__eq
( fxt.Make().Add("color", "green").Add_many(2, 4, "a", "b").Add("shape", "trapezoid").Add(4)
, ary1, ary2);
, XophpArray_.array_merge(ary1, ary2));
}
@Test public void array_merge__example_2() {
XophpArray ary1 = fxt.Make();
XophpArray ary2 = fxt.Make().Add(1, "data");
fxt.Test__array_merge
fxt.Test__eq
( fxt.Make().Add(0, "data")
, ary1, ary2);
, XophpArray_.array_merge(ary1, ary2));
}
@Test public void array_add() {
XophpArray ary1 = fxt.Make().Add(0, "zero_a").Add(2, "two_a").Add(3, "three_a");
XophpArray ary2 = fxt.Make().Add(1, "one_b").Add(3, "three_b").Add(4, "four_b");
fxt.Test__eq
( fxt.Make().Add(0, "zero_a").Add(2, "two_a").Add(3, "three_a").Add(1, "one_b").Add(4, "four_b")
, XophpArray_.array_add(ary1, ary2));
}
@Test public void array_splice__bgn_is_positive() {
XophpArray src = fxt.Make().Add_many("a", "b", "c", "d");
@ -253,10 +260,6 @@ public class XophpArray__tst { // REF:https://www.php.net/manual/en/function.arr
}
class XophpArray__fxt {
public XophpArray Make() {return new XophpArray();}
public void Test__array_merge(XophpArray expd, XophpArray... vals) {
XophpArray actl = XophpArray_.array_merge(vals);
Gftest.Eq__str(expd.To_str(), actl.To_str());
}
public void Test__eq(XophpArray expd, XophpArray actl) {
Gftest.Eq__str(expd.To_str(), actl.To_str());
}

@ -17,7 +17,7 @@ package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
public class XophpIo_ {
public static String file_get_contents(String path) {
String rv = Io_mgr.Instance.LoadFilStr(path);
return String_.Eq(rv, String_.Empty) ? XophpString_.Null : rv;
return String_.Eq(rv, String_.Empty) ? XophpString_.False : rv;
}
public static boolean file_exists(String path) {
return Io_mgr.Instance.ExistsFil(Io_url_.new_fil_(path));

@ -19,7 +19,7 @@ import gplx.core.intls.*;
import gplx.objects.strings.unicodes.*;
import gplx.core.primitives.*;
public class XophpString_ implements XophpCallbackOwner {
public static final String Null = null;
public static final String False = null;
public static boolean is_true(String s) {return s != null;} // handles code like "if ($var)" where var is an Object;
// REF.PHP: https://www.php.net/manual/en/function.strpos.php
@ -240,6 +240,9 @@ public class XophpString_ implements XophpCallbackOwner {
public static byte[] str_replace(byte[] find, byte[] repl, byte[] src) {
return Bry_.Replace(src, find, repl);
}
public static String str_replace(String find, String repl, String src) {
return String_.Replace(src, find, repl);
}
public static byte[] strstr(byte[] src, byte[] find) {
int pos = Bry_find_.Find_fwd(src, find);
return pos == Bry_find_.Not_found ? null : Bry_.Mid(src, pos, src.length);
@ -256,93 +259,135 @@ public class XophpString_ implements XophpCallbackOwner {
, Int_obj_ref.New(Byte_ascii.Null)
, Int_obj_ref.New(Byte_ascii.Vertical_tab)
);
public static String rtrim(String src) {return rtrim(src, null);}
public static String rtrim(String src_str, String pad_str) {
Hash_adp pad_hash = null;
if (pad_str == null) pad_hash = trim_ws_hash;
public static String trim (String src) {return trim_outer( 0, src, null);}
public static String trim (String src, String pad) {return trim_outer( 0, src, pad);}
public static String ltrim(String src) {return trim_outer( 1, src, null);}
public static String ltrim(String src, String pad) {return trim_outer( 1, src, pad);}
public static String rtrim(String src) {return trim_outer(-1, src, null);}
public static String rtrim(String src, String pad) {return trim_outer(-1, src, pad);}
private static String trim_outer(int type, String src_str, String pad_str) {
// init brys / lens
byte[] src_bry = Bry_.new_u8(src_str);
int src_len = src_bry.length;
byte[] pad_bry = Bry_.new_u8(pad_str);
int pad_len = pad_bry.length;
// create pad_hash if not ws_hash
// NOTE: this does not support mutlibyte chars, and PHP does not support multibyte chars; see TEST
Hash_adp pad_hash = null;
if (pad_len > 1) {
if (pad_str == null) {
pad_hash = trim_ws_hash;
}
else {
pad_hash = Hash_adp_.New();
byte prv_byte = Byte_.Zero;
for (int i = 0; i < pad_len; i++) {
byte pad_byte = pad_bry[i];
if (pad_byte == Byte_ascii.Dot && i < pad_len - 1) {
byte nxt_byte = pad_bry[i + 1];
if (nxt_byte == Byte_ascii.Dot) {
if (i == 0) {
throw new XophpError(".. found but at start of String; src=" + pad_str);
}
else if (i == pad_len - 2) {
throw new XophpError(".. found but at end of String; src=" + pad_str);
}
else {
nxt_byte = pad_bry[i + 2];
if (nxt_byte > prv_byte) {
for (byte j = prv_byte; j < nxt_byte; j++) {
Byte_obj_ref rng_obj = Byte_obj_ref.new_(j);
if (!pad_hash.Has(rng_obj))
pad_hash.Add_as_key_and_val(rng_obj);
}
i += 2;
continue;
}
else {
throw new XophpError(".. found but next byte must be greater than previous byte; src=" + pad_str);
}
}
}
}
prv_byte = pad_byte;
Byte_obj_ref pad_obj = Byte_obj_ref.new_(pad_byte);
if (!pad_hash.Has(pad_obj))
pad_hash.Add_as_key_and_val(pad_obj);
}
}
}
// do trim
int[] rv = new int[2];
rv[0] = 0;
rv[1] = src_len;
if (type <= 0) { // trim or rtrim
trim_inner(Bool_.N, rv, src_bry, src_len, pad_bry, pad_len, pad_hash);
}
if (type >= 0) { // trim or ltrim
trim_inner(Bool_.Y, rv, src_bry, src_len, pad_bry, pad_len, pad_hash);
}
// return String
int trim_bgn = rv[0];
int trim_end = rv[1];
return trim_bgn == 0 && trim_end == src_len
? src_str
: String_.new_u8(Bry_.Mid(src_bry, trim_bgn, trim_end));
}
private static void trim_inner(boolean is_bos, int[] rv, byte[] src_bry, int src_len, byte[] pad_bry, int pad_len, Hash_adp pad_hash) {
// ----------------------
// 0, 1 chars (optimized)
// init vars
// ----------------------
int last = 0;
int rv_idx = 1;
int trim_bgn = src_len - 1;
int trim_end = -1;
int trim_add = -1;
int trim_adj = 1;
if (is_bos) {
rv_idx = 0;
trim_bgn = 0;
trim_end = src_len;
trim_add = 1;
trim_adj = 0;
}
int trim_pos = trim_end;
switch (pad_len) {
// pad is ""
// pad is 0 char; aka: ""
case 0:
return src_str;
break;
// pad is 1 char
case 1:
last = src_len;
byte pad_byte = pad_bry[0];
for (int i = src_len - 1; i > -1; i--) {
for (int i = trim_bgn; i != trim_end; i += trim_add) {
byte cur = src_bry[i];
last = i + 1;
trim_pos = i + trim_adj;
if (cur != pad_byte) {
break;
}
}
return (last == src_len) ? src_str : String_.new_u8(Bry_.Mid(src_bry, 0, last));
}
// --------
// 2+ chars
// --------
// create pad_hash if not ws_hash
// NOTE: PHP does not support multibyte strings; see TEST
if (pad_hash == null) {
pad_hash = Hash_adp_.New();
byte prv_byte = Byte_.Zero;
for (int i = 0; i < pad_len; i++) {
byte pad_byte = pad_bry[i];
if (pad_byte == Byte_ascii.Dot && i < pad_len - 1) {
byte nxt_byte = pad_bry[i + 1];
if (nxt_byte == Byte_ascii.Dot) {
if (i == 0) {
throw new XophpError(".. found but at start of String; src=" + pad_str);
}
else if (i == pad_len - 2) {
throw new XophpError(".. found but at end of String; src=" + pad_str);
}
else {
nxt_byte = pad_bry[i + 2];
if (nxt_byte > prv_byte) {
for (byte j = prv_byte; j < nxt_byte; j++) {
Byte_obj_ref rng_obj = Byte_obj_ref.new_(j);
if (!pad_hash.Has(rng_obj))
pad_hash.Add_as_key_and_val(rng_obj);
}
i += 2;
continue;
}
else {
throw new XophpError(".. found but next byte must be greater than previous byte; src=" + pad_str);
}
}
break;
// pad is 2+ chars
default:
// loop src until non-matching pad int
Byte_obj_ref temp = Byte_obj_ref.zero_();
trim_pos = src_len;
for (int i = trim_bgn; i != trim_end; i += trim_add) {
temp.Val_(src_bry[i]);
trim_pos = i + trim_adj;
if (!pad_hash.Has(temp)) {
break;
}
}
prv_byte = pad_byte;
Byte_obj_ref pad_obj = Byte_obj_ref.new_(pad_byte);
if (!pad_hash.Has(pad_obj))
pad_hash.Add_as_key_and_val(pad_obj);
}
break;
}
// loop src until non-matching pad int
Byte_obj_ref temp = Byte_obj_ref.zero_();
last = src_len;
for (int i = src_len - 1; i > -1; i--) {
temp.Val_(src_bry[i]);
last = i + 1;
if (!pad_hash.Has(temp)) {
break;
}
// set return
if (trim_pos != trim_end) {
rv[rv_idx] = trim_pos;
}
return (last == src_len) ? src_str : String_.new_u8(Bry_.Mid(src_bry, 0, last));
}
public static String str_repeat(String val, int count) {
int val_len = String_.Len(val);

@ -94,6 +94,48 @@ public class XophpString__tst {
// REF.MW:https://www.php.net/manual/en/function.trim.php
fxt.Test__rtrim("\u00A0µ déjà\u00A0", "\u00A0", "\u00A0µ déj<C3A9>");// NOTE: technically should be "...j\xC3", but String_.new_u8 ignores invalid bytes
}
@Test public void ltrim() {
// pad is 0, 1 char
fxt.Test__ltrim("0010", "", "0010"); // empty pad returns String
fxt.Test__ltrim("010", "0", "10"); // basic test; trim 1;
fxt.Test__ltrim("0010", "0", "10"); // basic test; trim 2;
fxt.Test__ltrim("10", "0", "10"); // nothing to trim
// pad is 2+char
fxt.Test__ltrim("10ab10", "01", "ab10"); // basic test
fxt.Test__ltrim("10ab10", "34", "10ab10"); // nothing to trim
fxt.Test__ltrim("10ab10", "010", "ab10"); // don't fail if repeated chars
// pad has ..
fxt.Test__ltrim("23ab23", "0..4", "ab23"); // basic test
fxt.Test__ltrim(".23ab23", "0.4", "23ab23"); // single dot is not range
// PHP samples
fxt.Test__ltrim("\t\tThese are a few words :) ... ", " \t.", "These are a few words :) ... ");
fxt.Test__ltrim("Hello World", "Hdle", "o World");
fxt.Test__ltrim("\u0009Example String\n", "\u0000..\u001F", "Example String\n");
}
@Test public void trim() {
// pad is 0, 1 char
fxt.Test__trim("0010", "", "0010"); // empty pad returns String
fxt.Test__trim("010", "0", "1"); // basic test; trim 1;
fxt.Test__trim("00100", "0", "1"); // basic test; trim 2;
fxt.Test__trim("10", "0", "1"); // nothing to trim
// pad is 2+char
fxt.Test__trim("10ab10", "01", "ab"); // basic test
fxt.Test__trim("10ab10", "34", "10ab10"); // nothing to trim
fxt.Test__trim("10ab10", "010", "ab"); // don't fail if repeated chars
// pad has ..
fxt.Test__trim("23ab23", "0..4", "ab"); // basic test
fxt.Test__trim(".23ab23.", "0.4", "23ab23"); // single dot is not range
// PHP samples
fxt.Test__trim("\t\tThese are a few words :) ... ", " \t.", "These are a few words :)");
fxt.Test__trim("Hello World", "Hdle", "o Wor");
fxt.Test__trim("\u0009Example String\n", "\u0000..\u001F", "Example String");
}
@Test public void ord() {
fxt.Test__ord("a", 97); // 1 char
fxt.Test__ord("abc", 97); // 2+ chars takes first
@ -168,6 +210,12 @@ class XophpString__fxt {
}
Gftest.Fail("expected failure, but got none: " + character_mask);
}
public void Test__ltrim(String str, String character_mask, String expd) {
Gftest.Eq__str(expd, XophpString_.ltrim(str, character_mask));
}
public void Test__trim(String str, String character_mask, String expd) {
Gftest.Eq__str(expd, XophpString_.trim(str, character_mask));
}
public void Test__ord(String str, int expd) {
Gftest.Eq__int(expd, XophpString_.ord(str));
}

@ -54,7 +54,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
/**
* @var array
*/
protected XophpArray childExpansionCache;
public XophpArray childExpansionCache;
/**
* Construct a new preprocessor frame.
@ -64,7 +64,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
this.preprocessor = preprocessor;
this.parser = preprocessor.Parser();
this.title = this.parser.mTitle;
this.titleCache = XophpArray.New().Add(XophpObject_.is_true(this.title) ? this.title.getPrefixedDBkeyStr() : XophpString_.Null);
this.titleCache = XophpArray.New().Add(XophpObject_.is_true(this.title) ? this.title.getPrefixedDBkeyStr() : XophpString_.False);
this.loopCheckHash = XophpArray.New();
this.depth = 0;
this.childExpansionCache = XophpArray.New();
@ -214,7 +214,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
}
Object newIterator = XophpObject_.False;
String contextName = XophpString_.Null;
String contextName = XophpString_.False;
XophpArray contextChildren = XophpArray.False;
if (!XophpObject_.is_true(contextNode)) {
@ -523,7 +523,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
return this.title.getPrefixedDBkeyStr();
} else {
// return isset( $this->titleCache[$level] ) ? $this->titleCache[$level] : false;
return this.titleCache.count() > 0 ? ((String)this.titleCache.Get_at(0)) : XophpString_.Null;
return this.titleCache.count() > 0 ? ((String)this.titleCache.Get_at(0)) : XophpString_.False;
}
}
@ -562,7 +562,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
* @return boolean Always false in this implementation.
*/
@Override public String getArgument(String name) {
return XophpString_.Null;
return XophpString_.False;
}
/**

@ -18,181 +18,188 @@ package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; impor
// * Expansion frame with template arguments
// * @ingroup Parser
// */
//// @codingStandardsIgnoreStart Squiz.Classes.ValidClassName.NotCamelCaps
// extends PPFrame_Hash
class XomwPPTemplateFrame_Hash extends XomwPPFrame { // // @codingStandardsIgnoreEnd
//
// public $numberedArgs, $namedArgs, $parent;
// public $numberedExpansionCache, $namedExpansionCache;
//
// /**
// * @param Preprocessor $preprocessor
// * @param boolean|PPFrame $parent
// * @param array $numberedArgs
// * @param array $namedArgs
// * @param boolean|Title $title
// */
// public function __construct($preprocessor, $parent = false, $numberedArgs = [],
// $namedArgs = [], $title = false
// ) {
// parent::__construct($preprocessor);
//
// this.parent = $parent;
// this.numberedArgs = $numberedArgs;
// this.namedArgs = $namedArgs;
// this.title = $title;
// $pdbk = $title ? $title.getPrefixedDBkey() : false;
// this.titleCache = $parent.titleCache;
// this.titleCache[] = $pdbk;
// this.loopCheckHash = /*clone*/ $parent.loopCheckHash;
// if ($pdbk !== false) {
// this.loopCheckHash[$pdbk] = true;
// }
// this.depth = $parent.depth + 1;
// this.numberedExpansionCache = this.namedExpansionCache = [];
// }
//
// public function __toString() {
// $s = 'tplframe{';
// $first = true;
// $args = this.numberedArgs + this.namedArgs;
// for each ($args as $name => $value) {
// if ($first) {
// $first = false;
// } else {
// $s .= ', ';
// }
// $s .= "\"$name\":\"" .
// str_replace('"', '\\"', $value.__toString()) . '"';
// }
// $s .= '}';
// return $s;
// }
//
// /**
// * @throws MWException
// * @param String|int $key
// * @param String|PPNode $root
// * @param int $flags
// * @return String
// */
// public function cachedExpand($key, $root, $flags = 0) {
// if (isset(this.parent.childExpansionCache[$key])) {
// return this.parent.childExpansionCache[$key];
// }
// $retval = this.expand($root, $flags);
// if (!this.isVolatile()) {
// this.parent.childExpansionCache[$key] = $retval;
// }
// return $retval;
// }
//
// /**
// * Returns true if there are no arguments in this frame
// *
// * @return boolean
// */
// public function isEmpty() {
// return !count(this.numberedArgs) && !count(this.namedArgs);
// }
//
// /**
// * @return array
// */
// public function getArguments() {
// $arguments = [];
// for each (array_merge(
// array_keys(this.numberedArgs),
// array_keys(this.namedArgs)) as $key) {
// $arguments[$key] = this.getArgument($key);
// }
// return $arguments;
// }
//
// /**
// * @return array
// */
// public function getNumberedArguments() {
// $arguments = [];
// for each (array_keys(this.numberedArgs) as $key) {
// $arguments[$key] = this.getArgument($key);
// }
// return $arguments;
// }
//
// /**
// * @return array
// */
// public function getNamedArguments() {
// $arguments = [];
// for each (array_keys(this.namedArgs) as $key) {
// $arguments[$key] = this.getArgument($key);
// }
// return $arguments;
// }
//
// /**
// * @param int $index
// * @return String|boolean
// */
// public function getNumberedArgument($index) {
// if (!isset(this.numberedArgs[$index])) {
// return false;
// }
// if (!isset(this.numberedExpansionCache[$index])) {
// # No trimming for unnamed arguments
// this.numberedExpansionCache[$index] = this.parent.expand(
// this.numberedArgs[$index],
// PPFrame::STRIP_COMMENTS
// );
// }
// return this.numberedExpansionCache[$index];
// }
//
// /**
// * @param String $name
// * @return String|boolean
// */
// public function getNamedArgument($name) {
// if (!isset(this.namedArgs[$name])) {
// return false;
// }
// if (!isset(this.namedExpansionCache[$name])) {
// # Trim named arguments post-expand, for backwards compatibility
// this.namedExpansionCache[$name] = trim(
// this.parent.expand(this.namedArgs[$name], PPFrame::STRIP_COMMENTS));
// }
// return this.namedExpansionCache[$name];
// }
//
// /**
// * @param int|String $name
// * @return String|boolean
// */
// public function getArgument($name) {
// $text = this.getNumberedArgument($name);
// if ($text === false) {
// $text = this.getNamedArgument($name);
// }
// return $text;
// }
//
// /**
// * Return true if the frame is a template frame
// *
// * @return boolean
// */
// public function isTemplate() {
// return true;
// }
//
// public function setVolatile($flag = true) {
// parent::setVolatile($flag);
// this.parent.setVolatile($flag);
// }
//
// public function setTTL($ttl) {
// parent::setTTL($ttl);
// this.parent.setTTL($ttl);
// }
class XomwPPTemplateFrame_Hash extends XomwPPFrame_Hash { public XophpArray numberedArgs, namedArgs;
public XomwPPFrame_Hash parent;
public XophpArray numberedExpansionCache, namedExpansionCache;
/**
* @param Preprocessor $preprocessor
* @param boolean|PPFrame $parent
* @param array $numberedArgs
* @param array $namedArgs
* @param boolean|Title $title
*/
// parent = false, numberedArgs = [], namedArgs = []; titl = false
public XomwPPTemplateFrame_Hash(XomwPreprocessor preprocessor, XomwPPFrame_Hash parent, XophpArray numberedArgs,
XophpArray namedArgs, XomwTitle title
) {super(preprocessor);
this.parent = parent;
this.numberedArgs = numberedArgs;
this.namedArgs = namedArgs;
this.title = title;
String pdbk = title != null ? title.getPrefixedDBkeyStr() : XophpString_.False;
this.titleCache = parent.titleCache;
this.titleCache.Add(pdbk);
this.loopCheckHash = /*clone*/ parent.loopCheckHash;
if (pdbk != XophpString_.False) {
this.loopCheckHash.Add(pdbk, true);
}
this.depth = parent.depth + 1;
this.numberedExpansionCache = this.namedExpansionCache = XophpArray.New();
}
@Override public String toString() {
String s = "tplframe{";
boolean first = true;
XophpArray args = XophpArray_.array_add(this.numberedArgs, this.namedArgs);
int args_len = args.count();
for (int i = 0; i < args_len; i++) {
XophpArrayItm itm = args.Get_at_itm(i);
if (first) {
first = false;
} else {
s += ", ";
}
s += "\"" + itm.Key() + "\":\"" +
XophpString_.str_replace("\"", "\\\"", itm.Val().toString()) + "\"";
}
s += "}";
return s;
}
/**
* @throws MWException
* @param String|int $key
* @param String|PPNode $root
* @param int $flags
* @return String
*/
@Override public String cachedExpand(String key, XomwPPNode root, int flags) { // flags = 0
if (XophpObject_.isset_obj(this.parent.childExpansionCache.Get_by(key))) {
return this.parent.childExpansionCache.Get_by_str(key);
}
String retval = this.expand(root, flags);
if (!this.isVolatile()) {
this.parent.childExpansionCache.Set(key, retval);
}
return retval;
}
/**
* Returns true if there are no arguments in this frame
*
* @return boolean
*/
@Override public boolean isEmpty() {
return !this.numberedArgs.count_bool() && !this.namedArgs.count_bool();
}
/**
* @return array
*/
@Override public XophpArray getArguments() {
XophpArray arguments = XophpArray.New();
XophpArray merged = XophpArray_.array_merge(
XophpArray_.array_keys(this.numberedArgs),
XophpArray_.array_keys(this.namedArgs));
int merged_len = merged.count();
for (int i = 0; i < merged_len; i++) {
String key = merged.Get_at_str(i);
arguments.Set(key, this.getArgument(key));
}
return arguments;
}
/**
* @return array
*/
@Override public XophpArray getNumberedArguments() {
XophpArray arguments = XophpArray.New();
XophpArray temp = XophpArray_.array_keys(this.numberedArgs);
int temp_len = temp.count();
for (int i = 0; i < temp_len; i++) {
String key = temp.Get_at_str(i);
arguments.Set(key, this.getArgument(key));
}
return arguments;
}
/**
* @return array
*/
@Override public XophpArray getNamedArguments() {
XophpArray arguments = XophpArray.New();
XophpArray temp = XophpArray_.array_keys(this.namedArgs);
int temp_len = temp.count();
for (int i = 0; i < temp_len; i++) {
String key = temp.Get_at_str(i);
arguments.Set(key, this.getArgument(key));
}
return arguments;
}
/**
* @param int $index
* @return String|boolean
*/
public String getNumberedArgument(int index) {
if (!XophpObject_.isset_obj(this.numberedArgs.Get_at(index))) {
return XophpString_.False;
}
if (!XophpObject_.isset_obj(this.numberedExpansionCache.Get_at(index))) {
// No trimming for unnamed arguments
this.numberedExpansionCache.Set(index, this.parent.expand(
(XomwPPNode)this.numberedArgs.Get_at(index),
XomwPPFrame.STRIP_COMMENTS
));
}
return this.numberedExpansionCache.Get_at_str(index);
}
/**
* @param String $name
* @return String|boolean
*/
public String getNamedArgument(String name) {
if (!XophpObject_.isset_obj(this.namedArgs.Get_by_str(name))) {
return XophpString_.False;
}
if (!XophpObject_.isset_obj(this.namedExpansionCache.Get_by_str(name))) {
// Trim named arguments post-expand, for backwards compatibility
this.namedExpansionCache.Set(name, XophpString_.trim(
this.parent.expand((XomwPPNode)this.namedArgs.Get_by(name), XomwPPFrame.STRIP_COMMENTS)));
}
return this.namedExpansionCache.Get_by_str(name);
}
/**
* @param int|String $name
* @return String|boolean
*/
public String getArgument(Object name) {
String text = this.getNumberedArgument((int)name);
if (String_.Eq(text, XophpString_.False)) {
text = this.getNamedArgument((String)name);
}
return text;
}
/**
* Return true if the frame is a template frame
*
* @return boolean
*/
@Override public boolean isTemplate() {
return true;
}
@Override public void setVolatile(boolean flag) { // flag = true
super.setVolatile(flag);
this.parent.setVolatile(flag);
}
@Override public void setTTL(int ttl) {
super.setTTL(ttl);
this.parent.setTTL(ttl);
}
}

Loading…
Cancel
Save