mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
XomwTemplateParser: Port XomwPPTemplateFrame_Hash [#632]
This commit is contained in:
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…
Reference in New Issue
Block a user