mirror of
https://github.com/gnosygnu/xowa.git
synced 2025-06-13 12:54:14 +00:00
JsonConfig: Add Localize function for tabular data
This commit is contained in:
parent
8967ca810a
commit
54d74b0acd
@ -40,6 +40,10 @@ public class Bry_find_ {
|
|||||||
if (src[i] == lkp) return i;
|
if (src[i] == lkp) return i;
|
||||||
return Bry_find_.Not_found;
|
return Bry_find_.Not_found;
|
||||||
}
|
}
|
||||||
|
public static int Find_bwd_or(byte[] src, byte lkp, int cur, int end, int or) {
|
||||||
|
int rv = Find_bwd(src, lkp, cur, end);
|
||||||
|
return rv == Bry_find_.Not_found ? or : rv;
|
||||||
|
}
|
||||||
public static int Move_fwd(byte[] src, byte lkp, int cur, int end) {
|
public static int Move_fwd(byte[] src, byte lkp, int cur, int end) {
|
||||||
int rv = Find_fwd(src, lkp, cur, src.length);
|
int rv = Find_fwd(src, lkp, cur, src.length);
|
||||||
return rv == Bry_find_.Not_found ? rv : rv + 1;
|
return rv == Bry_find_.Not_found ? rv : rv + 1;
|
||||||
|
@ -30,6 +30,15 @@ public class Object_ {
|
|||||||
rv[i] = rhs[i - lhs_len];
|
rv[i] = rhs[i - lhs_len];
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
public static Object[] Ary_add_one(Object[] lhs, Object rhs) {
|
||||||
|
int lhs_len = lhs.length, rhs_len = 1;
|
||||||
|
int rv_len = lhs_len + rhs_len;
|
||||||
|
Object[] rv = new Object[rv_len];
|
||||||
|
for (int i = 0; i < lhs_len; ++i)
|
||||||
|
rv[i] = lhs[i];
|
||||||
|
rv[rv_len - 1] = rhs;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
public static boolean Eq(Object lhs, Object rhs) {
|
public static boolean Eq(Object lhs, Object rhs) {
|
||||||
if (lhs == null && rhs == null) return true;
|
if (lhs == null && rhs == null) return true;
|
||||||
else if (lhs == null || rhs == null) return false;
|
else if (lhs == null || rhs == null) return false;
|
||||||
|
@ -30,6 +30,7 @@ public class Type_ids_ {//RF:2017-10-08
|
|||||||
, Id__bry = 11
|
, Id__bry = 11
|
||||||
, Id__date = 12
|
, Id__date = 12
|
||||||
, Id__decimal = 13
|
, Id__decimal = 13
|
||||||
|
, Id__array = 14
|
||||||
;
|
;
|
||||||
|
|
||||||
public static int To_id_by_obj(Object o) {
|
public static int To_id_by_obj(Object o) {
|
||||||
|
@ -30,8 +30,8 @@ public class Xoa_app_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static final String Name = "xowa";
|
public static final String Name = "xowa";
|
||||||
public static final int Version_id = 540;
|
public static final int Version_id = 542;
|
||||||
public static final String Version = "4.5.18.1711";
|
public static final String Version = "4.5.20.1801";
|
||||||
public static String Build_date = "2012-12-30 00:00:00";
|
public static String Build_date = "2012-12-30 00:00:00";
|
||||||
public static String Build_date_fmt = "yyyy-MM-dd HH:mm:ss";
|
public static String Build_date_fmt = "yyyy-MM-dd HH:mm:ss";
|
||||||
public static String Op_sys_str;
|
public static String Op_sys_str;
|
||||||
|
@ -18,7 +18,7 @@ import gplx.core.btries.*;
|
|||||||
import gplx.langs.htmls.*; import gplx.xowa.langs.kwds.*; import gplx.langs.htmls.entitys.*;
|
import gplx.langs.htmls.*; import gplx.xowa.langs.kwds.*; import gplx.langs.htmls.entitys.*;
|
||||||
import gplx.xowa.htmls.core.wkrs.hdrs.*; import gplx.xowa.htmls.core.wkrs.lnkes.*;
|
import gplx.xowa.htmls.core.wkrs.hdrs.*; import gplx.xowa.htmls.core.wkrs.lnkes.*;
|
||||||
import gplx.xowa.wikis.domains.*;
|
import gplx.xowa.wikis.domains.*;
|
||||||
import gplx.xowa.parsers.*; import gplx.xowa.parsers.apos.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.lnkes.*; import gplx.xowa.parsers.lists.*; import gplx.xowa.htmls.core.wkrs.lnkis.htmls.*; import gplx.xowa.parsers.tblws.*; import gplx.xowa.parsers.paras.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.lnkis.*; import gplx.xowa.parsers.miscs.*; import gplx.xowa.parsers.htmls.*;
|
import gplx.xowa.parsers.*; import gplx.xowa.parsers.apos.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.lnkes.*; import gplx.xowa.parsers.lists.*; import gplx.xowa.htmls.core.wkrs.lnkis.htmls.*; import gplx.xowa.parsers.tblws.*; import gplx.xowa.parsers.paras.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.lnkis.*; import gplx.xowa.parsers.miscs.*; import gplx.xowa.parsers.htmls.*; import gplx.xowa.parsers.uniqs.*;
|
||||||
import gplx.xowa.xtns.*; import gplx.xowa.xtns.cites.*; import gplx.xowa.parsers.hdrs.*;
|
import gplx.xowa.xtns.*; import gplx.xowa.xtns.cites.*; import gplx.xowa.parsers.hdrs.*;
|
||||||
public class Xoh_html_wtr {
|
public class Xoh_html_wtr {
|
||||||
private final Xoae_app app; private final Xowe_wiki wiki; private final Xow_html_mgr html_mgr; private final Xop_xatr_whitelist_mgr whitelist_mgr;
|
private final Xoae_app app; private final Xowe_wiki wiki; private final Xow_html_mgr html_mgr; private final Xop_xatr_whitelist_mgr whitelist_mgr;
|
||||||
@ -90,6 +90,7 @@ public class Xoh_html_wtr {
|
|||||||
case Xop_tkn_itm_.Tid_tblw_tc: Tblw (bfr, ctx, hctx, src, (Xop_tblw_tkn)tkn, Gfh_tag_.Caption_lhs_bgn , Gfh_tag_.Caption_rhs, false); break;
|
case Xop_tkn_itm_.Tid_tblw_tc: Tblw (bfr, ctx, hctx, src, (Xop_tblw_tkn)tkn, Gfh_tag_.Caption_lhs_bgn , Gfh_tag_.Caption_rhs, false); break;
|
||||||
case Xop_tkn_itm_.Tid_newLine: New_line (bfr, ctx, hctx, src, (Xop_nl_tkn)tkn); break;
|
case Xop_tkn_itm_.Tid_newLine: New_line (bfr, ctx, hctx, src, (Xop_nl_tkn)tkn); break;
|
||||||
case Xop_tkn_itm_.Tid_bry: Bry (bfr, ctx, hctx, src, (Xop_bry_tkn)tkn); break;
|
case Xop_tkn_itm_.Tid_bry: Bry (bfr, ctx, hctx, src, (Xop_bry_tkn)tkn); break;
|
||||||
|
case Xop_tkn_itm_.Tid_uniq: Uniq (bfr, ctx, hctx, src, (Xop_uniq_tkn)tkn); break;
|
||||||
case Xop_tkn_itm_.Tid_lnki: lnki_wtr.Write_lnki(bfr, hctx, src, (Xop_lnki_tkn)tkn); break;
|
case Xop_tkn_itm_.Tid_lnki: lnki_wtr.Write_lnki(bfr, hctx, src, (Xop_lnki_tkn)tkn); break;
|
||||||
case Xop_tkn_itm_.Tid_lnke: wkr__lnke.Write_html(bfr, html_mgr, this, hctx, ctx, src, (Xop_lnke_tkn)tkn); break;
|
case Xop_tkn_itm_.Tid_lnke: wkr__lnke.Write_html(bfr, html_mgr, this, hctx, ctx, src, (Xop_lnke_tkn)tkn); break;
|
||||||
case Xop_tkn_itm_.Tid_hdr: wkr__hdr.Write_html(bfr, this, wiki, page, ctx, hctx, cfg, grp, sub_idx, src, (Xop_hdr_tkn)tkn); break;
|
case Xop_tkn_itm_.Tid_hdr: wkr__hdr.Write_html(bfr, this, wiki, page, ctx, hctx, cfg, grp, sub_idx, src, (Xop_hdr_tkn)tkn); break;
|
||||||
@ -232,6 +233,10 @@ public class Xoh_html_wtr {
|
|||||||
private void Bry(Bry_bfr bfr, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_bry_tkn bry) {
|
private void Bry(Bry_bfr bfr, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_bry_tkn bry) {
|
||||||
bfr.Add(bry.Val());
|
bfr.Add(bry.Val());
|
||||||
}
|
}
|
||||||
|
private void Uniq(Bry_bfr bfr, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_uniq_tkn tkn) {
|
||||||
|
byte[] val = wiki.Parser_mgr().Uniq_mgr().Get(tkn.Key());
|
||||||
|
Xoh_html_wtr_escaper.Escape(app.Parser_amp_mgr(), bfr, val, 0, val.length, true, false);
|
||||||
|
}
|
||||||
private void Under(Bry_bfr bfr, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_under_tkn under) {
|
private void Under(Bry_bfr bfr, Xop_ctx ctx, Xoh_wtr_ctx hctx, byte[] src, Xop_under_tkn under) {
|
||||||
if (hctx.Mode_is_alt()) return;
|
if (hctx.Mode_is_alt()) return;
|
||||||
switch (under.Under_tid()) {
|
switch (under.Under_tid()) {
|
||||||
@ -436,7 +441,7 @@ public class Xoh_html_wtr {
|
|||||||
for (int i = 0; i < ary_len; i++) {
|
for (int i = 0; i < ary_len; i++) {
|
||||||
Mwh_atr_itm atr = ary[i];
|
Mwh_atr_itm atr = ary[i];
|
||||||
if (atr.Invalid()) continue;
|
if (atr.Invalid()) continue;
|
||||||
if (!whitelist_mgr.Chk(tag_id, src, atr)) continue;
|
if (!whitelist_mgr.Chk(tag_id, atr)) continue;
|
||||||
Xnde_atr_write(bfr, app, hctx, src, atr);
|
Xnde_atr_write(bfr, app, hctx, src, atr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,7 +468,7 @@ public class Xoh_html_wtr {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (atr.Val_bry() == null)
|
if (atr.Val_bry() == null)
|
||||||
bfr.Add_mid(src, atr.Val_bgn(), atr.Val_end());
|
bfr.Add_mid(atr.Src(), atr.Val_bgn(), atr.Val_end());
|
||||||
else
|
else
|
||||||
bfr.Add(atr.Val_bry());
|
bfr.Add(atr.Val_bry());
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class Xoh_hdr_html {
|
|||||||
|
|
||||||
// register hdr with TOC
|
// register hdr with TOC
|
||||||
byte[] hdr_text_bry = Bld_hdr_html(hdr_text_bfr, wtr, page, ctx, hctx, src, hdr);
|
byte[] hdr_text_bry = Bld_hdr_html(hdr_text_bfr, wtr, page, ctx, hctx, src, hdr);
|
||||||
hdr_text_bry = wiki.Parser_mgr().Uniq_mgr().Convert(hdr_text_bry); // need for math; DATE:2016-12-09
|
hdr_text_bry = wiki.Parser_mgr().Uniq_mgr().Parse(hdr_text_bry); // need for math; DATE:2016-12-09
|
||||||
Xoh_toc_itm toc_itm = hdr_is_valid && hdr_text_bry.length > 0
|
Xoh_toc_itm toc_itm = hdr_is_valid && hdr_text_bry.length > 0
|
||||||
? page.Html_data().Toc_mgr().Add(hdr_num, hdr_text_bry)
|
? page.Html_data().Toc_mgr().Add(hdr_num, hdr_text_bry)
|
||||||
: invalid_toc_itm;
|
: invalid_toc_itm;
|
||||||
|
@ -59,9 +59,13 @@ public class Xol_lang_itm implements Gfo_invk {
|
|||||||
public Xol_lang_itm Fallback_bry_(byte[] v) {
|
public Xol_lang_itm Fallback_bry_(byte[] v) {
|
||||||
fallback_bry = v;
|
fallback_bry = v;
|
||||||
fallback_bry_ary = Fallbacy_bry_ary__bld(v);
|
fallback_bry_ary = Fallbacy_bry_ary__bld(v);
|
||||||
|
for (byte[] key : fallback_bry_ary) {
|
||||||
|
fallback_hash.Add_as_key_and_val(String_.new_u8(key));
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
} private byte[] fallback_bry;
|
} private byte[] fallback_bry;
|
||||||
public byte[][] Fallback_bry_ary() {return fallback_bry_ary;} private byte[][] fallback_bry_ary = Bry_.Ary_empty;
|
public byte[][] Fallback_bry_ary() {return fallback_bry_ary;} private byte[][] fallback_bry_ary = Bry_.Ary_empty;
|
||||||
|
public Ordered_hash Fallback_hash() {return fallback_hash;} private final Ordered_hash fallback_hash = Ordered_hash_.New();
|
||||||
public boolean Dir_ltr() {return dir_ltr;} private boolean dir_ltr = true;
|
public boolean Dir_ltr() {return dir_ltr;} private boolean dir_ltr = true;
|
||||||
public void Dir_ltr_(boolean v) {
|
public void Dir_ltr_(boolean v) {
|
||||||
dir_ltr = v;
|
dir_ltr = v;
|
||||||
|
@ -20,6 +20,6 @@ public class Xop_lxr_ {
|
|||||||
, Tid_list = 10, Tid_hdr = 11, Tid_hr = 12, Tid_xnde = 13, Tid_lnke_bgn = 14, Tid_lnke_end = 15, Tid_tblw = 16, Tid_pre = 17, Tid_under = 18, Tid_comment = 19
|
, Tid_list = 10, Tid_hdr = 11, Tid_hr = 12, Tid_xnde = 13, Tid_lnke_bgn = 14, Tid_lnke_end = 15, Tid_tblw = 16, Tid_pre = 17, Tid_under = 18, Tid_comment = 19
|
||||||
, Tid_eq = 20, Tid_curly_bgn = 21, Tid_curly_end = 22, Tid_brack_bgn = 23, Tid_brack_end = 24, Tid_poem = 25
|
, Tid_eq = 20, Tid_curly_bgn = 21, Tid_curly_end = 22, Tid_brack_bgn = 23, Tid_brack_end = 24, Tid_poem = 25
|
||||||
, Tid_tvar = 26, Tid_vnt_bgn = 27, Tid_vnt_end = 28, Tid_vnt_eqgt = 29, Tid_vnt_tmpl_bgn = 30, Tid_word = 31, Tid_nl_poem = 32, Tid_cr = 33
|
, Tid_tvar = 26, Tid_vnt_bgn = 27, Tid_vnt_end = 28, Tid_vnt_eqgt = 29, Tid_vnt_tmpl_bgn = 30, Tid_word = 31, Tid_nl_poem = 32, Tid_cr = 33
|
||||||
, Tid_brack_end_lnki = 34, Tid_nl_tab = 35, Tid_escape = 36
|
, Tid_brack_end_lnki = 34, Tid_nl_tab = 35, Tid_escape = 36, Tid_uniq = 37
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
package gplx.xowa.parsers; import gplx.*; import gplx.xowa.*;
|
package gplx.xowa.parsers; import gplx.*; import gplx.xowa.*;
|
||||||
import gplx.core.btries.*;
|
import gplx.core.btries.*;
|
||||||
import gplx.xowa.langs.*;
|
import gplx.xowa.langs.*;
|
||||||
import gplx.xowa.parsers.apos.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.lnkes.*; import gplx.xowa.parsers.hdrs.*; import gplx.xowa.parsers.lists.*; import gplx.xowa.parsers.tblws.*; import gplx.xowa.parsers.paras.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.lnkis.*; import gplx.xowa.parsers.tmpls.*; import gplx.xowa.parsers.miscs.*;
|
import gplx.xowa.parsers.apos.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.lnkes.*; import gplx.xowa.parsers.hdrs.*; import gplx.xowa.parsers.lists.*; import gplx.xowa.parsers.tblws.*; import gplx.xowa.parsers.paras.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.lnkis.*; import gplx.xowa.parsers.tmpls.*; import gplx.xowa.parsers.miscs.*; import gplx.xowa.parsers.uniqs.*;
|
||||||
public class Xop_lxr_mgr {
|
public class Xop_lxr_mgr {
|
||||||
private final Xop_lxr[] ary;
|
private final Xop_lxr[] ary;
|
||||||
private final List_adp page_lxr_list = List_adp_.New();
|
private final List_adp page_lxr_list = List_adp_.New();
|
||||||
@ -77,6 +77,7 @@ public class Xop_lxr_mgr {
|
|||||||
, Xop_pre_lxr.Instance, Xop_nl_tab_lxr.Instance
|
, Xop_pre_lxr.Instance, Xop_nl_tab_lxr.Instance
|
||||||
, Xop_comm_lxr.Instance
|
, Xop_comm_lxr.Instance
|
||||||
, Xop_under_lxr.Instance
|
, Xop_under_lxr.Instance
|
||||||
|
// , Xop_uniq_lxr.Instance // NOWIKI;DATE:2018-01-16
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static Xop_lxr_mgr new_anchor_encoder() {
|
public static Xop_lxr_mgr new_anchor_encoder() {
|
||||||
|
@ -15,7 +15,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
*/
|
*/
|
||||||
package gplx.xowa.parsers; import gplx.*; import gplx.xowa.*;
|
package gplx.xowa.parsers; import gplx.*; import gplx.xowa.*;
|
||||||
public class Xop_tkn_itm_ {
|
public class Xop_tkn_itm_ {
|
||||||
public static final Xop_tkn_itm[] Ary_empty = new Xop_tkn_itm[0];
|
public static final Xop_tkn_itm[] Ary_empty = new Xop_tkn_itm[0];
|
||||||
public static final byte
|
public static final byte
|
||||||
Tid_null = 0
|
Tid_null = 0
|
||||||
, Tid_root = 1
|
, Tid_root = 1
|
||||||
@ -69,8 +69,9 @@ public class Xop_tkn_itm_ {
|
|||||||
, Tid_vnt_eqgt = 49
|
, Tid_vnt_eqgt = 49
|
||||||
, Tid_cr = 50
|
, Tid_cr = 50
|
||||||
, Tid_escape = 51
|
, Tid_escape = 51
|
||||||
|
, Tid_uniq = 52
|
||||||
;
|
;
|
||||||
public static final String[] Tid__names
|
public static final String[] Tid__names
|
||||||
= new String[]
|
= new String[]
|
||||||
{ "null"
|
{ "null"
|
||||||
, "root"
|
, "root"
|
||||||
@ -124,5 +125,6 @@ public static final String[] Tid__names
|
|||||||
, "vnt_eqgt"
|
, "vnt_eqgt"
|
||||||
, "cr"
|
, "cr"
|
||||||
, "escape"
|
, "escape"
|
||||||
|
, "uniq"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ class Xop_section_list implements Xomw_heading_cbk {
|
|||||||
key = wiki.Parser_mgr().Main().Parse_text_to_html(wiki.Parser_mgr().Ctx(), key);
|
key = wiki.Parser_mgr().Main().Parse_text_to_html(wiki.Parser_mgr().Ctx(), key);
|
||||||
|
|
||||||
// handle math; EX: "== <math>\delta</math> =="
|
// handle math; EX: "== <math>\delta</math> =="
|
||||||
key = wiki.Parser_mgr().Uniq_mgr().Convert(key);
|
key = wiki.Parser_mgr().Uniq_mgr().Parse(key);
|
||||||
|
|
||||||
// convert key to toc_text to handle (a) XML ("<i>a</i>" -> "a"); (b) dupes ("text" -> "text_2")
|
// convert key to toc_text to handle (a) XML ("<i>a</i>" -> "a"); (b) dupes ("text" -> "text_2")
|
||||||
int num = wkr.Hdr_num();
|
int num = wkr.Hdr_num();
|
||||||
|
@ -71,7 +71,7 @@ public class Xop_section_mgr implements Gfo_invk {
|
|||||||
this.fmt__edit_hint.Fmt_(String_.new_u8(wiki.Msg_mgr().Val_by_key_obj("editsectionhint")));
|
this.fmt__edit_hint.Fmt_(String_.new_u8(wiki.Msg_mgr().Val_by_key_obj("editsectionhint")));
|
||||||
}
|
}
|
||||||
|
|
||||||
section_key = wiki.Parser_mgr().Uniq_mgr().Convert(section_key); // need to swap out uniqs for Math; DATE:2016-12-09
|
section_key = wiki.Parser_mgr().Uniq_mgr().Parse(section_key); // need to swap out uniqs for Math; DATE:2016-12-09
|
||||||
byte[] edit_hint = fmt__edit_hint.Bld_many_to_bry(tmp_bfr, section_hint);
|
byte[] edit_hint = fmt__edit_hint.Bld_many_to_bry(tmp_bfr, section_hint);
|
||||||
fmt__section_editable.Bld_many(bfr, page_ttl, section_key, edit_hint, bry__edit_text);
|
fmt__section_editable.Bld_many(bfr, page_ttl, section_key, edit_hint, bry__edit_text);
|
||||||
}
|
}
|
||||||
|
@ -28,22 +28,22 @@ public class Mwh_atr_itm {
|
|||||||
this.val_bgn = val_bgn; this.val_end = val_end; this.val_bry = val_bry;
|
this.val_bgn = val_bgn; this.val_end = val_end; this.val_bry = val_bry;
|
||||||
this.eql_pos = eql_pos; this.qte_tid = qte_tid;
|
this.eql_pos = eql_pos; this.qte_tid = qte_tid;
|
||||||
}
|
}
|
||||||
public byte[] Src() {return src;} private final byte[] src;
|
public byte[] Src() {return src;} private final byte[] src;
|
||||||
public boolean Valid() {return valid;} private final boolean valid;
|
public boolean Valid() {return valid;} private final boolean valid;
|
||||||
public boolean Key_exists() {return key_exists;} private final boolean key_exists;
|
public boolean Key_exists() {return key_exists;} private final boolean key_exists;
|
||||||
public boolean Repeated() {return repeated;} private final boolean repeated;
|
public boolean Repeated() {return repeated;} private final boolean repeated;
|
||||||
public boolean Invalid() {return repeated || !valid;}
|
public boolean Invalid() {return repeated || !valid;}
|
||||||
public int Atr_bgn() {return atr_bgn;} private int atr_bgn;
|
public int Atr_bgn() {return atr_bgn;} private int atr_bgn;
|
||||||
public int Atr_end() {return atr_end;} private int atr_end;
|
public int Atr_end() {return atr_end;} private int atr_end;
|
||||||
public int Key_bgn() {return key_bgn;} private final int key_bgn;
|
public int Key_bgn() {return key_bgn;} private final int key_bgn;
|
||||||
public int Key_end() {return key_end;} private final int key_end;
|
public int Key_end() {return key_end;} private final int key_end;
|
||||||
public byte[] Key_bry() {return key_bry;} private byte[] key_bry;
|
public byte[] Key_bry() {return key_bry;} private byte[] key_bry;
|
||||||
public byte Key_tid() {return key_tid;} public Mwh_atr_itm Key_tid_(byte v) {key_tid = v; return this;} private byte key_tid;
|
public byte Key_tid() {return key_tid;} public Mwh_atr_itm Key_tid_(byte v) {key_tid = v; return this;} private byte key_tid;
|
||||||
public int Val_bgn() {return val_bgn;} private final int val_bgn;
|
public int Val_bgn() {return val_bgn;} private final int val_bgn;
|
||||||
public int Val_end() {return val_end;} private final int val_end;
|
public int Val_end() {return val_end;} private final int val_end;
|
||||||
public byte[] Val_bry() {return val_bry;} private byte[] val_bry;
|
public byte[] Val_bry() {return val_bry;} private byte[] val_bry;
|
||||||
public int Eql_pos() {return eql_pos;} private final int eql_pos;
|
public int Eql_pos() {return eql_pos;} private final int eql_pos;
|
||||||
public int Qte_tid() {return qte_tid;} private final int qte_tid;
|
public int Qte_tid() {return qte_tid;} private final int qte_tid;
|
||||||
public byte Qte_byte() {
|
public byte Qte_byte() {
|
||||||
switch (qte_tid) {
|
switch (qte_tid) {
|
||||||
case Mwh_atr_itm_.Qte_tid__none: return Byte_ascii.Null;
|
case Mwh_atr_itm_.Qte_tid__none: return Byte_ascii.Null;
|
||||||
@ -53,7 +53,6 @@ public class Mwh_atr_itm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Mwh_atr_itm Atr_rng(int bgn, int end) {this.atr_bgn = bgn; this.atr_end = end; return this;}
|
public Mwh_atr_itm Atr_rng(int bgn, int end) {this.atr_bgn = bgn; this.atr_end = end; return this;}
|
||||||
public void Key_bry_(byte[] v) {this.key_bry = v;}
|
|
||||||
public void Val_bry_(byte[] v) {this.val_bry = v;}
|
public void Val_bry_(byte[] v) {this.val_bry = v;}
|
||||||
public String Val_as_str() {return String_.new_u8(Val_as_bry());}
|
public String Val_as_str() {return String_.new_u8(Val_as_bry());}
|
||||||
public byte[] Val_as_bry() {if (val_bry == null) val_bry = Bry_.Mid(src, val_bgn, val_end); return val_bry;} // NOTE: val_bry is cached
|
public byte[] Val_as_bry() {if (val_bry == null) val_bry = Bry_.Mid(src, val_bgn, val_end); return val_bry;} // NOTE: val_bry is cached
|
||||||
|
@ -493,6 +493,9 @@ public class Xop_tblw_wkr implements Xop_ctx_wkr {
|
|||||||
atrs_bgn = Bry_find_.Find_fwd_while(src, atrs_bgn, src.length, Byte_ascii.Dash);
|
atrs_bgn = Bry_find_.Find_fwd_while(src, atrs_bgn, src.length, Byte_ascii.Dash);
|
||||||
prv_tblw.Atrs_rng_set(atrs_bgn, atrs_end);
|
prv_tblw.Atrs_rng_set(atrs_bgn, atrs_end);
|
||||||
if (ctx.Parse_tid() == Xop_parser_tid_.Tid__wtxt && atrs_bgn != -1) {
|
if (ctx.Parse_tid() == Xop_parser_tid_.Tid__wtxt && atrs_bgn != -1) {
|
||||||
|
// NOWIKI;DATE:2018-01-16
|
||||||
|
// byte[] converted = ctx.Wiki().Parser_mgr().Uniq_mgr().Parse(Bool_.N, Bry_.Mid(src, atrs_bgn, atrs_end));
|
||||||
|
// Mwh_atr_itm[] atrs = ctx.App().Parser_mgr().Xnde__parse_atrs(converted, 0, converted.length);
|
||||||
Mwh_atr_itm[] atrs = ctx.App().Parser_mgr().Xnde__parse_atrs_for_tblw(src, atrs_bgn, atrs_end);
|
Mwh_atr_itm[] atrs = ctx.App().Parser_mgr().Xnde__parse_atrs_for_tblw(src, atrs_bgn, atrs_end);
|
||||||
prv_tblw.Atrs_ary_as_tblw_(atrs);
|
prv_tblw.Atrs_ary_as_tblw_(atrs);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
package gplx.xowa.parsers.tblws; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
package gplx.xowa.parsers.tblws; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
public class Xop_tblw_wkr__uncommon_tst {
|
public class Xop_tblw_wkr__uncommon_tst {
|
||||||
@Before public void init() {fxt.Reset(); fxt.Init_para_y_();} private final Xop_fxt fxt = new Xop_fxt();
|
@Before public void init() {fxt.Reset(); fxt.Init_para_y_();} private final Xop_fxt fxt = new Xop_fxt();
|
||||||
@After public void term() {fxt.Init_para_n_();}
|
@After public void term() {fxt.Init_para_n_();}
|
||||||
@Test public void Tr_pops_entire_stack() { // PURPOSE: in strange cases, tr will pop entire stack; PAGE:en.w:Turks_in_Denmark; DATE:2014-03-02
|
@Test public void Tr_pops_entire_stack() { // PURPOSE: in strange cases, tr will pop entire stack; PAGE:en.w:Turks_in_Denmark; DATE:2014-03-02
|
||||||
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
|
fxt.Test_parse_page_all_str(String_.Concat_lines_nl_skip_last
|
||||||
|
@ -62,8 +62,12 @@ public class Xot_tmpl_wtr {
|
|||||||
if (xnde.Tag_close_bgn() == Int_.Min_value)
|
if (xnde.Tag_close_bgn() == Int_.Min_value)
|
||||||
rslt_bfr.Add_mid(src, tkn.Src_bgn(), tkn.Src_end()); // write src from bgn/end
|
rslt_bfr.Add_mid(src, tkn.Src_bgn(), tkn.Src_end()); // write src from bgn/end
|
||||||
else { // NOTE: if nowiki then "deactivate" all xndes by swapping out < for < nowiki_xnde_frag; DATE:2013-01-27
|
else { // NOTE: if nowiki then "deactivate" all xndes by swapping out < for < nowiki_xnde_frag; DATE:2013-01-27
|
||||||
Bry_bfr tmp_bfr = ctx.Wiki().Utl__bfr_mkr().Get_k004();
|
// NOWIKI;DATE:2018-01-16
|
||||||
|
// byte[] uniq = ctx.Wiki().Parser_mgr().Uniq_mgr().Add(Bool_.N, Bry_.Empty, Bry_.Mid(src, xnde.Tag_open_end(), xnde.Tag_close_bgn()));
|
||||||
|
// rslt_bfr.Add(uniq);
|
||||||
|
|
||||||
int nowiki_content_bgn = xnde.Tag_open_end(), nowiki_content_end = xnde.Tag_close_bgn();
|
int nowiki_content_bgn = xnde.Tag_open_end(), nowiki_content_end = xnde.Tag_close_bgn();
|
||||||
|
Bry_bfr tmp_bfr = ctx.Wiki().Utl__bfr_mkr().Get_k004();
|
||||||
boolean escaped = gplx.xowa.parsers.tmpls.Nowiki_escape_itm.Escape(tmp_bfr, src, nowiki_content_bgn, nowiki_content_end);
|
boolean escaped = gplx.xowa.parsers.tmpls.Nowiki_escape_itm.Escape(tmp_bfr, src, nowiki_content_bgn, nowiki_content_end);
|
||||||
rslt_bfr.Add_bfr_or_mid(escaped, tmp_bfr, src, nowiki_content_bgn, nowiki_content_end);
|
rslt_bfr.Add_bfr_or_mid(escaped, tmp_bfr, src, nowiki_content_bgn, nowiki_content_end);
|
||||||
tmp_bfr.Mkr_rls();
|
tmp_bfr.Mkr_rls();
|
||||||
|
30
400_xowa/src/gplx/xowa/parsers/uniqs/Xop_uniq_itm.java
Normal file
30
400_xowa/src/gplx/xowa/parsers/uniqs/Xop_uniq_itm.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.parsers.uniqs; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||||
|
class Xop_uniq_itm {
|
||||||
|
public Xop_uniq_itm(boolean expand_after_template_parsing, byte[] type, int idx, byte[] key, byte[] val) {
|
||||||
|
this.expand_after_template_parsing = expand_after_template_parsing;
|
||||||
|
this.type = type;
|
||||||
|
this.idx = idx;
|
||||||
|
this.key = key;
|
||||||
|
this.val = val;
|
||||||
|
}
|
||||||
|
public boolean Expand_after_template_parsing() {return expand_after_template_parsing;} private final boolean expand_after_template_parsing;
|
||||||
|
public byte[] Type() {return type;} private final byte[] type;
|
||||||
|
public int Idx() {return idx;} private final int idx;
|
||||||
|
public byte[] Key() {return key;} private final byte[] key;
|
||||||
|
public byte[] Val() {return val;} private final byte[] val;
|
||||||
|
}
|
41
400_xowa/src/gplx/xowa/parsers/uniqs/Xop_uniq_lxr.java
Normal file
41
400_xowa/src/gplx/xowa/parsers/uniqs/Xop_uniq_lxr.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.parsers.uniqs; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||||
|
import gplx.core.btries.*; import gplx.xowa.langs.*;
|
||||||
|
// EX: "\u007fUNIQ-item-1-QINU\u007f"
|
||||||
|
public class Xop_uniq_lxr implements Xop_lxr {
|
||||||
|
public int Lxr_tid() {return Xop_lxr_.Tid_uniq;}
|
||||||
|
public void Init_by_wiki(Xowe_wiki wiki, Btrie_fast_mgr core_trie) {
|
||||||
|
core_trie.Add(Xop_uniq_mgr.Bry__uniq__bgn_w_dash, this);
|
||||||
|
}
|
||||||
|
public void Init_by_lang(Xol_lang_itm lang, Btrie_fast_mgr core_trie) {}
|
||||||
|
public void Term(Btrie_fast_mgr core_trie) {}
|
||||||
|
public int Make_tkn(Xop_ctx ctx, Xop_tkn_mkr tkn_mkr, Xop_root_tkn root, byte[] src, int src_len, int bgn_pos, int cur_pos) {
|
||||||
|
// find end
|
||||||
|
int rhs_bgn = Bry_find_.Find_fwd(src, Xop_uniq_mgr.Bry__uniq__add__end, cur_pos);
|
||||||
|
if (rhs_bgn == Bry_find_.Not_found) {
|
||||||
|
Gfo_usr_dlg_.Instance.Warn_many("", "", "uniq_mgr:unable to find uniq; src=~{0}", src);
|
||||||
|
return ctx.Lxr_make_txt_(cur_pos);
|
||||||
|
}
|
||||||
|
int rhs_end = rhs_bgn + Xop_uniq_mgr.Bry__uniq__add__end.length;
|
||||||
|
|
||||||
|
byte[] key = Bry_.Mid(src, bgn_pos, rhs_end);
|
||||||
|
Xop_uniq_tkn uniq_tkn = new Xop_uniq_tkn(bgn_pos, rhs_end, key);
|
||||||
|
ctx.Subs_add(root, uniq_tkn);
|
||||||
|
return rhs_end;
|
||||||
|
}
|
||||||
|
public static final Xop_uniq_lxr Instance = new Xop_uniq_lxr(); Xop_uniq_lxr() {}
|
||||||
|
}
|
@ -17,88 +17,73 @@ package gplx.xowa.parsers.uniqs; import gplx.*; import gplx.xowa.*; import gplx.
|
|||||||
import gplx.core.btries.*;
|
import gplx.core.btries.*;
|
||||||
public class Xop_uniq_mgr { // REF.MW:/parser/StripState.php
|
public class Xop_uniq_mgr { // REF.MW:/parser/StripState.php
|
||||||
private final Btrie_slim_mgr general_trie = Btrie_slim_mgr.cs(); private final Btrie_rv trv = new Btrie_rv();
|
private final Btrie_slim_mgr general_trie = Btrie_slim_mgr.cs(); private final Btrie_rv trv = new Btrie_rv();
|
||||||
private final Bry_bfr key_bfr = Bry_bfr_.New_w_size(32);
|
private final Bry_bfr tmp_bfr = Bry_bfr_.New_w_size(32);
|
||||||
private int idx = -1;
|
private int nxt_idx = -1;
|
||||||
public void Clear() {idx = -1; general_trie.Clear();}
|
public void Clear() {
|
||||||
public byte[] Get(byte[] key) {return (byte[])general_trie.Match_exact(key, 0, key.length);}
|
nxt_idx = -1;
|
||||||
public byte[] Add(byte[] type, byte[] val) {// "<b>" -> "\u007fUNIQ-item-1--QINU\u007f"
|
general_trie.Clear();
|
||||||
byte[] key = key_bfr
|
|
||||||
.Add(Bry__uniq__bgn_w_dash)
|
|
||||||
.Add(type).Add_byte(Byte_ascii.Dash) // EX: "ref-"
|
|
||||||
.Add_int_variable(++idx)
|
|
||||||
.Add(Bry__uniq__add__end).To_bry_and_clear();
|
|
||||||
general_trie.Add_bry_bry(key, val);
|
|
||||||
return key;
|
|
||||||
}
|
}
|
||||||
public byte[] Convert(byte[] src) {
|
public byte[] Get(byte[] key) {
|
||||||
if (general_trie.Count() == 0) return src;
|
Xop_uniq_itm itm = (Xop_uniq_itm)general_trie.Match_exact(key, 0, key.length);
|
||||||
|
return itm.Val();
|
||||||
Bry_bfr dirty_bfr = null;
|
}
|
||||||
int cur = 0;
|
public byte[] Add(boolean expand_after_template_parsing, byte[] type, byte[] val) {// "<b>" -> "\u007fUNIQ-item-1-QINU\u007f"
|
||||||
int len = src.length;
|
int idx = ++nxt_idx;
|
||||||
while (cur < len) {
|
byte[] key = tmp_bfr
|
||||||
// find "\u007fUNIQ-"
|
.Add(Bry__uniq__bgn_w_dash) // "\u007f'\"`UNIQ-"
|
||||||
int uniq_bgn = Bry_find_.Find_fwd(src, Bry__uniq__bgn_w_dash, cur);
|
.Add(type).Add_byte(Byte_ascii.Dash) // "ref-"
|
||||||
if (uniq_bgn == Bry_find_.Not_found) break;
|
.Add_int_variable(idx) // "1"
|
||||||
|
.Add(Bry__uniq__add__end) // "-QINU`\"'\u007f"
|
||||||
// find "-"; EX: ref-
|
.To_bry_and_clear();
|
||||||
int tmp_pos = uniq_bgn;
|
Xop_uniq_itm itm = new Xop_uniq_itm(expand_after_template_parsing, type, idx, key, val);
|
||||||
tmp_pos = Bry_find_.Find_fwd(src, Byte_ascii.Dash, tmp_pos, len);
|
general_trie.Add_obj(key, itm);
|
||||||
if (tmp_pos == Bry_find_.Not_found) {
|
return key;
|
||||||
Gfo_usr_dlg_.Instance.Warn_many("", "", "uniq_mgr:unable to find 2nd dash; src=~{0}", src);
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find end
|
|
||||||
int uniq_end = Bry_find_.Find_fwd(src, Bry__uniq__add__end, tmp_pos);
|
|
||||||
if (uniq_end == Bry_find_.Not_found) {
|
|
||||||
Gfo_usr_dlg_.Instance.Warn_many("", "", "uniq_mgr:unable to convert uniq; src=~{0}", src);
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
uniq_end += Bry__uniq__add__end.length;
|
|
||||||
|
|
||||||
// add to bfr
|
|
||||||
if (dirty_bfr == null) dirty_bfr = key_bfr;
|
|
||||||
dirty_bfr.Add_mid(src, cur, uniq_bgn);
|
|
||||||
dirty_bfr.Add((byte[])general_trie.Match_exact(src, uniq_bgn, uniq_end));
|
|
||||||
cur = uniq_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dirty_bfr != null) {
|
|
||||||
dirty_bfr.Add_mid(src, cur, len);
|
|
||||||
}
|
|
||||||
return dirty_bfr == null ? src : dirty_bfr.To_bry_and_clear();
|
|
||||||
}
|
}
|
||||||
public void Parse(Bry_bfr bfr) {
|
public void Parse(Bry_bfr bfr) {
|
||||||
if (general_trie.Count() == 0) return;
|
if (general_trie.Count() == 0) return;
|
||||||
byte[] rv = Parse(key_bfr, general_trie, bfr.To_bry_and_clear());
|
byte[] rv = Parse_recurse(Bool_.Y, tmp_bfr, bfr.To_bry_and_clear());
|
||||||
bfr.Add(rv);
|
bfr.Add(rv);
|
||||||
}
|
}
|
||||||
public byte[] Parse(byte[] src) {return Parse(key_bfr, general_trie, src);}
|
public byte[] Parse(boolean template_parsing, byte[] src) {return Parse_recurse(template_parsing, tmp_bfr, src);}
|
||||||
private byte[] Parse(Bry_bfr bfr, Btrie_slim_mgr trie, byte[] src) {
|
public byte[] Parse(byte[] src) {return Parse_recurse(Bool_.Y, tmp_bfr, src);}
|
||||||
|
private byte[] Parse_recurse(boolean template_parsing, Bry_bfr bfr, byte[] src) {
|
||||||
int src_len = src.length;
|
int src_len = src.length;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int mark_bgn = 0;
|
int prv_bgn = 0;
|
||||||
boolean dirty = false;
|
boolean dirty = false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
boolean is_last = pos == src_len;
|
boolean is_last = pos == src_len;
|
||||||
byte b = is_last ? Byte_ascii.Null : src[pos];
|
byte b = is_last ? Byte_ascii.Null : src[pos];
|
||||||
Object o = trie.Match_at_w_b0(trv, b, src, pos, src_len);
|
Object o = general_trie.Match_at_w_b0(trv, b, src, pos, src_len);
|
||||||
|
|
||||||
|
// match not found for "\x7fUNIQ"; move on to next
|
||||||
if (o == null)
|
if (o == null)
|
||||||
++pos;
|
pos++;
|
||||||
|
// match found
|
||||||
else {
|
else {
|
||||||
byte[] val = (byte[])o;
|
Xop_uniq_itm itm = (Xop_uniq_itm)o;
|
||||||
int new_pos = trv.Pos(); // NOTE: since trie is reused, must capture pos here
|
int itm_end = trv.Pos(); // NOTE: must capture pos since trv is reused in the recursive call below
|
||||||
val = Parse(Bry_bfr_.New(), trie, val);
|
// skip if template_parsing
|
||||||
|
if (template_parsing
|
||||||
|
&& !itm.Expand_after_template_parsing()) {
|
||||||
|
pos = itm_end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add everything from prv_bgn up to UNIQ
|
||||||
|
bfr.Add_mid(src, prv_bgn, pos);
|
||||||
|
|
||||||
|
// expand UNIQ (can be recursive)
|
||||||
|
byte[] val = Parse_recurse(template_parsing, Bry_bfr_.New(), itm.Val());
|
||||||
// val = gplx.xowa.parsers.xndes.Xop_xnde_tkn.Hack_ctx.Wiki().Parser_mgr().Main().Parse_text_to_html(gplx.xowa.parsers.xndes.Xop_xnde_tkn.Hack_ctx, val); // CHART
|
// val = gplx.xowa.parsers.xndes.Xop_xnde_tkn.Hack_ctx.Wiki().Parser_mgr().Main().Parse_text_to_html(gplx.xowa.parsers.xndes.Xop_xnde_tkn.Hack_ctx, val); // CHART
|
||||||
bfr.Add_mid(src, mark_bgn, pos);
|
|
||||||
bfr.Add(val);
|
bfr.Add(val);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
pos = mark_bgn = new_pos;
|
pos = prv_bgn = itm_end;
|
||||||
}
|
}
|
||||||
if (is_last) {
|
if (is_last) {
|
||||||
if (dirty)
|
if (dirty)
|
||||||
bfr.Add_mid(src, mark_bgn, src_len);
|
bfr.Add_mid(src, prv_bgn, src_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,19 +96,19 @@ public class Xop_uniq_mgr { // REF.MW:/parser/StripState.php
|
|||||||
}
|
}
|
||||||
public void Random_int_ary_(int... v) {random_int_ary = v;} private int[] random_int_ary; // TEST:
|
public void Random_int_ary_(int... v) {random_int_ary = v;} private int[] random_int_ary; // TEST:
|
||||||
public byte[] Random_bry_new(int len) {
|
public byte[] Random_bry_new(int len) {
|
||||||
Bry_bfr key_bfr = Bry_bfr_.New();
|
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||||
RandomAdp random_gen = RandomAdp_.new_();
|
RandomAdp random_gen = RandomAdp_.new_();
|
||||||
for (int i = 0; i < len; i += 7) {
|
for (int i = 0; i < len; i += 7) {
|
||||||
int rand = random_int_ary == null ? random_gen.Next(Int_.Max_value) : random_int_ary[i / 7];
|
int rand = random_int_ary == null ? random_gen.Next(Int_.Max_value) : random_int_ary[i / 7];
|
||||||
String rand_str = Int_.To_str_hex(Bool_.N, Bool_.Y, rand & 0xfffffff); // limits value to 268435455
|
String rand_str = Int_.To_str_hex(Bool_.N, Bool_.Y, rand & 0xfffffff); // limits value to 268435455
|
||||||
key_bfr.Add_str_a7(rand_str);
|
tmp_bfr.Add_str_a7(rand_str);
|
||||||
}
|
}
|
||||||
byte[] rv = key_bfr.To_bry(0, len);
|
byte[] rv = tmp_bfr.To_bry(0, len);
|
||||||
key_bfr.Clear();
|
tmp_bfr.Clear();
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final byte[]
|
public static final byte[]
|
||||||
Bry__uniq__bgn = Bry_.new_a7("\u007f'\"`UNIQ-")
|
Bry__uniq__bgn = Bry_.new_a7("\u007f'\"`UNIQ-")
|
||||||
, Bry__uniq__bgn_w_dash = Bry_.Add(Bry__uniq__bgn, Byte_ascii.Dash_bry)
|
, Bry__uniq__bgn_w_dash = Bry_.Add(Bry__uniq__bgn, Byte_ascii.Dash_bry)
|
||||||
, Bry__uniq__add__end = Bry_.new_a7("-QINU`\"'\u007f")
|
, Bry__uniq__add__end = Bry_.new_a7("-QINU`\"'\u007f")
|
||||||
|
@ -65,7 +65,7 @@ class Xop_uniq_mgr__fxt {
|
|||||||
Gftest.Eq__str(expd, String_.new_a7(mgr.Uniq_bry_new()), "unique_bry");
|
Gftest.Eq__str(expd, String_.new_a7(mgr.Uniq_bry_new()), "unique_bry");
|
||||||
}
|
}
|
||||||
public void Test__add(String raw, String expd) {
|
public void Test__add(String raw, String expd) {
|
||||||
Gftest.Eq__str(expd, String_.new_a7(mgr.Add(Bry_.new_a7("item"), Bry_.new_a7(raw))), "add");
|
Gftest.Eq__str(expd, String_.new_a7(mgr.Add(Bool_.Y, Bry_.new_a7("item"), Bry_.new_a7(raw))), "add");
|
||||||
}
|
}
|
||||||
public void Test__get(String key, String expd) {
|
public void Test__get(String key, String expd) {
|
||||||
Gftest.Eq__str(expd, String_.new_a7(mgr.Get(Bry_.new_a7(key))), "get");
|
Gftest.Eq__str(expd, String_.new_a7(mgr.Get(Bry_.new_a7(key))), "get");
|
||||||
@ -74,6 +74,6 @@ class Xop_uniq_mgr__fxt {
|
|||||||
Gftest.Eq__str(expd, String_.new_a7(mgr.Parse(Bry_.new_a7(raw))), "parse");
|
Gftest.Eq__str(expd, String_.new_a7(mgr.Parse(Bry_.new_a7(raw))), "parse");
|
||||||
}
|
}
|
||||||
public void Test__convert(String raw, String expd) {
|
public void Test__convert(String raw, String expd) {
|
||||||
Gftest.Eq__str(expd, String_.new_a7(mgr.Convert(Bry_.new_a7(raw))), "convert");
|
Gftest.Eq__str(expd, String_.new_a7(mgr.Parse(Bry_.new_a7(raw))), "convert");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
400_xowa/src/gplx/xowa/parsers/uniqs/Xop_uniq_tkn.java
Normal file
26
400_xowa/src/gplx/xowa/parsers/uniqs/Xop_uniq_tkn.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.parsers.uniqs; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||||
|
import gplx.langs.htmls.entitys.*;
|
||||||
|
// EX: "\u007fUNIQ-item-1--QINU\u007f"
|
||||||
|
public class Xop_uniq_tkn extends Xop_tkn_itm_base {
|
||||||
|
public Xop_uniq_tkn(int bgn, int end, byte[] key) {
|
||||||
|
this.Tkn_ini_pos(false, bgn, end);
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
@Override public byte Tkn_tid() {return Xop_tkn_itm_.Tid_uniq;}
|
||||||
|
public byte[] Key() {return key;} private final byte[] key;
|
||||||
|
}
|
@ -18,7 +18,8 @@ import gplx.core.primitives.*; import gplx.core.btries.*; import gplx.xowa.parse
|
|||||||
public class Xop_xatr_whitelist_mgr {
|
public class Xop_xatr_whitelist_mgr {
|
||||||
private final Hash_adp_bry grp_hash = Hash_adp_bry.cs();
|
private final Hash_adp_bry grp_hash = Hash_adp_bry.cs();
|
||||||
private final Btrie_rv trv = new Btrie_rv();
|
private final Btrie_rv trv = new Btrie_rv();
|
||||||
public boolean Chk(int tag_id, byte[] src, Mwh_atr_itm xatr) {
|
public boolean Chk(int tag_id, Mwh_atr_itm xatr) {
|
||||||
|
byte[] src = xatr.Src();
|
||||||
byte[] key_bry = xatr.Key_bry();
|
byte[] key_bry = xatr.Key_bry();
|
||||||
byte[] chk_bry; int chk_bgn, chk_end;
|
byte[] chk_bry; int chk_bgn, chk_end;
|
||||||
if (key_bry == null) {
|
if (key_bry == null) {
|
||||||
|
@ -16,7 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||||
import org.junit.*; import gplx.xowa.parsers.htmls.*;
|
import org.junit.*; import gplx.xowa.parsers.htmls.*;
|
||||||
public class Xop_xatr_whitelist_mgr_tst {
|
public class Xop_xatr_whitelist_mgr_tst {
|
||||||
private final Xop_xatr_whitelist_fxt fxt = new Xop_xatr_whitelist_fxt();
|
private final Xop_xatr_whitelist_fxt fxt = new Xop_xatr_whitelist_fxt();
|
||||||
@Before public void init() {fxt.Clear();}
|
@Before public void init() {fxt.Clear();}
|
||||||
@Test public void Basic() {
|
@Test public void Basic() {
|
||||||
fxt.Whitelist(Xop_xnde_tag_.Tid__div , "style" , true);
|
fxt.Whitelist(Xop_xnde_tag_.Tid__div , "style" , true);
|
||||||
@ -45,29 +45,29 @@ public class Xop_xatr_whitelist_mgr_tst {
|
|||||||
}
|
}
|
||||||
class Xop_xatr_whitelist_fxt {
|
class Xop_xatr_whitelist_fxt {
|
||||||
private Xop_xatr_whitelist_mgr whitelist_mgr;
|
private Xop_xatr_whitelist_mgr whitelist_mgr;
|
||||||
private Mwh_atr_itm atr_itm = new Mwh_atr_itm(null, false, false, false, -1, -1, -1, -1, null, -1, -1, null, -1, 0);
|
|
||||||
public void Clear() {
|
public void Clear() {
|
||||||
if (whitelist_mgr == null) whitelist_mgr = new Xop_xatr_whitelist_mgr().Ini();
|
if (whitelist_mgr == null) whitelist_mgr = new Xop_xatr_whitelist_mgr().Ini();
|
||||||
}
|
}
|
||||||
public void Whitelist(int tag_id, String key_str, boolean expd) {
|
public void Whitelist(int tag_id, String key_str, boolean expd) {
|
||||||
byte[] key_bry = Bry_.new_a7(key_str);
|
Mwh_atr_itm atr_itm = New_atr_itm(key_str, null);
|
||||||
// atr_itm.Key_rng_(0, key_bry.length);
|
Tfds.Eq(expd, whitelist_mgr.Chk(tag_id, atr_itm), key_str);
|
||||||
atr_itm.Key_bry_(key_bry);
|
|
||||||
Tfds.Eq(expd, whitelist_mgr.Chk(tag_id, key_bry, atr_itm), key_str);
|
|
||||||
}
|
}
|
||||||
public void Whitelist(int tag_id, String key_str, String val_str, boolean expd) {
|
public void Whitelist(int tag_id, String key_str, String val_str, boolean expd) {
|
||||||
byte[] key_bry = Bry_.new_a7(key_str);
|
Mwh_atr_itm atr_itm = New_atr_itm(key_str, val_str);
|
||||||
// atr_itm.Key_rng_(0, key_bry.length);
|
Tfds.Eq(expd, whitelist_mgr.Chk(tag_id, atr_itm), key_str);
|
||||||
atr_itm.Key_bry_(key_bry);
|
|
||||||
atr_itm.Val_bry_(Bry_.new_a7(val_str));
|
|
||||||
Tfds.Eq(expd, whitelist_mgr.Chk(tag_id, key_bry, atr_itm), key_str);
|
|
||||||
}
|
}
|
||||||
public void Scrub_style_pass(String style_val_str) {Scrub_style(style_val_str, style_val_str);}
|
public void Scrub_style_pass(String style_val_str) {Scrub_style(style_val_str, style_val_str);}
|
||||||
public void Scrub_style_fail(String val_str) {Scrub_style(val_str, "");}
|
public void Scrub_style_fail(String val_str) {Scrub_style(val_str, "");}
|
||||||
public void Scrub_style(String val_str, String expd) {
|
public void Scrub_style(String val_str, String expd) {
|
||||||
byte[] val_bry = Bry_.new_a7(val_str);
|
byte[] val_bry = Bry_.new_a7(val_str);
|
||||||
atr_itm.Val_bry_(val_bry);
|
Mwh_atr_itm atr_itm = New_atr_itm(null, val_str);
|
||||||
whitelist_mgr.Scrub_style(atr_itm, val_bry);
|
whitelist_mgr.Scrub_style(atr_itm, val_bry);
|
||||||
Tfds.Eq(expd, String_.new_a7(atr_itm.Val_bry()));
|
Tfds.Eq(expd, String_.new_a7(atr_itm.Val_bry()));
|
||||||
}
|
}
|
||||||
|
private static Mwh_atr_itm New_atr_itm(String key_str, String val_str) {
|
||||||
|
byte[] key_bry = key_str == null ? null : Bry_.new_u8(key_str);
|
||||||
|
byte[] val_bry = val_str == null ? null : Bry_.new_u8(val_str);
|
||||||
|
Mwh_atr_itm rv = new Mwh_atr_itm(key_bry, false, false, false, -1, -1, -1, -1, key_bry, -1, -1, val_bry, -1, 0);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ public class Xop_xnde_tkn extends Xop_tkn_itm_base implements Xop_tblw_tkn {
|
|||||||
// UNIQ; DATE:2017-03-31
|
// UNIQ; DATE:2017-03-31
|
||||||
if (is_tmpl_mode) {
|
if (is_tmpl_mode) {
|
||||||
byte[] val = cur_bfr.To_bry_and_clear();
|
byte[] val = cur_bfr.To_bry_and_clear();
|
||||||
byte[] key = ctx.Wiki().Parser_mgr().Uniq_mgr().Add(tag.Name_bry(), val);
|
byte[] key = ctx.Wiki().Parser_mgr().Uniq_mgr().Add(Bool_.Y, tag.Name_bry(), val);
|
||||||
bfr.Add(key);
|
bfr.Add(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,6 +302,13 @@ public class Xop_xnde_wkr implements Xop_ctx_wkr {
|
|||||||
}
|
}
|
||||||
Mwh_atr_itm[] atrs = null;
|
Mwh_atr_itm[] atrs = null;
|
||||||
if (ctx.Parse_tid() == Xop_parser_tid_.Tid__wtxt) {
|
if (ctx.Parse_tid() == Xop_parser_tid_.Tid__wtxt) {
|
||||||
|
// NOWIKI;DATE:2018-01-16
|
||||||
|
// if (atrs_bgn < atrs_end) {
|
||||||
|
// byte[] converted = ctx.Wiki().Parser_mgr().Uniq_mgr().Parse(Bool_.N, Bry_.Mid(src, atrs_bgn, atrs_end));
|
||||||
|
// atrs = ctx.App().Parser_mgr().Xnde__parse_atrs(converted, 0, converted.length);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// atrs = ctx.App().Parser_mgr().Xnde__parse_atrs(src, atrs_bgn, atrs_end);
|
||||||
atrs = ctx.App().Parser_mgr().Xnde__parse_atrs(src, atrs_bgn, atrs_end);
|
atrs = ctx.App().Parser_mgr().Xnde__parse_atrs(src, atrs_bgn, atrs_end);
|
||||||
}
|
}
|
||||||
if (( ( tag.Xtn()
|
if (( ( tag.Xtn()
|
||||||
|
@ -16,7 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
public class Xop_xnde_wkr__nowiki_tst {
|
public class Xop_xnde_wkr__nowiki_tst {
|
||||||
private final Xop_fxt fxt = new Xop_fxt();
|
private final Xop_fxt fxt = new Xop_fxt();
|
||||||
@After public void term() {fxt.Init_para_n_();}
|
@After public void term() {fxt.Init_para_n_();}
|
||||||
@Test public void Basic() {
|
@Test public void Basic() {
|
||||||
fxt.Test_parse_page_wiki_str
|
fxt.Test_parse_page_wiki_str
|
||||||
|
@ -175,7 +175,7 @@ public class Gallery_mgr_wtr {
|
|||||||
int len = xatr_list.Count();
|
int len = xatr_list.Count();
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
Mwh_atr_itm xatr = (Mwh_atr_itm)xatr_list.Get_at(i);
|
Mwh_atr_itm xatr = (Mwh_atr_itm)xatr_list.Get_at(i);
|
||||||
if (!whitelist_mgr.Chk(Xop_xnde_tag_.Tid__ul, src, xatr)) continue;
|
if (!whitelist_mgr.Chk(Xop_xnde_tag_.Tid__ul, xatr)) continue;
|
||||||
byte[] key = xatr.Key_bry();
|
byte[] key = xatr.Key_bry();
|
||||||
byte[] val = xatr.Val_as_bry();
|
byte[] val = xatr.Val_as_bry();
|
||||||
Gfh_wtr.Write_atr_bry(bfr, key, val);
|
Gfh_wtr.Write_atr_bry(bfr, key, val);
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.xtns.jsonConfigs.scribunto; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.jsonConfigs.*;
|
||||||
|
import gplx.xowa.langs.*;
|
||||||
|
class Jscfg_localizer {
|
||||||
|
public Keyval[] Localize(Xol_lang_itm lang, byte[] page, Keyval[] root) {
|
||||||
|
if (lang == null) return root; // if no lang, return original
|
||||||
|
|
||||||
|
int len = root.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
Keyval nde = root[i];
|
||||||
|
String nde_key = nde.Key();
|
||||||
|
if (String_.Eq(nde_key, Id__root__license)) {
|
||||||
|
}
|
||||||
|
else if (String_.Eq(nde_key, Id__root__description)) {
|
||||||
|
root[i] = pickLocalizedString(lang, page, nde);
|
||||||
|
}
|
||||||
|
else if (String_.Eq(nde_key, Id__root__schema)) {
|
||||||
|
nde = Localize_schema(lang, page, nde);
|
||||||
|
}
|
||||||
|
else if (String_.Eq(nde_key, Id__root__data)) {
|
||||||
|
nde = Localize_data(lang, page, nde);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
private Keyval Localize_schema(Xol_lang_itm lang, byte[] page, Keyval schema) {
|
||||||
|
Keyval[] schemas = Cast_to_kvary_or_null(page, schema) ; if (schemas == null) return schema;
|
||||||
|
Keyval[] fields = Cast_to_kvary_or_null(page, schemas[0]); if (fields == null) return schema;
|
||||||
|
for (Keyval field : fields) {
|
||||||
|
Keyval[] atrs = (Keyval[])field.Val();
|
||||||
|
int atrs_len = atrs.length;
|
||||||
|
for (int i = 0; i < atrs_len; i++) {
|
||||||
|
Keyval atr = atrs[i];
|
||||||
|
if (String_.Eq(atr.Key(), Id__fld__title)) {
|
||||||
|
atrs[i] = pickLocalizedString(lang, page, atr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
private Keyval Localize_data(Xol_lang_itm lang, byte[] page, Keyval data) {
|
||||||
|
Keyval[] rows = Cast_to_kvary_or_null(page, data); if (rows == null) return data;
|
||||||
|
for (Keyval row : rows) {
|
||||||
|
Object[] vals = (Object[])row.Val();
|
||||||
|
int len = vals.length;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
Object val = vals[i];
|
||||||
|
if (Type_.Eq_by_obj(val, Keyval[].class)) {
|
||||||
|
Keyval val_as_kv = pickLocalizedString(lang, Int_.To_str(i), (Keyval[])val);
|
||||||
|
vals[i] = val_as_kv.Val();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
private static Keyval pickLocalizedString(Xol_lang_itm lang, byte[] page, Keyval kv) {
|
||||||
|
Keyval[] kvs = Cast_to_kvary_or_null(page, kv.Key(), kv.Val());
|
||||||
|
Keyval rv = pickLocalizedString(lang, kv.Key(), kvs);
|
||||||
|
return rv == null ? kv : rv;
|
||||||
|
}
|
||||||
|
public static Keyval pickLocalizedString(Xol_lang_itm lang, String key, Keyval[] ary) {
|
||||||
|
// local vars for conditional logic
|
||||||
|
Object val_lang = null, val_en = null, val_1st = null;
|
||||||
|
Object[] val_fallbacks = null;
|
||||||
|
|
||||||
|
// local vars for lang
|
||||||
|
String langCode = lang.Key_str();
|
||||||
|
Ordered_hash fallback_hash = lang.Fallback_hash();
|
||||||
|
|
||||||
|
// loop ary to populate local vars
|
||||||
|
for (Keyval itm : ary) {
|
||||||
|
String itm_key = itm.Key();
|
||||||
|
Object itm_val = itm.Val();
|
||||||
|
if (val_1st == null) {
|
||||||
|
val_1st = itm_val;
|
||||||
|
}
|
||||||
|
if (String_.Eq(itm_key, langCode)) {
|
||||||
|
val_lang = itm_val;
|
||||||
|
}
|
||||||
|
else if (fallback_hash.Has(itm_key)) {
|
||||||
|
if (val_fallbacks == null) {
|
||||||
|
val_fallbacks = new Object[fallback_hash.Len()];
|
||||||
|
}
|
||||||
|
int idx = fallback_hash.Idx_of(itm_key);
|
||||||
|
val_fallbacks[idx] = itm_val;
|
||||||
|
}
|
||||||
|
else if (String_.Eq(itm_key, "en")) {
|
||||||
|
val_en = itm_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val_lang != null) {
|
||||||
|
return Keyval_.new_(key, val_lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val_fallbacks != null) {
|
||||||
|
for (Object v : val_fallbacks) {
|
||||||
|
if (v != null)
|
||||||
|
return Keyval_.new_(key, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If fallbacks fail, check if english is defined
|
||||||
|
if (val_en != null) {
|
||||||
|
return Keyval_.new_(key, val_en);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a custom default, return that
|
||||||
|
// if (defaultValue != null) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Return first available value, or an empty String
|
||||||
|
// There might be a better way to get the first value from an Object
|
||||||
|
Object val = val_1st == null ? "" : val_1st;
|
||||||
|
return Keyval_.new_(key, val);
|
||||||
|
}
|
||||||
|
private static Keyval[] Cast_to_kvary_or_null(byte[] page, Keyval kv) {return Cast_to_kvary_or_null(page, kv.Key(), kv.Val());}
|
||||||
|
private static Keyval[] Cast_to_kvary_or_null(byte[] page, String key, Object val) {
|
||||||
|
if (Type_.Eq_by_obj(val, Keyval[].class)) {
|
||||||
|
return (Keyval[])val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Gfo_usr_dlg_.Instance.Warn_many("", "", "could not cast to kvary; page=~{0} key=~{1}", key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static final String
|
||||||
|
Id__root__schema = "schema"
|
||||||
|
, Id__root__data = "data"
|
||||||
|
, Id__root__description = "description"
|
||||||
|
, Id__root__license = "license"
|
||||||
|
, Id__fld__title = "title"
|
||||||
|
;
|
||||||
|
}
|
@ -18,6 +18,7 @@ import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.scribunto.libs.*; impor
|
|||||||
import gplx.xowa.wikis.domains.*;
|
import gplx.xowa.wikis.domains.*;
|
||||||
public class Jscfg_scrib_lib implements Scrib_lib {
|
public class Jscfg_scrib_lib implements Scrib_lib {
|
||||||
private final Scrib_lib_text__json_util json_util = new Scrib_lib_text__json_util();
|
private final Scrib_lib_text__json_util json_util = new Scrib_lib_text__json_util();
|
||||||
|
private final Jscfg_localizer localizer = new Jscfg_localizer();
|
||||||
private Scrib_core core;
|
private Scrib_core core;
|
||||||
public Scrib_lua_mod Mod() {return mod;} private Scrib_lua_mod mod;
|
public Scrib_lua_mod Mod() {return mod;} private Scrib_lua_mod mod;
|
||||||
public Scrib_lib Init() {procs.Init_by_lib(this, Proc_names); return this;}
|
public Scrib_lib Init() {procs.Init_by_lib(this, Proc_names); return this;}
|
||||||
@ -57,6 +58,8 @@ public class Jscfg_scrib_lib implements Scrib_lib {
|
|||||||
throw Err_.new_wo_type("bad argument #1 to 'get' (not a valid title) " + String_.new_u8(ttl_bry));
|
throw Err_.new_wo_type("bad argument #1 to 'get' (not a valid title) " + String_.new_u8(ttl_bry));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scrib_lib_text.JsonDecodeStatic(args, rslt, core, json_util, page, Scrib_lib_text__json_util.Opt__force_assoc, Scrib_lib_text__json_util.Flag__none);
|
Keyval[] rv = Scrib_lib_text.JsonDecodeStatic(args, core, json_util, page, Scrib_lib_text__json_util.Opt__force_assoc, Scrib_lib_text__json_util.Flag__none);
|
||||||
|
rv = localizer.Localize(core.Wiki().Lang(), page, rv);
|
||||||
|
return rslt.Init_obj(rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,14 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
|||||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
*/
|
*/
|
||||||
package gplx.xowa.xtns.jsonConfigs.scribunto; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.jsonConfigs.*;
|
package gplx.xowa.xtns.jsonConfigs.scribunto; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.jsonConfigs.*;
|
||||||
import org.junit.*;
|
import org.junit.*; import gplx.core.tests.*;
|
||||||
import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.scribunto.libs.*;
|
import gplx.xowa.xtns.scribunto.*; import gplx.xowa.xtns.scribunto.libs.*;
|
||||||
|
import gplx.xowa.langs.*;
|
||||||
|
import gplx.langs.jsons.*;
|
||||||
public class Jscfg_scrib_lib_tst {
|
public class Jscfg_scrib_lib_tst {
|
||||||
@Before public void init() {
|
private final Jscfg_scrib_lib_fxt fxt = new Jscfg_scrib_lib_fxt();
|
||||||
fxt.Clear_for_lib();
|
|
||||||
lib = new Jscfg_scrib_lib();
|
|
||||||
lib.Init();
|
|
||||||
lib.Core_(fxt.Core());
|
|
||||||
} private Scrib_invoke_func_fxt fxt = new Scrib_invoke_func_fxt(); private Jscfg_scrib_lib lib;
|
|
||||||
@Test public void Get() {
|
@Test public void Get() {
|
||||||
Xowe_wiki commons_wiki = fxt.Parser_fxt().Wiki().Appe().Wiki_mgr().Get_by_or_make(gplx.xowa.wikis.domains.Xow_domain_itm_.Bry__commons).Init_assert();
|
fxt.Init__page("Data:Test.tab", Json_doc.Make_str_by_apos
|
||||||
fxt.Parser_fxt().Init_page_create(commons_wiki, "Data:Test.tab", gplx.langs.jsons.Json_doc.Make_str_by_apos
|
|
||||||
( "{"
|
( "{"
|
||||||
, " 'data':"
|
, " 'data':"
|
||||||
, " ["
|
, " ["
|
||||||
@ -41,7 +37,7 @@ public class Jscfg_scrib_lib_tst {
|
|||||||
, " ]"
|
, " ]"
|
||||||
, "}"
|
, "}"
|
||||||
));
|
));
|
||||||
fxt.Test_scrib_proc_str_ary(lib, Jscfg_scrib_lib.Invk_get, Keyval_.Ary(Keyval_.int_(1, "Test.tab")), String_.Concat_lines_nl_skip_last
|
fxt.Test__get("Test.tab", String_.Concat_lines_nl_skip_last
|
||||||
( "1="
|
( "1="
|
||||||
, " data="
|
, " data="
|
||||||
, " 1="
|
, " 1="
|
||||||
@ -52,4 +48,126 @@ public class Jscfg_scrib_lib_tst {
|
|||||||
, " 2=Data:Q2"
|
, " 2=Data:Q2"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@Test public void Get_localize() {
|
||||||
|
fxt.Init__page("Data:Test_localize.tab", Json_doc.Make_str_by_apos
|
||||||
|
( "{"
|
||||||
|
, " 'license': 'CC0-1.0',"
|
||||||
|
, " 'description': {"
|
||||||
|
, " 'de': 'Objekttabelle',"
|
||||||
|
, " 'en': 'Object table'"
|
||||||
|
, " },"
|
||||||
|
, " 'sources': 'Objects in Data:Data.tab completed by [https://www.wikidata.org Wikidata]',"
|
||||||
|
, " 'schema': {"
|
||||||
|
, " 'fields': ["
|
||||||
|
, " {"
|
||||||
|
, " 'name': 'wikidataID',"
|
||||||
|
, " 'type': 'String',"
|
||||||
|
, " 'title': {"
|
||||||
|
, " 'de': 'Wikidata-Item',"
|
||||||
|
, " 'en': 'Wikidata item'"
|
||||||
|
, " }"
|
||||||
|
, " },"
|
||||||
|
, " {"
|
||||||
|
, " 'name': 'wikidataLabel',"
|
||||||
|
, " 'type': 'localized',"
|
||||||
|
, " 'title': {"
|
||||||
|
, " 'de': 'Wikidata-Label',"
|
||||||
|
, " 'en': 'Wikidata label'"
|
||||||
|
, " }"
|
||||||
|
, " }"
|
||||||
|
, " ]"
|
||||||
|
, " },"
|
||||||
|
, " 'data': ["
|
||||||
|
, " ["
|
||||||
|
, " 'Q183',"
|
||||||
|
, " {"
|
||||||
|
, " 'de': 'Deutschland',"
|
||||||
|
, " 'en': 'Germany'"
|
||||||
|
, " }"
|
||||||
|
, " ],"
|
||||||
|
, " ["
|
||||||
|
, " 'Q61912',"
|
||||||
|
, " {"
|
||||||
|
, " 'de': 'Wertheim',"
|
||||||
|
, " 'en': 'Wertheim am Main'"
|
||||||
|
, " }"
|
||||||
|
, " ]"
|
||||||
|
, " ]"
|
||||||
|
, "}"
|
||||||
|
));
|
||||||
|
fxt.Test__get( "Test_localize.tab", String_.Concat_lines_nl_skip_last
|
||||||
|
( "1="
|
||||||
|
, " license=CC0-1.0"
|
||||||
|
, " description=Object table"
|
||||||
|
, " sources=Objects in Data:Data.tab completed by [https://www.wikidata.org Wikidata]"
|
||||||
|
, " schema="
|
||||||
|
, " fields="
|
||||||
|
, " 1="
|
||||||
|
, " name=wikidataID"
|
||||||
|
, " type=String"
|
||||||
|
, " title=Wikidata item"
|
||||||
|
, " 2="
|
||||||
|
, " name=wikidataLabel"
|
||||||
|
, " type=localized"
|
||||||
|
, " title=Wikidata label"
|
||||||
|
, " data="
|
||||||
|
, " 1="
|
||||||
|
, " 1=Q183"
|
||||||
|
, " 2=Germany"
|
||||||
|
, " 2="
|
||||||
|
, " 1=Q61912"
|
||||||
|
, " 2=Wertheim am Main"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
@Test public void pickLocalizedString() {
|
||||||
|
Xol_lang_itm lang = fxt.Init__lang("zh-cn", "zh1,zh0");
|
||||||
|
|
||||||
|
// match key
|
||||||
|
fxt.Test__pickLocalizedString(lang, fxt.Init__picklocalizedStringKvs("fr", "zh-cn"), "zh-cn");
|
||||||
|
|
||||||
|
// match fallback; note that zh1 is higher in fallback list, but lower in kvs
|
||||||
|
fxt.Test__pickLocalizedString(lang, fxt.Init__picklocalizedStringKvs("zh0", "zh1"), "zh1");
|
||||||
|
|
||||||
|
// match en if no key or fallbacks
|
||||||
|
fxt.Test__pickLocalizedString(lang, fxt.Init__picklocalizedStringKvs("fr", "en"), "en");
|
||||||
|
|
||||||
|
// pick 1st if no match
|
||||||
|
fxt.Test__pickLocalizedString(lang, fxt.Init__picklocalizedStringKvs("fr", "de"), "fr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Jscfg_scrib_lib_fxt {
|
||||||
|
private final Scrib_invoke_func_fxt fxt = new Scrib_invoke_func_fxt();
|
||||||
|
private final Jscfg_scrib_lib lib;
|
||||||
|
private final Xowe_wiki commons_wiki;
|
||||||
|
public Jscfg_scrib_lib_fxt() {
|
||||||
|
fxt.Clear_for_lib();
|
||||||
|
lib = new Jscfg_scrib_lib();
|
||||||
|
lib.Init();
|
||||||
|
lib.Core_(fxt.Core());
|
||||||
|
this.commons_wiki = fxt.Parser_fxt().Wiki().Appe().Wiki_mgr().Get_by_or_make(gplx.xowa.wikis.domains.Xow_domain_itm_.Bry__commons).Init_assert();
|
||||||
|
}
|
||||||
|
public void Init__page(String page, String text) {
|
||||||
|
fxt.Parser_fxt().Init_page_create(commons_wiki, page, text);
|
||||||
|
}
|
||||||
|
public Xol_lang_itm Init__lang(String key, String fallbacks) {
|
||||||
|
Xol_lang_itm lang = new Xol_lang_itm(fxt.Core().App().Lang_mgr(), Bry_.new_u8(key));
|
||||||
|
lang.Fallback_bry_(Bry_.new_a7(fallbacks));
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
public Keyval[] Init__picklocalizedStringKvs(String... vals) {
|
||||||
|
int len = vals.length;
|
||||||
|
Keyval[] rv = new Keyval[len];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
String val = vals[i];
|
||||||
|
rv[i] = Keyval_.new_(val, val);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
public void Test__get(String page, String expd) {
|
||||||
|
fxt.Test_scrib_proc_str_ary(lib, Jscfg_scrib_lib.Invk_get, Keyval_.Ary(Keyval_.int_(1, page)), expd);
|
||||||
|
}
|
||||||
|
public void Test__pickLocalizedString(Xol_lang_itm lang, Keyval[] kv_ary, String expd) {
|
||||||
|
Keyval actl_kv = Jscfg_localizer.pickLocalizedString(lang, "key", kv_ary);
|
||||||
|
Gftest.Eq__obj_or_null(expd, actl_kv.Val());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,23 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
*/
|
*/
|
||||||
package gplx.xowa.xtns.jsonConfigs.scribunto; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.jsonConfigs.*;
|
package gplx.xowa.xtns.jsonConfigs.scribunto; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.jsonConfigs.*;
|
||||||
import gplx.xowa.xtns.scribunto.*;
|
import gplx.xowa.xtns.scribunto.*;
|
||||||
|
import gplx.xowa.mediawiki.*;
|
||||||
public class Jscfg_xtn_mgr extends Xox_mgr_base {
|
public class Jscfg_xtn_mgr extends Xox_mgr_base {
|
||||||
@Override public byte[] Xtn_key() {return XTN_KEY;} public static final byte[] XTN_KEY = Bry_.new_a7("JsonConfig");
|
@Override public byte[] Xtn_key() {return XTN_KEY;} public static final byte[] XTN_KEY = Bry_.new_a7("JsonConfig");
|
||||||
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {
|
@Override public void Xtn_init_by_wiki(Xowe_wiki wiki) {
|
||||||
Scrib_xtn_mgr scrib_xtn = (Scrib_xtn_mgr)wiki.Xtn_mgr().Get_or_fail(Scrib_xtn_mgr.XTN_KEY);
|
Scrib_xtn_mgr scrib_xtn = (Scrib_xtn_mgr)wiki.Xtn_mgr().Get_or_fail(Scrib_xtn_mgr.XTN_KEY);
|
||||||
scrib_xtn.Lib_mgr().Add(new Jscfg_scrib_lib());
|
scrib_xtn.Lib_mgr().Add(new Jscfg_scrib_lib());
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
@Override public void Xtn_ctor_by_app(Xoae_app app) {
|
||||||
|
Init_xtn();
|
||||||
|
}
|
||||||
|
public void Init_xtn() {
|
||||||
|
JCSingleton singleton = new JCSingleton();
|
||||||
|
singleton.ConfigModels().Add(JCTabularContent.Model_id, JCTabularContent.Model_id);
|
||||||
|
XophpEnv.Instance.Singletons().Add(JCSingleton.Singleton_Id, singleton);
|
||||||
|
XophpEnv.Instance.ClassBldrs().Add(JCTabularContent.Model_id, new JCTabularContentFactory());
|
||||||
|
}
|
||||||
|
*/
|
||||||
@Override public Xox_mgr Xtn_clone_new() {return new Jscfg_xtn_mgr();}
|
@Override public Xox_mgr Xtn_clone_new() {return new Jscfg_xtn_mgr();}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ class Xomath_html_wtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write html: <span>math_expr</math>
|
// write html: <span>math_expr</math>
|
||||||
byte[] unique_bry = wiki.Parser_mgr().Uniq_mgr().Add(Bry__math, math_bry);
|
byte[] unique_bry = wiki.Parser_mgr().Uniq_mgr().Add(Bool_.Y, Bry__math, math_bry);
|
||||||
Bry_fmt fmt = is_latex ? fmt__latex : fmt__mathjax;
|
Bry_fmt fmt = is_latex ? fmt__latex : fmt__mathjax;
|
||||||
fmt.Bld_many(tmp_bfr, uid, unique_bry);
|
fmt.Bld_many(tmp_bfr, uid, unique_bry);
|
||||||
bfr.Add_bfr_and_clear(tmp_bfr);
|
bfr.Add_bfr_and_clear(tmp_bfr);
|
||||||
|
@ -52,7 +52,7 @@ public class Pfunc_tag extends Pf_func_base {// REF:CoreParserFunctions.php
|
|||||||
|
|
||||||
// add to UNIQ hash; DATE:2017-03-31
|
// add to UNIQ hash; DATE:2017-03-31
|
||||||
byte[] val = tmp_bfr.To_bry_and_clear();
|
byte[] val = tmp_bfr.To_bry_and_clear();
|
||||||
byte[] key = ctx.Wiki().Parser_mgr().Uniq_mgr().Add(tag_name, val);
|
byte[] key = ctx.Wiki().Parser_mgr().Uniq_mgr().Add(Bool_.Y, tag_name, val);
|
||||||
bfr.Add(key);
|
bfr.Add(key);
|
||||||
}
|
}
|
||||||
finally {tmp_bfr.Mkr_rls();}
|
finally {tmp_bfr.Mkr_rls();}
|
||||||
|
@ -14,12 +14,18 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
|||||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
*/
|
*/
|
||||||
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||||
import gplx.core.bits.*;
|
import gplx.core.bits.*; import gplx.core.btries.*;
|
||||||
import gplx.xowa.langs.msgs.*;
|
import gplx.xowa.langs.msgs.*;
|
||||||
import gplx.xowa.xtns.scribunto.procs.*;
|
import gplx.xowa.xtns.scribunto.procs.*;
|
||||||
public class Scrib_lib_text implements Scrib_lib {
|
public class Scrib_lib_text implements Scrib_lib {
|
||||||
private final Scrib_lib_text__json_util json_util = new Scrib_lib_text__json_util();
|
private final Scrib_lib_text__json_util json_util = new Scrib_lib_text__json_util();
|
||||||
public Scrib_lib_text(Scrib_core core) {this.core = core;} private Scrib_core core;
|
private final Scrib_lib_text__nowiki_util nowiki_util = new Scrib_lib_text__nowiki_util();
|
||||||
|
private final Scrib_core core;
|
||||||
|
private final Btrie_slim_mgr trie;
|
||||||
|
public Scrib_lib_text(Scrib_core core) {
|
||||||
|
this.core = core;
|
||||||
|
this.trie = nowiki_util.Make_trie(gplx.xowa.parsers.xndes.Xop_xnde_tag_.Tag__nowiki.Name_bry());
|
||||||
|
}
|
||||||
public Scrib_lua_mod Mod() {return mod;} private Scrib_lua_mod mod;
|
public Scrib_lua_mod Mod() {return mod;} private Scrib_lua_mod mod;
|
||||||
public Scrib_lib Init() {procs.Init_by_lib(this, Proc_names); return this;}
|
public Scrib_lib Init() {procs.Init_by_lib(this, Proc_names); return this;}
|
||||||
public Scrib_lib Clone_lib(Scrib_core core) {return new Scrib_lib_text(core);}
|
public Scrib_lib Clone_lib(Scrib_core core) {return new Scrib_lib_text(core);}
|
||||||
@ -47,7 +53,11 @@ public class Scrib_lib_text implements Scrib_lib {
|
|||||||
, Invk_init_text_for_wiki = "init_text_for_wiki", Invk_jsonEncode = "jsonEncode", Invk_jsonDecode = "jsonDecode";
|
, Invk_init_text_for_wiki = "init_text_for_wiki", Invk_jsonEncode = "jsonEncode", Invk_jsonDecode = "jsonDecode";
|
||||||
private static final String[] Proc_names = String_.Ary(Invk_unstrip, Invk_unstripNoWiki, Invk_killMarkers, Invk_getEntityTable, Invk_init_text_for_wiki, Invk_jsonEncode, Invk_jsonDecode);
|
private static final String[] Proc_names = String_.Ary(Invk_unstrip, Invk_unstripNoWiki, Invk_killMarkers, Invk_getEntityTable, Invk_init_text_for_wiki, Invk_jsonEncode, Invk_jsonDecode);
|
||||||
public boolean Unstrip(Scrib_proc_args args, Scrib_proc_rslt rslt) {return rslt.Init_obj(args.Pull_str(0));} // NOTE: XOWA does not use MediaWiki strip markers; just return original; DATE:2015-01-20
|
public boolean Unstrip(Scrib_proc_args args, Scrib_proc_rslt rslt) {return rslt.Init_obj(args.Pull_str(0));} // NOTE: XOWA does not use MediaWiki strip markers; just return original; DATE:2015-01-20
|
||||||
public boolean UnstripNoWiki(Scrib_proc_args args, Scrib_proc_rslt rslt) {return rslt.Init_obj(args.Pull_str(0));} // NOTE: XOWA does not use MediaWiki strip markers; just return original; DATE:2015-01-20
|
public boolean UnstripNoWiki(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||||
|
// NOTE: XOWA does not use MediaWiki strip markers; just return original; DATE:2015-01-20
|
||||||
|
byte[] src = args.Pull_bry(0);
|
||||||
|
return rslt.Init_obj(nowiki_util.Strip_tag(core.Page().Url_bry_safe(), src, trie));
|
||||||
|
}
|
||||||
public boolean KillMarkers(Scrib_proc_args args, Scrib_proc_rslt rslt) {return rslt.Init_obj(args.Pull_str(0));} // NOTE: XOWA does not use MediaWiki strip markers; just return original; DATE:2015-01-20
|
public boolean KillMarkers(Scrib_proc_args args, Scrib_proc_rslt rslt) {return rslt.Init_obj(args.Pull_str(0));} // NOTE: XOWA does not use MediaWiki strip markers; just return original; DATE:2015-01-20
|
||||||
public boolean GetEntityTable(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
public boolean GetEntityTable(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||||
if (html_entities == null) html_entities = Scrib_lib_text_html_entities.new_();
|
if (html_entities == null) html_entities = Scrib_lib_text_html_entities.new_();
|
||||||
@ -108,10 +118,11 @@ public class Scrib_lib_text implements Scrib_lib {
|
|||||||
if (Bitmask_.Has_int(flags, Scrib_lib_text__json_util.Flag__try_fixing))
|
if (Bitmask_.Has_int(flags, Scrib_lib_text__json_util.Flag__try_fixing))
|
||||||
opts = Bitmask_.Add_int(opts, Scrib_lib_text__json_util.Flag__try_fixing);
|
opts = Bitmask_.Add_int(opts, Scrib_lib_text__json_util.Flag__try_fixing);
|
||||||
|
|
||||||
return JsonDecodeStatic(args, rslt, core, json_util, json, opts, flags);
|
Keyval[] rv = JsonDecodeStatic(args, core, json_util, json, opts, flags);
|
||||||
|
return rslt.Init_obj(rv);
|
||||||
}
|
}
|
||||||
public static boolean JsonDecodeStatic
|
public static Keyval[] JsonDecodeStatic
|
||||||
( Scrib_proc_args args, Scrib_proc_rslt rslt, Scrib_core core, Scrib_lib_text__json_util json_util
|
( Scrib_proc_args args, Scrib_core core, Scrib_lib_text__json_util json_util
|
||||||
, byte[] json, int opts, int flags) {
|
, byte[] json, int opts, int flags) {
|
||||||
// decode json to Object; note that Bool_.Y means ary and Bool_.N means ary
|
// decode json to Object; note that Bool_.Y means ary and Bool_.N means ary
|
||||||
byte rv_tid = json_util.Decode(core.App().Utl__json_parser(), json, opts);
|
byte rv_tid = json_util.Decode(core.App().Utl__json_parser(), json, opts);
|
||||||
@ -125,10 +136,10 @@ public class Scrib_lib_text implements Scrib_lib {
|
|||||||
json_util.Reindex_arrays(reindex_data, rv_as_kvy, false);
|
json_util.Reindex_arrays(reindex_data, rv_as_kvy, false);
|
||||||
rv_as_kvy = reindex_data.Rv_is_kvy() ? (Keyval[])reindex_data.Rv_as_kvy() : (Keyval[])reindex_data.Rv_as_ary();
|
rv_as_kvy = reindex_data.Rv_is_kvy() ? (Keyval[])reindex_data.Rv_as_kvy() : (Keyval[])reindex_data.Rv_as_ary();
|
||||||
}
|
}
|
||||||
return rslt.Init_obj(rv_as_kvy);
|
return rv_as_kvy;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return rslt.Init_obj(json_util.Decode_rslt_as_ary());
|
return json_util.Decode_rslt_as_ary();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Notify_wiki_changed() {if (notify_wiki_changed_fnc != null) core.Interpreter().CallFunction(notify_wiki_changed_fnc.Id(), Keyval_.Ary_empty);}
|
public void Notify_wiki_changed() {if (notify_wiki_changed_fnc != null) core.Interpreter().CallFunction(notify_wiki_changed_fnc.Id(), Keyval_.Ary_empty);}
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||||
|
import gplx.core.btries.*;
|
||||||
|
import gplx.core.primitives.*;
|
||||||
|
public class Scrib_lib_text__nowiki_util {
|
||||||
|
public Btrie_slim_mgr Make_trie(byte[] tag) {
|
||||||
|
Bry_bfr tmp = Bry_bfr_.New();
|
||||||
|
Btrie_slim_mgr rv = Btrie_slim_mgr.ci_u8();
|
||||||
|
byte[] lhs_bry = tmp.Add_bry_many(Byte_ascii.Angle_bgn_bry, tag, Byte_ascii.Angle_end_bry).To_bry_and_clear();
|
||||||
|
byte[] rhs_bry = tmp.Add_bry_many(Byte_ascii.Angle_bgn_bry, Byte_ascii.Slash_bry, tag, Byte_ascii.Angle_end_bry).To_bry_and_clear();
|
||||||
|
rv.Add_obj(lhs_bry, Bool_obj_val.True);
|
||||||
|
rv.Add_obj(rhs_bry, Bool_obj_val.False);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
public byte[] Strip_tag(byte[] page, byte[] src, Btrie_slim_mgr trie) {
|
||||||
|
Btrie_rv trv = new Btrie_rv();
|
||||||
|
Bry_bfr tmp = null;
|
||||||
|
int bgn = 0;
|
||||||
|
int end = src.length;
|
||||||
|
|
||||||
|
// main loop
|
||||||
|
boolean lhs_found = false;
|
||||||
|
int pos = bgn;
|
||||||
|
int rhs_end = pos, lhs_bgn = pos, lhs_end = pos;
|
||||||
|
while (pos < end) {
|
||||||
|
// check byte against trie
|
||||||
|
Object o = trie.Match_at_w_b0(trv, src[pos], src, pos, end);
|
||||||
|
|
||||||
|
// no match; increment and continue;
|
||||||
|
if (o == null) {
|
||||||
|
pos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// match found
|
||||||
|
Bool_obj_val tag_marker = (Bool_obj_val)o;
|
||||||
|
|
||||||
|
// match is open tag; EX: <tag>
|
||||||
|
if (tag_marker.Val()) {
|
||||||
|
// set lhs_bgn and lhs_end; note that if there are multiple open tags, it will only keep the first
|
||||||
|
if (!lhs_found) {
|
||||||
|
lhs_found = true;
|
||||||
|
lhs_bgn = pos;
|
||||||
|
lhs_end = trv.Pos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// match is close tag; EX: </tag>
|
||||||
|
else {
|
||||||
|
// only splice if open tag exists; avoids dangling rhs; EX: "a</tag>b"
|
||||||
|
if (lhs_found) {
|
||||||
|
lhs_found = false;
|
||||||
|
if (tmp == null) tmp = Bry_bfr_.New();
|
||||||
|
|
||||||
|
// add text from previous </tag> to current <tag>;
|
||||||
|
tmp.Add_mid(src, rhs_end, lhs_bgn);
|
||||||
|
|
||||||
|
// add text between <tag> and </tag>;
|
||||||
|
tmp.Add_mid(src, lhs_end, pos);
|
||||||
|
|
||||||
|
// update </tag> pos
|
||||||
|
rhs_end = trv.Pos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update pos to after match
|
||||||
|
pos = trv.Pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add remaining text to bfr
|
||||||
|
if (tmp != null) {
|
||||||
|
tmp.Add_mid(src, rhs_end, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp == null ? src : tmp.To_bry_and_clear();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||||
|
import org.junit.*; import gplx.core.tests.*;
|
||||||
|
import gplx.core.btries.*;
|
||||||
|
import gplx.xowa.parsers.xndes.*;
|
||||||
|
public class Scrib_lib_text__nowiki_util_tst {
|
||||||
|
private final Scrib_lib_text__nowiki_util_fxt fxt = new Scrib_lib_text__nowiki_util_fxt();
|
||||||
|
@Test public void Basic() {
|
||||||
|
// noop
|
||||||
|
fxt.Test__Strip_tag("abc", "abc");
|
||||||
|
|
||||||
|
// one
|
||||||
|
fxt.Test__Strip_tag("a<nowiki>b</nowiki>c", "abc");
|
||||||
|
|
||||||
|
// mixed case
|
||||||
|
fxt.Test__Strip_tag("a<NOwiki>b</noWIKI>c", "abc");
|
||||||
|
|
||||||
|
// multiple: consecutive
|
||||||
|
fxt.Test__Strip_tag("a<nowiki>b</nowiki>c<nowiki>d</nowiki>e", "abcde");
|
||||||
|
|
||||||
|
// dangling: left
|
||||||
|
fxt.Test__Strip_tag("a<nowiki>b<nowiki>c</nowiki>d", "ab<nowiki>cd");
|
||||||
|
|
||||||
|
// dangling: right
|
||||||
|
fxt.Test__Strip_tag( "a<nowiki>b</nowiki>c</nowiki>d", "abc</nowiki>d");
|
||||||
|
|
||||||
|
// nested
|
||||||
|
fxt.Test__Strip_tag("a<nowiki>b<nowiki>c</nowiki>d</nowiki>e", "ab<nowiki>cd</nowiki>e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Scrib_lib_text__nowiki_util_fxt {
|
||||||
|
private final Scrib_lib_text__nowiki_util util = new Scrib_lib_text__nowiki_util();
|
||||||
|
private final Btrie_slim_mgr trie;
|
||||||
|
public Scrib_lib_text__nowiki_util_fxt() {
|
||||||
|
this.trie = util.Make_trie(Xop_xnde_tag_.Tag__nowiki.Name_bry());
|
||||||
|
}
|
||||||
|
public void Test__Strip_tag(String src, String expd) {
|
||||||
|
byte[] actl = util.Strip_tag(Bry_.new_a7("Page"), Bry_.new_u8(src), trie);
|
||||||
|
Gftest.Eq__str(expd, actl);
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,9 @@ public class Scrib_lib_text_tst {
|
|||||||
@Test public void Unstrip() {
|
@Test public void Unstrip() {
|
||||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_text.Invk_unstrip, Object_.Ary("a"), "a");
|
fxt.Test_scrib_proc_str(lib, Scrib_lib_text.Invk_unstrip, Object_.Ary("a"), "a");
|
||||||
}
|
}
|
||||||
|
@Test public void UnstripNoWiki() {
|
||||||
|
fxt.Test_scrib_proc_str(lib, Scrib_lib_text.Invk_unstripNoWiki, Object_.Ary("a<nowiki>b</nowiki>c"), "abc");
|
||||||
|
}
|
||||||
@Test public void GetEntityTable() {
|
@Test public void GetEntityTable() {
|
||||||
Keyval[] actl = fxt.Test_scrib_proc_rv_as_kv_ary(lib, Scrib_lib_text.Invk_getEntityTable, Object_.Ary());
|
Keyval[] actl = fxt.Test_scrib_proc_rv_as_kv_ary(lib, Scrib_lib_text.Invk_getEntityTable, Object_.Ary());
|
||||||
Tfds.Eq(1510, actl.length); // large result; only test # of entries
|
Tfds.Eq(1510, actl.length); // large result; only test # of entries
|
||||||
|
@ -15,31 +15,10 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
*/
|
*/
|
||||||
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
public class XophpArray {
|
public class XophpArray {
|
||||||
public static boolean popBoolOrN(List_adp list) {return Bool_.Cast(List_adp_.Pop_or(list, false));}
|
public static boolean in_array(String needle, String[] haystack) {
|
||||||
public static byte[] popBryOrNull(List_adp list) {return (byte[])List_adp_.Pop_or(list, null);}
|
for (String hay : haystack)
|
||||||
public static String[] array_keys_str(Ordered_hash array) {
|
if (String_.Eq(hay, needle))
|
||||||
int len = array.Len();
|
return true;
|
||||||
String[] rv = new String[len];
|
return false;
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
rv[i] = (String)array.Get_at(i);
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
public static byte[][] array_keys_bry(Ordered_hash array) {
|
|
||||||
int len = array.Len();
|
|
||||||
byte[][] rv = new byte[len][];
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
rv[i] = (byte[])array.Get_at(i);
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
public static boolean array_key_exists(int key, Ordered_hash array) {return array.Has(key);}
|
|
||||||
public static boolean array_key_exists(String key, Ordered_hash array) {return array.Has(key);}
|
|
||||||
public static boolean array_key_exists(byte[] key, Ordered_hash array) {return array.Has(key);}
|
|
||||||
public static boolean array_is_empty(Ordered_hash array) {
|
|
||||||
return array.Len() == 0;
|
|
||||||
}
|
|
||||||
public static void unset(Ordered_hash array, Object key) {
|
|
||||||
array.Del(key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
public class XophpArrayUtl {
|
||||||
|
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);}
|
||||||
|
public static String[] array_keys_str(Ordered_hash array) {
|
||||||
|
int len = array.Len();
|
||||||
|
String[] rv = new String[len];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
rv[i] = (String)array.Get_at(i);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
public static byte[][] array_keys_bry(Ordered_hash array) {
|
||||||
|
int len = array.Len();
|
||||||
|
byte[][] rv = new byte[len][];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
rv[i] = (byte[])array.Get_at(i);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
public static boolean array_key_exists(int key, Ordered_hash array) {return array.Has(key);}
|
||||||
|
public static boolean array_key_exists(String key, Ordered_hash array) {return array.Has(key);}
|
||||||
|
public static boolean array_key_exists(byte[] key, Ordered_hash array) {return array.Has(key);}
|
||||||
|
public static boolean array_is_empty(Ordered_hash array) {
|
||||||
|
return array.Len() == 0;
|
||||||
|
}
|
||||||
|
public static void unset(Ordered_hash array, Object key) {
|
||||||
|
array.Del(key);
|
||||||
|
}
|
||||||
|
public static Object[] unset_by_idx(Object[] ary, int idx) {
|
||||||
|
int ary_len = ary.length;
|
||||||
|
Object[] rv = new Object[ary_len];
|
||||||
|
for (int i = 0; i < idx; i++)
|
||||||
|
rv[i] = ary[i];
|
||||||
|
for (int i = idx + 1; i < ary_len; i++)
|
||||||
|
rv[i - 1] = ary[i];
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
public interface XophpClassBldr {
|
||||||
|
String Id();
|
||||||
|
Object Make(Object... args);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
public class XophpClassBldrs {
|
||||||
|
private final Ordered_hash hash = Ordered_hash_.New();
|
||||||
|
public void Add(String id, XophpClassBldr bldr) {
|
||||||
|
hash.Add(id, bldr);
|
||||||
|
}
|
||||||
|
public XophpClassBldr Get_by_or_null(String id) {
|
||||||
|
return (XophpClassBldr)hash.Get_by(id);
|
||||||
|
}
|
||||||
|
}
|
22
gplx.xowa.mediawiki/src/gplx/xowa/mediawiki/XophpEnv.java
Normal file
22
gplx.xowa.mediawiki/src/gplx/xowa/mediawiki/XophpEnv.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
public class XophpEnv {
|
||||||
|
public XophpClassBldrs ClassBldrs() {return classBldrs;} private final XophpClassBldrs classBldrs = new XophpClassBldrs();
|
||||||
|
public Ordered_hash Singletons() {return singletons;} private final Ordered_hash singletons = Ordered_hash_.New();
|
||||||
|
|
||||||
|
public static final XophpEnv Instance = new XophpEnv();
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
public class XophpStdClass {
|
||||||
|
private final List_adp list = List_adp_.New();
|
||||||
|
private final Ordered_hash hash = Ordered_hash_.New();
|
||||||
|
public int Len() {return list.Len();}
|
||||||
|
public boolean Has(String key) {return hash.Has(key);}
|
||||||
|
public void Add_at_as_itm(XophpStdClass itm) {
|
||||||
|
list.Add(itm);
|
||||||
|
}
|
||||||
|
public void Add_by_as_obj(String key, Object itm) {
|
||||||
|
list.Add(itm);
|
||||||
|
hash.Add(key, itm);
|
||||||
|
}
|
||||||
|
public XophpStdClass Get_at_as_itm(int idx) {return (XophpStdClass)list.Get_at(idx);}
|
||||||
|
public Object Get_by_as_obj(String key) {return hash.Get_by(key);}
|
||||||
|
public XophpStdClass Get_by_as_itm(String key) {return (XophpStdClass)hash.Get_by(key);}
|
||||||
|
public String Get_by_as_str(String key) {return (String)hash.Get_by(key);}
|
||||||
|
public String Get_at_as_str(int idx) {return (String)list.Get_at(idx);}
|
||||||
|
public XophpStdClass Get_by_ary_as_itm(String... keys) {
|
||||||
|
return (XophpStdClass)Get_by_ary_or_null(false, keys, keys.length - 1, 0);
|
||||||
|
}
|
||||||
|
public boolean Comp_str(String key, String expd) {
|
||||||
|
String actl = Get_by_as_str(key);
|
||||||
|
return String_.Eq(expd, actl);
|
||||||
|
}
|
||||||
|
public void Set_by_as_itm(String key, XophpStdClass itm) {
|
||||||
|
hash.Add_if_dupe_use_nth(key, itm);
|
||||||
|
}
|
||||||
|
public void Set_by_as_itm(String[] keys, XophpStdClass rv) {
|
||||||
|
int keys_last_idx = keys.length - 1;
|
||||||
|
XophpStdClass itm = (XophpStdClass)Get_by_ary_or_null(true, keys, keys_last_idx - 1, 0);
|
||||||
|
itm.Set_by_as_itm(keys[keys_last_idx], rv);
|
||||||
|
}
|
||||||
|
public void Set_by_as_str(String key, String val) {
|
||||||
|
hash.Add_if_dupe_use_nth(key, val);
|
||||||
|
}
|
||||||
|
public void Set_at_as_str(int idx, String val) {
|
||||||
|
list.Del_at(idx);
|
||||||
|
list.Add_at(idx, val);
|
||||||
|
}
|
||||||
|
public void Del_by(String key) {
|
||||||
|
Object itm = hash.Get_by(key);
|
||||||
|
hash.Del(key);
|
||||||
|
list.Del(itm);
|
||||||
|
}
|
||||||
|
private Object Get_by_ary_or_null(boolean create, String[] keys, int keys_idx_last, int keys_idx) {
|
||||||
|
if (keys_idx == keys_idx_last) {
|
||||||
|
return hash.Get_by(keys[keys_idx_last]);
|
||||||
|
}
|
||||||
|
|
||||||
|
String key = keys[keys_idx];
|
||||||
|
XophpStdClass itm = Get_by_as_itm(key);
|
||||||
|
if (itm == null) {
|
||||||
|
// set
|
||||||
|
if (create) {
|
||||||
|
itm = new XophpStdClass();
|
||||||
|
Set_by_as_itm(key, itm);
|
||||||
|
}
|
||||||
|
// get
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itm.Get_by_ary_or_null(create, keys, keys_idx_last, keys_idx + 1);
|
||||||
|
}
|
||||||
|
}
|
90
gplx.xowa.mediawiki/src/gplx/xowa/mediawiki/Xophp_ary.java
Normal file
90
gplx.xowa.mediawiki/src/gplx/xowa/mediawiki/Xophp_ary.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
import gplx.core.brys.*;
|
||||||
|
public class Xophp_ary implements Bry_bfr_able {
|
||||||
|
private final Ordered_hash hash = Ordered_hash_.New();
|
||||||
|
private int nxt_idx;
|
||||||
|
public Xophp_ary Add(Object val) {
|
||||||
|
int key = nxt_idx++;
|
||||||
|
Xophp_ary_itm itm = Xophp_ary_itm.New(key, val);
|
||||||
|
hash.Add_if_dupe_use_nth(key, itm);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Xophp_ary Add(int key, Object val) {
|
||||||
|
nxt_idx = key + 1;
|
||||||
|
Xophp_ary_itm itm = Xophp_ary_itm.New(key, val);
|
||||||
|
hash.Add_if_dupe_use_nth(key, itm);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Xophp_ary Add(double key, Object val) {
|
||||||
|
int key_as_int = (int)key;
|
||||||
|
nxt_idx = key_as_int + 1;
|
||||||
|
Xophp_ary_itm itm = Xophp_ary_itm.New(key_as_int, val);
|
||||||
|
hash.Add_if_dupe_use_nth(key_as_int, itm);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Xophp_ary Add(boolean key, Object val) {
|
||||||
|
int key_as_int = key ? 1 : 0;
|
||||||
|
nxt_idx = key_as_int + 1;
|
||||||
|
Xophp_ary_itm itm = Xophp_ary_itm.New(key_as_int, val);
|
||||||
|
hash.Add_if_dupe_use_nth(key_as_int, itm);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Xophp_ary Add(String key, Object val) {
|
||||||
|
Xophp_ary_itm itm = null;
|
||||||
|
int key_as_int = Int_.Parse_or(key, Int_.Min_value);
|
||||||
|
if (key_as_int != Int_.Min_value) {
|
||||||
|
itm = Xophp_ary_itm.New(key_as_int, val);
|
||||||
|
nxt_idx = key_as_int + 1;
|
||||||
|
hash.Add_if_dupe_use_nth(key_as_int, itm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
itm = Xophp_ary_itm.New(key, val);
|
||||||
|
hash.Add_if_dupe_use_nth(key, itm);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Object Get(Object key) {
|
||||||
|
Xophp_ary_itm itm = (Xophp_ary_itm)hash.Get_by(key);
|
||||||
|
return itm.Val();
|
||||||
|
}
|
||||||
|
public void Unset(Object key) {
|
||||||
|
hash.Del(key);
|
||||||
|
}
|
||||||
|
public boolean Has(Object key) {
|
||||||
|
return hash.Has(key);
|
||||||
|
}
|
||||||
|
public Xophp_ary Values() {
|
||||||
|
Xophp_ary rv = new Xophp_ary();
|
||||||
|
int len = hash.Len();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
Xophp_ary_itm old_itm = (Xophp_ary_itm)hash.Get_at(i);
|
||||||
|
rv.Add(i, old_itm.Val());
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
public Xophp_ary_itm[] To_ary() {
|
||||||
|
return (Xophp_ary_itm[])hash.To_ary(Xophp_ary_itm.class);
|
||||||
|
}
|
||||||
|
public void To_bfr(Bry_bfr bfr) {
|
||||||
|
Xophp_ary_itm[] itms = To_ary();
|
||||||
|
for (Xophp_ary_itm itm : itms) {
|
||||||
|
itm.To_bfr(bfr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static Xophp_ary New() {return new Xophp_ary();}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
import gplx.core.brys.*;
|
||||||
|
public class Xophp_ary_itm implements Bry_bfr_able {
|
||||||
|
public Xophp_ary_itm(int key_as_int, String key_as_str, Object val) {
|
||||||
|
this.key_as_int = key_as_int;
|
||||||
|
this.key_as_str = key_as_str;
|
||||||
|
this.val = val;
|
||||||
|
}
|
||||||
|
public int Key_as_int() {return key_as_int;} private final int key_as_int;
|
||||||
|
public String Key_as_str() {return key_as_str;} private final String key_as_str;
|
||||||
|
public Object Val() {return val;} private final Object val;
|
||||||
|
public void To_bfr(Bry_bfr bfr) {
|
||||||
|
String key = key_as_str == null ? Int_.To_str(key_as_int) : key_as_str;
|
||||||
|
bfr.Add_str_u8(key).Add_byte_eq();
|
||||||
|
|
||||||
|
if (Type_.Type_by_obj(val) == Xophp_ary.class) {
|
||||||
|
Xophp_ary sub_ary = (Xophp_ary)val;
|
||||||
|
bfr.Add_byte_nl();
|
||||||
|
sub_ary.To_bfr(bfr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bfr.Add_obj(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Xophp_ary_itm New(int key, Object val) {return new Xophp_ary_itm(key, null, val);}
|
||||||
|
public static Xophp_ary_itm New(String key, Object val) {return new Xophp_ary_itm(-1 , key , val);}
|
||||||
|
}
|
137
gplx.xowa.mediawiki/src/gplx/xowa/mediawiki/Xophp_ary_tst.java
Normal file
137
gplx.xowa.mediawiki/src/gplx/xowa/mediawiki/Xophp_ary_tst.java
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
|
import org.junit.*; import gplx.core.tests.*;
|
||||||
|
public class Xophp_ary_tst { // REF: http://php.net/manual/en/language.types.array.php
|
||||||
|
private final XophpArray_fxt fxt = new XophpArray_fxt();
|
||||||
|
@Test public void array__kvs() {
|
||||||
|
// $array = array("foo" => "bar", "bar" => "foo",);
|
||||||
|
fxt.Test__array
|
||||||
|
( Xophp_ary.New()
|
||||||
|
. Add("foo", "bar")
|
||||||
|
. Add("bar", "foo")
|
||||||
|
, Xophp_ary_itm.New("foo", "bar")
|
||||||
|
, Xophp_ary_itm.New("bar", "foo")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Test public void array__casting() {
|
||||||
|
// $array = array(1 => "a", "1" => "b", 1.5 => "c", true => "d",);
|
||||||
|
fxt.Test__array
|
||||||
|
( Xophp_ary.New()
|
||||||
|
. Add(1 , "a")
|
||||||
|
. Add("1" , "b")
|
||||||
|
. Add(1.5 , "c")
|
||||||
|
. Add(true, "d")
|
||||||
|
, Xophp_ary_itm.New(1, "d"));
|
||||||
|
}
|
||||||
|
@Test public void array__mixed() {
|
||||||
|
// $array = array("foo" => "bar", "bar" => "foo", 100 => -100, -100 => 100);
|
||||||
|
fxt.Test__array
|
||||||
|
( Xophp_ary.New()
|
||||||
|
. Add("foo", "bar")
|
||||||
|
. Add("bar", "foo")
|
||||||
|
. Add(100, -100)
|
||||||
|
. Add(-100, 100)
|
||||||
|
, Xophp_ary_itm.New("foo", "bar")
|
||||||
|
, Xophp_ary_itm.New("bar", "foo")
|
||||||
|
, Xophp_ary_itm.New(100, -100)
|
||||||
|
, Xophp_ary_itm.New(-100, 100)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Test public void array__objs() {
|
||||||
|
// $array = array("foo", "bar", "hello", "world");
|
||||||
|
fxt.Test__array
|
||||||
|
( Xophp_ary.New()
|
||||||
|
. Add("foo")
|
||||||
|
. Add("bar")
|
||||||
|
. Add("hello")
|
||||||
|
. Add("world")
|
||||||
|
, Xophp_ary_itm.New(0, "foo")
|
||||||
|
, Xophp_ary_itm.New(1, "bar")
|
||||||
|
, Xophp_ary_itm.New(2, "hello")
|
||||||
|
, Xophp_ary_itm.New(3, "world")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Test public void array__unkeyed() {
|
||||||
|
// $array = array("a", "b", 6 => "c", "d");
|
||||||
|
fxt.Test__array
|
||||||
|
( Xophp_ary.New()
|
||||||
|
. Add("a")
|
||||||
|
. Add("b")
|
||||||
|
. Add(6, "c")
|
||||||
|
. Add("d")
|
||||||
|
, Xophp_ary_itm.New(0, "a")
|
||||||
|
, Xophp_ary_itm.New(1, "b")
|
||||||
|
, Xophp_ary_itm.New(6, "c")
|
||||||
|
, Xophp_ary_itm.New(7, "d")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Test public void array__multidimensional() {
|
||||||
|
/*
|
||||||
|
$array = array(
|
||||||
|
"foo" => "bar",
|
||||||
|
42 => 24,
|
||||||
|
"multi" => array(
|
||||||
|
"dimensional" => array(
|
||||||
|
"array" => "foo"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
fxt.Test__array
|
||||||
|
( Xophp_ary.New()
|
||||||
|
. Add("foo" , "bar")
|
||||||
|
. Add(42 , 24)
|
||||||
|
. Add("multi" , Xophp_ary.New()
|
||||||
|
. Add("dimensional", Xophp_ary.New()
|
||||||
|
. Add("array", "foo")
|
||||||
|
))
|
||||||
|
, Xophp_ary_itm.New("foo", "bar")
|
||||||
|
, Xophp_ary_itm.New(42, "24")
|
||||||
|
, Xophp_ary_itm.New("multi", Xophp_ary.New()
|
||||||
|
. Add("dimensional", Xophp_ary.New()
|
||||||
|
. Add("array", "foo")
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Test public void array__unset() {
|
||||||
|
Xophp_ary ary = Xophp_ary.New();
|
||||||
|
ary.Add(0, "a").Add(1, "b");
|
||||||
|
|
||||||
|
// delete all
|
||||||
|
ary.Unset(0);
|
||||||
|
ary.Unset(1);
|
||||||
|
fxt.Test__array(ary);
|
||||||
|
|
||||||
|
// add new and assert idx is 2
|
||||||
|
ary.Add("c");
|
||||||
|
fxt.Test__array(ary, Xophp_ary_itm.New(2, "c"));
|
||||||
|
|
||||||
|
ary = ary.Values();
|
||||||
|
ary.Add("d");
|
||||||
|
fxt.Test__array(ary, Xophp_ary_itm.New(0, "c"), Xophp_ary_itm.New(1, "d"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class XophpArray_fxt {
|
||||||
|
public void Test__array(Xophp_ary ary, Xophp_ary_itm... expd) {
|
||||||
|
Xophp_ary_itm[] actl = ary.To_ary();
|
||||||
|
Gftest.Eq__ary(expd, actl);
|
||||||
|
}
|
||||||
|
public void Test__unset(Xophp_ary ary, int idx, Xophp_ary_itm... expd) {
|
||||||
|
Xophp_ary_itm[] actl = ary.To_ary();
|
||||||
|
Gftest.Eq__ary(expd, actl);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.content.*;
|
||||||
|
public class JCContent extends TextContent { /** @var array */
|
||||||
|
private Object rawData = null;
|
||||||
|
/** @var stdClass|array */
|
||||||
|
protected XophpStdClass data = null;
|
||||||
|
/** @var Status */
|
||||||
|
private XomwStatus status;
|
||||||
|
/** @var boolean */
|
||||||
|
private boolean thoroughVar;
|
||||||
|
/** @var JCContentView|null contains an instance of the view class */
|
||||||
|
// private Object view = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param String text Json configuration. If null, default content will be inserted instead
|
||||||
|
* @param String $modelId
|
||||||
|
* @param boolean thorough True if extra validation should be performed
|
||||||
|
*/
|
||||||
|
public void __construct(byte[] text, String modelId, boolean thorough) {
|
||||||
|
if (text == null) {
|
||||||
|
// text = this.getView($modelId).getDefault($modelId);
|
||||||
|
}
|
||||||
|
super.__construct(text, modelId);
|
||||||
|
this.thoroughVar = thorough;
|
||||||
|
this.status = new XomwStatus();
|
||||||
|
this.parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get validated data
|
||||||
|
* @return stdClass|stdClass[]
|
||||||
|
*/
|
||||||
|
public XophpStdClass getData() {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data after sanitization, suitable for third-party use
|
||||||
|
*
|
||||||
|
* @param stdClass|stdClass[] data
|
||||||
|
* @return stdClass|stdClass[]
|
||||||
|
*/
|
||||||
|
public XophpStdClass getSafeData(XophpStdClass data) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns JSON Object as resulted from parsing initial text,
|
||||||
|
* before any validation/modifications took place
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public Object getRawData() {
|
||||||
|
return this.rawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get content status Object
|
||||||
|
* @return Status
|
||||||
|
*/
|
||||||
|
public XomwStatus getStatus() {
|
||||||
|
return this.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean False if this configuration has parsing or validation errors
|
||||||
|
*/
|
||||||
|
public boolean isValid() {
|
||||||
|
return this.status.isGood();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final byte[] Bry__ary__empty = Bry_.new_a7("{}");
|
||||||
|
public boolean isEmpty() {
|
||||||
|
byte[] text = Bry_.Trim(this.getNativeData());
|
||||||
|
return Bry_.Len_eq_0(text) || Bry_.Eq(text, Bry__ary__empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether this content should be considered a "page" for statistics
|
||||||
|
* In our case, just making sure it's not empty or a redirect
|
||||||
|
* @param boolean $hasLinks
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isCountable(boolean hasLinks) {
|
||||||
|
return !this.isEmpty() && !this.isRedirect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the text is in JSON format.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isValidJson() {
|
||||||
|
return this.rawData != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean true if thorough validation may be needed -
|
||||||
|
* e.g. rendering HTML or saving new value
|
||||||
|
*/
|
||||||
|
public boolean thorough() {
|
||||||
|
return this.thoroughVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to perform additional data validation
|
||||||
|
* @param mixed data
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public XophpStdClass validate(XophpStdClass data) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform initial json parsing and validation
|
||||||
|
*/
|
||||||
|
private void parse() {
|
||||||
|
// String rawText = this.getNativeData();
|
||||||
|
// parseOpts = FormatJson::STRIP_COMMENTS + FormatJson::TRY_FIXING;
|
||||||
|
// status = FormatJson::parse(rawText, parseOpts);
|
||||||
|
// if (!status.isOK()) {
|
||||||
|
// this.status = status;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// data = status.getValue();
|
||||||
|
// // @fixme: HACK - need a deep clone of the data
|
||||||
|
// // @fixme: but doing (Object)(array)data will re-encode empty [] as {}
|
||||||
|
// // @performance: re-encoding is likely faster than stripping comments in PHP twice
|
||||||
|
//// this.rawData = FormatJson::decode(
|
||||||
|
//// FormatJson::encode(data, FormatJson::ALL_OK), true
|
||||||
|
//// );
|
||||||
|
// this.data = this.validate(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Beautifies JSON prior to save.
|
||||||
|
// * @param Title $title Title
|
||||||
|
// * @param \User $user User
|
||||||
|
// * @param \ParserOptions $popts
|
||||||
|
// * @return JCContent
|
||||||
|
// */
|
||||||
|
// public function preSaveTransform(Title $title, \User $user, \ParserOptions $popts) {
|
||||||
|
// if (!this.isValidJson()) {
|
||||||
|
// return this; // Invalid JSON - can't do anything with it
|
||||||
|
// }
|
||||||
|
// $formatted = FormatJson::encode(this.getData(), false, FormatJson::ALL_OK);
|
||||||
|
// if (this.getNativeData() !== $formatted) {
|
||||||
|
// return new static($formatted, this.getModel(), this.thorough());
|
||||||
|
// }
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function fillParserOutput(Title $title, $revId, ParserOptions $options,
|
||||||
|
// $generateHtml, ParserOutput &$output) {
|
||||||
|
// if (!$generateHtml) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// status = this.getStatus();
|
||||||
|
// if (!status.isGood()) {
|
||||||
|
// // Use user's language, and split parser cache. This should not have a big
|
||||||
|
// // impact because data namespace is rarely viewed, but viewing it localized
|
||||||
|
// // will be valuable
|
||||||
|
// $lang = $options.getUserLangObj();
|
||||||
|
// $html = status.getHTML(false, false, $lang);
|
||||||
|
// } else {
|
||||||
|
// $html = '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (status.isOK()) {
|
||||||
|
// $html .= this
|
||||||
|
// .getView(this.getModel())
|
||||||
|
// .valueToHtml(this, $title, $revId, $options, $generateHtml, $output);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $output.setText($html);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Get a view Object for this content Object
|
||||||
|
// * @param String $modelId is required here because parent ctor might not have ran yet
|
||||||
|
// * @return JCContentView
|
||||||
|
// */
|
||||||
|
// protected function getView($modelId) {
|
||||||
|
// global $wgJsonConfigModels;
|
||||||
|
// view = this.view;
|
||||||
|
// if (view === null) {
|
||||||
|
// $configModels = \ExtensionRegistry::getInstance().getAttribute('JsonConfigModels')
|
||||||
|
// + $wgJsonConfigModels;
|
||||||
|
// if (array_key_exists($modelId, $configModels)) {
|
||||||
|
// $value = $configModels[$modelId];
|
||||||
|
// if (is_array($value) && array_key_exists('view', $value)) {
|
||||||
|
// $class = $value['view'];
|
||||||
|
// view = new $class();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (view === null) {
|
||||||
|
// view = this.createDefaultView();
|
||||||
|
// }
|
||||||
|
// this.view = view;
|
||||||
|
// }
|
||||||
|
// return view;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * In case view is not associated with the model for this class, this function will instantiate
|
||||||
|
// * a default. Override may instantiate a more appropriate view
|
||||||
|
// * @return JCContentView
|
||||||
|
// */
|
||||||
|
// protected function createDefaultView() {
|
||||||
|
// return new JCDefaultContentView();
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.content.*;
|
||||||
|
class JCContentHandler extends TextContentHandler { /**
|
||||||
|
* Internal format to force pretty-printed json serialization
|
||||||
|
*/
|
||||||
|
private static final String CONTENT_FORMAT_JSON_PRETTY = "application/json+pretty";
|
||||||
|
|
||||||
|
private JCSingleton singleton;
|
||||||
|
/**
|
||||||
|
* @param String $modelId
|
||||||
|
*/
|
||||||
|
public void __construct(String modelId, JCSingleton singleton) {
|
||||||
|
super.__construct(modelId, XomwDefines.CONTENT_FORMAT_JSON, CONTENT_FORMAT_JSON_PRETTY);
|
||||||
|
this.singleton = singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Returns the content's text as-is.
|
||||||
|
// *
|
||||||
|
// * @param \Content|JCContent $content This is actually a Content Object
|
||||||
|
// * @param String|null $format
|
||||||
|
// * @return mixed
|
||||||
|
// */
|
||||||
|
// public function serializeContent(\Content $content, $format = null) {
|
||||||
|
// this.checkFormat($format);
|
||||||
|
// $status = $content->getStatus();
|
||||||
|
// if ($status->isGood()) {
|
||||||
|
// $data = $content->getData(); // There are no errors, normalize data
|
||||||
|
// } elseif ($status->isOK()) {
|
||||||
|
// $data = $content->getRawData(); // JSON is valid, but the data has errors
|
||||||
|
// } else {
|
||||||
|
// return $content->getNativeData(); // Invalid JSON - can't do anything with it
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return FormatJson::encode($data, $format === self::CONTENT_FORMAT_JSON_PRETTY,
|
||||||
|
// FormatJson::ALL_OK);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param \Content|JCContent $oldContent
|
||||||
|
// * @param \Content|JCContent $myContent
|
||||||
|
// * @param \Content|JCContent $yourContent
|
||||||
|
// * @return boolean|JCContent
|
||||||
|
// */
|
||||||
|
// public function merge3(\Content $oldContent, \Content $myContent, \Content $yourContent) {
|
||||||
|
// // Almost identical clone of the parent's merge3, except that we use pretty-printed merge,
|
||||||
|
// // thus allowing much more lenient line-based merging.
|
||||||
|
//
|
||||||
|
// this.checkModelID($oldContent->getModel());
|
||||||
|
// this.checkModelID($myContent->getModel());
|
||||||
|
// this.checkModelID($yourContent->getModel());
|
||||||
|
//
|
||||||
|
// $format = self::CONTENT_FORMAT_JSON_PRETTY;
|
||||||
|
//
|
||||||
|
// $old = this.serializeContent($oldContent, $format);
|
||||||
|
// $mine = this.serializeContent($myContent, $format);
|
||||||
|
// $yours = this.serializeContent($yourContent, $format);
|
||||||
|
//
|
||||||
|
// $ok = wfMerge($old, $mine, $yours, $result);
|
||||||
|
//
|
||||||
|
// if (!$ok) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!$result) {
|
||||||
|
// return this.makeEmptyContent();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $mergedContent = this.unserializeContent($result, $format);
|
||||||
|
//
|
||||||
|
// return $mergedContent;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns the name of the diff engine to use.
|
||||||
|
// *
|
||||||
|
// * @since 1.21
|
||||||
|
// *
|
||||||
|
// * @return String
|
||||||
|
// */
|
||||||
|
// protected function getDiffEngineClass() {
|
||||||
|
// return JCJsonDifferenceEngine::class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
/**
|
||||||
|
* Unserializes a JsonSchemaContent Object.
|
||||||
|
*
|
||||||
|
* @param String $text Serialized form of the content
|
||||||
|
* @param null|String $format The format used for serialization
|
||||||
|
* @param boolean $isSaving Perform extra validation
|
||||||
|
* @return JCContent the JsonSchemaContent Object wrapping $text
|
||||||
|
*/
|
||||||
|
public JCContent unserializeContent(byte[] text) {return unserializeContent(text, null, true);}
|
||||||
|
public JCContent unserializeContent(byte[] text, String format, boolean isSaving) {
|
||||||
|
this.checkFormat(format);
|
||||||
|
String modelId = this.getModelID();
|
||||||
|
XophpClassBldr factory = singleton.getContentClass(modelId);
|
||||||
|
return (JCContent)factory.Make(text, modelId, isSaving);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Returns the name of the associated Content class, to
|
||||||
|
// * be used when creating new objects. Override expected
|
||||||
|
// * by subclasses.
|
||||||
|
// *
|
||||||
|
// * @return String
|
||||||
|
// */
|
||||||
|
// protected function getContentClass() {
|
||||||
|
// $modelId = this.getModelID();
|
||||||
|
// return JCSingleton::getContentClass($modelId);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Creates an empty JsonSchemaContent Object.
|
||||||
|
// *
|
||||||
|
// * @return JCContent
|
||||||
|
// */
|
||||||
|
// public function makeEmptyContent() {
|
||||||
|
// // Each model could have its own default JSON value
|
||||||
|
// // null notifies that default should be used
|
||||||
|
// return this.unserializeContent(null);
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.mediawiki.*;
|
||||||
|
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
|
||||||
|
public class JCDataContent extends JCObjContent { // /**
|
||||||
|
// * Derived classes must implement this method to perform custom validation
|
||||||
|
// * using the check(...) calls
|
||||||
|
// */
|
||||||
|
// public function validateContent() {
|
||||||
|
// if (!$this.thorough()) {
|
||||||
|
// // We are not doing any modifications to the original, so no need to validate it
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $this.test('license', JCValidators::isStringLine(), self::isValidLicense());
|
||||||
|
// $this.testOptional('description', [ 'en' => '' ], JCValidators::isLocalizedString());
|
||||||
|
// $this.testOptional('sources', '', JCValidators::isString());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /** Returns a validator function to check if the value is a valid String
|
||||||
|
// * @return callable
|
||||||
|
// */
|
||||||
|
// public static function isValidLicense() {
|
||||||
|
// return function (JCValue $v, array $path) {
|
||||||
|
// global $wgJsonConfigAllowedLicenses, $wgLang;
|
||||||
|
// if (!in_array($v.getValue(), $wgJsonConfigAllowedLicenses, true)) {
|
||||||
|
// $v.error('jsonconfig-err-license', $path,
|
||||||
|
// $wgLang.commaList($wgJsonConfigAllowedLicenses));
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get data as localized for the given language
|
||||||
|
* @param Language $lang
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public XophpStdClass getLocalizedData(Xol_lang_itm lang) {
|
||||||
|
if (!this.isValid()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
XophpStdClass result = new XophpStdClass();
|
||||||
|
this.localizeData(result, lang);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve @Override any specific localizations, and add it to $result
|
||||||
|
* @param Object $result
|
||||||
|
* @param Language $lang
|
||||||
|
*/
|
||||||
|
@gplx.Virtual protected void localizeData(XophpStdClass result, Xol_lang_itm lang) {
|
||||||
|
XophpStdClass data = this.getData();
|
||||||
|
if (data.Has("description")) {
|
||||||
|
result.Set_by_as_str("description", JCUtils.pickLocalizedString(data.Get_by_as_itm("description"), lang));
|
||||||
|
}
|
||||||
|
XophpStdClass license = this.getLicenseObject();
|
||||||
|
if (license != null) {
|
||||||
|
// Xol_msg_itm msg = license.Get_by_as_obj("text");
|
||||||
|
// String text = msg.inLanguage($lang).plain();
|
||||||
|
// $result.license = (Object)[
|
||||||
|
// 'code' => $license['code'],
|
||||||
|
// 'text' => $text,
|
||||||
|
// 'url' => $license['url'].inLanguage($lang).plain(),
|
||||||
|
// ];
|
||||||
|
}
|
||||||
|
if (data.Has("sources")) {
|
||||||
|
result.Set_by_as_itm("sources", data.Get_by_as_itm("sources"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// public function renderDescription( $lang ) {
|
||||||
|
// $description = $this->getField( 'description' );
|
||||||
|
//
|
||||||
|
// if ( $description && !$description->error() ) {
|
||||||
|
// $description = JCUtils::pickLocalizedString( $description->getValue(), $lang );
|
||||||
|
// $html = Html::element( 'p', [ 'class' => 'mw-jsonconfig-description' ], $description );
|
||||||
|
// } else {
|
||||||
|
// $html = '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return $html;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Renders license HTML, including optional "or later version" clause
|
||||||
|
// * <a href="...">Creative Commons 1.0</a>, or later version
|
||||||
|
// * @return String
|
||||||
|
// */
|
||||||
|
// public function renderLicense() {
|
||||||
|
// $license = $this->getLicenseObject();
|
||||||
|
// if ( $license ) {
|
||||||
|
// $text = Html::element( 'a', [
|
||||||
|
// 'href' => $license['url']->plain()
|
||||||
|
// ], $license['text']->plain() );
|
||||||
|
//
|
||||||
|
// $text = wfMessage( 'jsonconfig-license' )->rawParams( $text )->parse();
|
||||||
|
//
|
||||||
|
// $html = Html::rawElement( 'p', [ 'class' => 'mw-jsonconfig-license' ], $text );
|
||||||
|
// } else {
|
||||||
|
// $html = '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return $html;
|
||||||
|
// }
|
||||||
|
|
||||||
|
private XophpStdClass getLicenseObject() {
|
||||||
|
// XophpStdClass license = this.getField("license");
|
||||||
|
// if ( $license && !$license->error() ) {
|
||||||
|
// $code = $license->getValue();
|
||||||
|
//
|
||||||
|
// return [
|
||||||
|
// 'code' => $code,
|
||||||
|
// 'text' => wfMessage( 'jsonconfig-license-name-' . $code ),
|
||||||
|
// 'url' => wfMessage( 'jsonconfig-license-url-' . $code ),
|
||||||
|
// ];
|
||||||
|
// }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public function renderSources( Parser $parser, Title $title, $revId, ParserOptions $options ) {
|
||||||
|
// $sources = $this->getField( 'sources' );
|
||||||
|
//
|
||||||
|
// if ( $sources && !$sources->error() ) {
|
||||||
|
// $markup = $sources->getValue();
|
||||||
|
// $html = Html::rawElement( 'p', [ 'class' => 'mw-jsonconfig-sources' ],
|
||||||
|
// $parser->parse( $markup, $title, $options, true, true, $revId )->getRawText() );
|
||||||
|
// } else {
|
||||||
|
// $html = '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return $html;
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,566 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.mediawiki.*;
|
||||||
|
public class JCObjContent extends JCContent { // /**
|
||||||
|
// * @var boolean if false, prevents multiple fields from having identical names that differ
|
||||||
|
// * only by casing
|
||||||
|
// */
|
||||||
|
// protected $isCaseSensitive = false;
|
||||||
|
//
|
||||||
|
// /** @var boolean if false, ensure the root to be an stdClass, otherwise - an array */
|
||||||
|
// protected $isRootArray = false;
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @var JCValue contains raw validation results. At first it is a parsed JSON value, with the
|
||||||
|
// * root element wrapped into JCValue. As validation progresses, all visited values become
|
||||||
|
// * wrapped with JCValue.
|
||||||
|
// */
|
||||||
|
// protected $validationData;
|
||||||
|
//
|
||||||
|
// /** @var mixed */
|
||||||
|
// protected $dataWithDefaults;
|
||||||
|
//
|
||||||
|
// /** @var boolean|null validation status - null=before, true=during, false=done */
|
||||||
|
// protected $isValidating = null;
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Override default behavior to include defaults if validation succeeded.
|
||||||
|
// *
|
||||||
|
// * @return String|boolean The raw text, or false if the conversion failed.
|
||||||
|
// */
|
||||||
|
// public function getWikitextForTransclusion() {
|
||||||
|
// if ( !$this->getStatus()->isGood() ) {
|
||||||
|
// // If validation failed, return original text
|
||||||
|
// return parent::getWikitextForTransclusion();
|
||||||
|
// }
|
||||||
|
// if ( !$this->thorough() && $this->validationData !== null ) {
|
||||||
|
// // ensure that data is sorted in the right order
|
||||||
|
// self::markUnchecked( $this->validationData );
|
||||||
|
// }
|
||||||
|
// return \FormatJson::encode( $this->getDataWithDefaults(), true, \FormatJson::ALL_OK );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// protected function createDefaultView() {
|
||||||
|
// return new JCDefaultObjContentView();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Get configuration data with custom defaults
|
||||||
|
// * @throws \Exception in case validation is not complete
|
||||||
|
// * @return mixed
|
||||||
|
// */
|
||||||
|
// public function getDataWithDefaults() {
|
||||||
|
// if ( $this->isValidating !== false ) {
|
||||||
|
// throw new Exception( 'This method may only be called after validation is complete' );
|
||||||
|
// }
|
||||||
|
// if ( $this->dataWithDefaults === null ) {
|
||||||
|
// $this->dataWithDefaults = JCUtils::sanitize( $this->validationData );
|
||||||
|
// }
|
||||||
|
// return $this->dataWithDefaults;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Get status array that recursively describes dataWithDefaults
|
||||||
|
// * @throws \Exception
|
||||||
|
// * @return JCValue
|
||||||
|
// */
|
||||||
|
// public function getValidationData() {
|
||||||
|
// if ( $this->isValidating === null ) {
|
||||||
|
// throw new Exception(
|
||||||
|
// 'This method may only be called during or after validation has started'
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return $this->validationData;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Call this function before performing data validation inside the derived validate()
|
||||||
|
// * @param array|Object $data
|
||||||
|
// * @throws \Exception
|
||||||
|
// * @return boolean if true, validation should be performed, otherwise all checks will be ignored
|
||||||
|
// */
|
||||||
|
// protected function initValidation( $data ) {
|
||||||
|
// if ( $this->isValidating !== null ) {
|
||||||
|
// throw new Exception( 'This method may only be called before validation has started' );
|
||||||
|
// }
|
||||||
|
// $this->isValidating = true;
|
||||||
|
// if ( !$this->isRootArray && !is_object( $data ) ) {
|
||||||
|
// $this->getStatus()->fatal( 'jsonconfig-err-root-Object-expected' );
|
||||||
|
// } elseif ( $this->isRootArray && !is_array( $data ) ) {
|
||||||
|
// $this->getStatus()->fatal( 'jsonconfig-err-root-array-expected' );
|
||||||
|
// } else {
|
||||||
|
// $this->validationData = new JCValue( JCValue::UNCHECKED, $data );
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Derived validate() must return the result of this function
|
||||||
|
// * @throws \Exception
|
||||||
|
// * @return array
|
||||||
|
// */
|
||||||
|
// protected function finishValidation() {
|
||||||
|
// if ( !$this->getStatus()->isGood() ) {
|
||||||
|
// return $this->getRawData(); // validation failed, do not modify
|
||||||
|
// }
|
||||||
|
// return null; // Data will be filter-cloned on demand inside self::getData()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Populate this data on-demand for efficiency
|
||||||
|
// * @return array
|
||||||
|
// */
|
||||||
|
// public function getData() {
|
||||||
|
// if ( $this->data === null ) {
|
||||||
|
// $this->data = JCUtils::sanitize( $this->validationData, true );
|
||||||
|
// }
|
||||||
|
// return $this->data;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function validate( $data ) {
|
||||||
|
// if ( $this->initValidation( $data ) ) {
|
||||||
|
// $this->validateContent();
|
||||||
|
// $data = $this->finishValidation();
|
||||||
|
// }
|
||||||
|
// if ( $this->thorough() && $this->validationData !== null ) {
|
||||||
|
// self::markUnchecked( $this->validationData );
|
||||||
|
// }
|
||||||
|
// $this->isValidating = false;
|
||||||
|
// return $data;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Derived classes must implement this method to perform custom validation
|
||||||
|
// * using the test(...) calls
|
||||||
|
// */
|
||||||
|
// abstract public function validateContent();
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Use this function to test a value, or if the value is missing, use the default value.
|
||||||
|
// * The value will be tested with validator(s) if provided, even if it was the default.
|
||||||
|
// * @param String|array $path name of the root field to check, or a path to the field in a nested
|
||||||
|
// * structure. Nested path should be in the form of
|
||||||
|
// * [ 'field-level1', 'field-level2', ... ]. For example, if client needs to check
|
||||||
|
// * validity of the 'value1' in the structure {'key':{'sub-key':['value0','value1']}},
|
||||||
|
// * $field should be set to [ 'key', 'sub-key', 1 ].
|
||||||
|
// * @param mixed $default value to be used in case field is not found. $default is passed to the
|
||||||
|
// * validator if validation fails. If validation of the default passes,
|
||||||
|
// * the value is considered optional.
|
||||||
|
// * @param callable $validator callback function as defined in JCValidators::run(). More than one
|
||||||
|
// * validator may be given. If validators are not provided, any value is accepted
|
||||||
|
// * @return boolean true if ok, false otherwise
|
||||||
|
// * @throws \Exception if $this->initValidation() was not called.
|
||||||
|
// */
|
||||||
|
// public function testOptional( $path, $default, $validator = null ) {
|
||||||
|
// $vld = self::convertValidators( $validator, func_get_args(), 2 );
|
||||||
|
// // first validator will replace missing with the default
|
||||||
|
// array_unshift( $vld, JCValidators::useDefault( $default ) );
|
||||||
|
// return $this->testInt( $path, $vld );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Use this function to test a field in the data. If missing, the validator(s) will receive
|
||||||
|
// * JCMissing singleton as a value, and it will be up to the validator(s) to accept it or not.
|
||||||
|
// * @param String|array $path name of the root field to check, or a path to the field in a nested
|
||||||
|
// * structure. Nested path should be in the form of
|
||||||
|
// * [ 'field-level1', 'field-level2', ... ]. For example, if client needs to check
|
||||||
|
// * validity of the 'value1' in the structure {'key':{'sub-key':['value0','value1']}},
|
||||||
|
// * $field should be set to [ 'key', 'sub-key', 1 ].
|
||||||
|
// * @param callable $validator callback function as defined in JCValidators::run().
|
||||||
|
// * More than one validator may be given.
|
||||||
|
// * If validators are not provided, any value is accepted
|
||||||
|
// * @throws \Exception
|
||||||
|
// * @return boolean true if ok, false otherwise
|
||||||
|
// */
|
||||||
|
// public function test( $path, $validator /*...*/ ) {
|
||||||
|
// $vld = self::convertValidators( $validator, func_get_args(), 1 );
|
||||||
|
// return $this->testInt( $path, $vld );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Use this function to test all values inside an array or an Object at a given path.
|
||||||
|
// * All validators will be called for each of the sub-values. If there is no value
|
||||||
|
// * at the given $path, or it is not a container, no action will be taken and no errors reported
|
||||||
|
// * @param String|array $path path to the container field in a nested structure.
|
||||||
|
// * Nested path should be in the form of [ 'field-level1', 'field-level2', ... ].
|
||||||
|
// * For example, if client needs to check validity of the 'value1' in the structure
|
||||||
|
// * {'key':{'sub-key':['value0','value1']}},
|
||||||
|
// * $field should be set to [ 'key', 'sub-key', 1 ].
|
||||||
|
// * @param callable $validator callback function as defined in JCValidators::run().
|
||||||
|
// * More than one validator may be given.
|
||||||
|
// * If validators are not provided, any value is accepted
|
||||||
|
// * @throws \Exception
|
||||||
|
// * @return boolean true if all values tested ok, false otherwise
|
||||||
|
// */
|
||||||
|
// public function testEach( $path, $validator = null /*...*/ ) {
|
||||||
|
// $vld = self::convertValidators( $validator, func_get_args(), 1 );
|
||||||
|
// $isOk = true;
|
||||||
|
// $path = (array)$path;
|
||||||
|
// $containerField = $this->getField( $path );
|
||||||
|
// if ( $containerField ) {
|
||||||
|
// $container = $containerField->getValue();
|
||||||
|
// if ( is_array( $container ) || is_object( $container ) ) {
|
||||||
|
// $lastIdx = count( $path );
|
||||||
|
// if ( is_object( $container ) ) {
|
||||||
|
// $container = get_object_vars( $container );
|
||||||
|
// }
|
||||||
|
// foreach ( array_keys( $container ) as $k ) {
|
||||||
|
// $path[$lastIdx] = $k;
|
||||||
|
// $isOk &= $this->testInt( $path, $vld );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return $isOk;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param array|String $path
|
||||||
|
// * @param array $validators
|
||||||
|
// * @return boolean
|
||||||
|
// * @throws \Exception
|
||||||
|
// */
|
||||||
|
// private function testInt( $path, $validators ) {
|
||||||
|
// if ( !$this->getStatus()->isOK() ) {
|
||||||
|
// return false; // skip all validation in case of a fatal error
|
||||||
|
// }
|
||||||
|
// if ( $this->isValidating !== true ) {
|
||||||
|
// throw new Exception(
|
||||||
|
// 'This function should only be called inside the validateContent() override'
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return $this->testRecursive( (array)$path, [], $this->validationData, $validators );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param array $path
|
||||||
|
// * @param array $fldPath For error reporting, path to the current field
|
||||||
|
// * @param JCValue $jcv
|
||||||
|
// * @param mixed $validators
|
||||||
|
// * @throws \Exception
|
||||||
|
// * @@gplx.Internal protected param JCValue $status
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// private function testRecursive( array $path, array $fldPath, JCValue $jcv, $validators ) {
|
||||||
|
// // Go recursively through all fields in path until empty, and validate last
|
||||||
|
// if ( !$path ) {
|
||||||
|
// // keep this branch here since we allow validation of the whole Object ($path==[])
|
||||||
|
// return $this->testValue( $fldPath, $jcv, $validators );
|
||||||
|
// }
|
||||||
|
// $fld = array_shift( $path );
|
||||||
|
// if ( is_array( $jcv->getValue() ) && ctype_digit( $fld ) ) {
|
||||||
|
// $fld = (int)$fld;
|
||||||
|
// }
|
||||||
|
// if ( !is_int( $fld ) && !is_string( $fld ) ) {
|
||||||
|
// throw new Exception( 'Unexpected field type, only strings and integers are allowed' );
|
||||||
|
// }
|
||||||
|
// $fldPath[] = $fld;
|
||||||
|
//
|
||||||
|
// $subJcv = $this->getField( $fld, $jcv );
|
||||||
|
// if ( $subJcv === null ) {
|
||||||
|
// $msg =
|
||||||
|
// is_int( $fld ) && !is_array( $jcv->getValue() ) ? 'jsonconfig-err-array-expected'
|
||||||
|
// : 'jsonconfig-err-Object-expected';
|
||||||
|
// $this->addValidationError( wfMessage( $msg, JCUtils::fieldPathToString( $fldPath ) ) );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /** @var boolean $reposition - should the field be deleted and re-added at the end
|
||||||
|
// * this is only needed for viewing and saving */
|
||||||
|
// $reposition = $this->thorough() && is_string( $fld ) && $subJcv !== false;
|
||||||
|
// if ( $subJcv === false || $subJcv->isUnchecked() ) {
|
||||||
|
// // We never went down this path before
|
||||||
|
// // Check that field exists, and is not case-duplicated
|
||||||
|
// if ( is_int( $fld ) ) {
|
||||||
|
// if ( count( $jcv->getValue() ) < $fld ) {
|
||||||
|
// // Allow existing index or index+1 for appending last item
|
||||||
|
// throw new Exception( "List index is too large at '" .
|
||||||
|
// JCUtils::fieldPathToString( $fldPath ) .
|
||||||
|
// "'. Index may not exceed list size." );
|
||||||
|
// }
|
||||||
|
// } elseif ( !$this->isCaseSensitive ) {
|
||||||
|
// // if we didn't find it before, it could have been misnamed
|
||||||
|
// $norm = $this->normalizeField( $jcv, $fld, $fldPath );
|
||||||
|
// if ( $norm === null ) {
|
||||||
|
// return false;
|
||||||
|
// } elseif ( $norm ) {
|
||||||
|
// $subJcv = $this->getField( $fld, $jcv );
|
||||||
|
// $reposition = false; // normalization already does that
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if ( $subJcv === null ) {
|
||||||
|
// throw new Exception( 'Logic error - subJcv must be valid here' );
|
||||||
|
// } elseif ( $subJcv === false ) {
|
||||||
|
// // field does not exist
|
||||||
|
// $initValue = !$path ? null : ( is_string( $path[0] ) ? new stdClass() : [] );
|
||||||
|
// $subJcv = new JCValue( JCValue::MISSING, $initValue );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// $isOk = $this->testRecursive( $path, $fldPath, $subJcv, $validators );
|
||||||
|
//
|
||||||
|
// // Always remove and re-append the field
|
||||||
|
// if ( $subJcv->isMissing() ) {
|
||||||
|
// $jcv->deleteField( $fld );
|
||||||
|
// } else {
|
||||||
|
// if ( $reposition ) {
|
||||||
|
// $jcv->deleteField( $fld );
|
||||||
|
// }
|
||||||
|
// $jcv->setField( $fld, $subJcv );
|
||||||
|
// if ( $jcv->isMissing() || $jcv->isUnchecked() ) {
|
||||||
|
// $jcv->status( JCValue::VISITED );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return $isOk;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param array $fldPath
|
||||||
|
// * @param JCValue $jcv
|
||||||
|
// * @param array $validators
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// private function testValue( array $fldPath, JCValue $jcv, $validators ) {
|
||||||
|
// // We have reached the last level of the path, test the actual value
|
||||||
|
// if ( $validators !== null ) {
|
||||||
|
// $isRequired = $jcv->defaultUsed();
|
||||||
|
// JCValidators::run( $validators, $jcv, $fldPath, $this );
|
||||||
|
// $err = $jcv->error();
|
||||||
|
// if ( $err ) {
|
||||||
|
// if ( is_object( $err ) ) {
|
||||||
|
// // if ( !$isRequired ) {
|
||||||
|
// // // User supplied value, so we don't know if the value is required or not
|
||||||
|
// // // if $default passes validation, original value was optional
|
||||||
|
// // $isRequired = !JCValidators::run(
|
||||||
|
// // $validators, $fldPath, JCValue::getMissing(), $this
|
||||||
|
// // );
|
||||||
|
// // }
|
||||||
|
// $this->addValidationError( $err, !$isRequired );
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// } elseif ( $jcv->isUnchecked() ) {
|
||||||
|
// $jcv->status( JCValue::CHECKED );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // if ( $this->thorough() && $jcv->status() === JCValue::CHECKED ) {
|
||||||
|
// // // Check if the value is the same as default - use a cast to array
|
||||||
|
// // // hack to compare objects
|
||||||
|
// // $isRequired = (boolean)JCValidators::run( $validators, $fldPath, JCMissing::get(), $this );
|
||||||
|
// // if ( ( is_object( $jcv ) && is_object( $default ) && (array)$jcv === (array)$default )
|
||||||
|
// // || ( !is_object( $default ) && $jcv === $default )
|
||||||
|
// // ) {
|
||||||
|
// // $newStatus = JCValue::SAME_AS_DEFAULT;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Recursively reorder all sub-elements - checked first, followed by unchecked.
|
||||||
|
// * Also, convert all sub-elements to JCValue(UNCHECKED) if at least one of them was JCValue
|
||||||
|
// * This is useful for HTML rendering to indicate unchecked items
|
||||||
|
// * @param JCValue $data
|
||||||
|
// */
|
||||||
|
// private static function markUnchecked( JCValue $data ) {
|
||||||
|
// $val = $data->getValue();
|
||||||
|
// $isObject = is_object( $val );
|
||||||
|
// if ( !$isObject && !is_array( $val ) ) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// $result = null;
|
||||||
|
// $firstPass = true;
|
||||||
|
// $hasJcv = false;
|
||||||
|
// // Two pass loop - first pass moves all checked values to the result,
|
||||||
|
// // second pass moves the rest of of the values, possibly converting them to JCValue
|
||||||
|
// while ( true ) {
|
||||||
|
// foreach ( $val as $key => $subVal ) {
|
||||||
|
// /** @var JCValue|mixed $subVal */
|
||||||
|
// $isJcv = is_a( $subVal, '\JsonConfig\JCValue' );
|
||||||
|
// if ( $firstPass && $isJcv ) {
|
||||||
|
// // On the first pass, recursively process subelements if they were visited
|
||||||
|
// self::markUnchecked( $subVal );
|
||||||
|
// $move = $isObject && !$subVal->isUnchecked();
|
||||||
|
// $hasJcv = true;
|
||||||
|
// } else {
|
||||||
|
// $move = false;
|
||||||
|
// }
|
||||||
|
// if ( $move || !$firstPass ) {
|
||||||
|
// if ( !$isJcv ) {
|
||||||
|
// $subVal = new JCValue( JCValue::UNCHECKED, $subVal );
|
||||||
|
// }
|
||||||
|
// if ( $result === null ) {
|
||||||
|
// $result = $isObject ? new stdClass() : [];
|
||||||
|
// }
|
||||||
|
// if ( $isObject ) {
|
||||||
|
// $result->$key = $subVal;
|
||||||
|
// unset( $val->$key );
|
||||||
|
// } else {
|
||||||
|
// // No need to unset - all values in an array are moved in the second pass
|
||||||
|
// $result[] = $subVal;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ( ( $result === null && !$hasJcv ) || !$firstPass ) {
|
||||||
|
// // either nothing was found, or we are done with the second pass
|
||||||
|
// if ( $result !== null ) {
|
||||||
|
// $data->setValue( $result );
|
||||||
|
// }
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// $firstPass = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param Message $error
|
||||||
|
// * @param boolean $isOptional
|
||||||
|
// */
|
||||||
|
// public function addValidationError( Message $error, $isOptional = false ) {
|
||||||
|
// $text = $error->plain();
|
||||||
|
// // @TODO fixme - need to re-enable optional field detection & reporting
|
||||||
|
// // if ( $isOptional ) {
|
||||||
|
// // $text .= ' ' . wfMessage( 'jsonconfig-optional-field' )->plain();
|
||||||
|
// // }
|
||||||
|
// $this->getStatus()->error( $text );
|
||||||
|
// }
|
||||||
|
|
||||||
|
/** Get field from data Object/array
|
||||||
|
* @param String|int|array $field
|
||||||
|
* @param stdClass|array|JCValue $data
|
||||||
|
* @throws \Exception
|
||||||
|
* @return false|null|JCValue search result:
|
||||||
|
* false if not found
|
||||||
|
* null if error (argument type does not match storage)
|
||||||
|
* JCValue if the value is found
|
||||||
|
*/
|
||||||
|
public JCValue getField(int field) {return getFieldWkr(field, null, null, null);}
|
||||||
|
public JCValue getField(int field, Object data) {return getFieldWkr(field, null, null, data);}
|
||||||
|
public JCValue getField(String field) {return getFieldWkr(-1, field, null, null);}
|
||||||
|
public JCValue getField(String field, Object data) {return getFieldWkr(-1, field, null, data);}
|
||||||
|
public JCValue getField(String[] fields) {return getFieldWkr(-1, null, fields, null);}
|
||||||
|
public JCValue getField(String[] fields, Object data) {return getFieldWkr(-1, null, fields, data);}
|
||||||
|
public JCValue getFieldWkr(int fldInt, String fldStr, String[] fldAry, Object data) {
|
||||||
|
if (data == null) {
|
||||||
|
// data = this.getValidationData();
|
||||||
|
}
|
||||||
|
if (fldAry == null) {
|
||||||
|
data = getFieldByItem(fldInt, fldStr, data);
|
||||||
|
if (data == null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (String fld : fldAry) {
|
||||||
|
data = getFieldByItem(-1, fld, data);
|
||||||
|
if (data == null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Type_.Eq_by_obj(data, JCValue.class)) {
|
||||||
|
return (JCValue)data;
|
||||||
|
} else {
|
||||||
|
// return new JCValue(JCValue.UNCHECKED, data);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Object getFieldByItem(int fldInt, String fldStr, Object data) {
|
||||||
|
if (fldInt == -1 && fldStr == null) {
|
||||||
|
throw Err_.new_wo_type("Field must be either int or String");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type_.Eq_by_obj(data, JCValue.class)) {
|
||||||
|
data = ((JCValue)data).getValue();
|
||||||
|
}
|
||||||
|
int typeId = XomwTypeUtl.To_type_id(data);
|
||||||
|
boolean isObject = typeId == Type_ids_.Id__obj;
|
||||||
|
boolean isArray = typeId == Type_ids_.Id__array;
|
||||||
|
if (fldStr != null ? !(isObject || isArray) : !isArray) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isObject) {
|
||||||
|
XophpStdClass dataAsMap = (XophpStdClass)data;
|
||||||
|
return dataAsMap.Get_by_as_itm(fldStr);
|
||||||
|
} else if (isArray) {
|
||||||
|
Object dataAsAry = Array_.cast(data);
|
||||||
|
if (fldInt < Array_.Len(dataAsAry))
|
||||||
|
return Array_.Get_at(dataAsAry, fldInt);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @param JCValue $jcv
|
||||||
|
// * @param int|String $fld
|
||||||
|
// * @param array $fldPath
|
||||||
|
// * @throws \Exception
|
||||||
|
// * @return boolean|null true if renamed, false if not found or original unchanged,
|
||||||
|
// * null if duplicate (error)
|
||||||
|
// */
|
||||||
|
// private function normalizeField( JCValue $jcv, $fld, array $fldPath ) {
|
||||||
|
// $valueRef = $jcv->getValue();
|
||||||
|
// $foundFld = false;
|
||||||
|
// $isError = false;
|
||||||
|
// foreach ( $valueRef as $k => $v ) {
|
||||||
|
// if ( 0 === strcasecmp( $k, $fld ) ) {
|
||||||
|
// if ( $foundFld !== false ) {
|
||||||
|
// $isError = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// $foundFld = $k;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if ( $isError ) {
|
||||||
|
// $this->addValidationError( wfMessage( 'jsonconfig-duplicate-field',
|
||||||
|
// JCUtils::fieldPathToString( $fldPath ) ) );
|
||||||
|
// if ( $this->thorough() ) {
|
||||||
|
// // Mark all duplicate fields as errors
|
||||||
|
// foreach ( $valueRef as $k => $v ) {
|
||||||
|
// if ( 0 === strcasecmp( $k, $fld ) ) {
|
||||||
|
// if ( !is_a( $v, '\JsonConfig\JCValue' ) ) {
|
||||||
|
// $v = new JCValue( JCValue::UNCHECKED, $v );
|
||||||
|
// $jcv->setField( $k, $v );
|
||||||
|
// }
|
||||||
|
// $v->error( true );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// } elseif ( $foundFld !== false && $foundFld !== $fld ) {
|
||||||
|
// // key had different casing, rename it to canonical
|
||||||
|
// $jcv->setField( $fld, $jcv->deleteField( $foundFld ) );
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param null|callable|array $param first validator parameter
|
||||||
|
// * @param array $funcArgs result of func_get_args() call
|
||||||
|
// * @param int $skipArgs how many non-validator arguments to remove
|
||||||
|
// * from the beginning of the $funcArgs
|
||||||
|
// * @return array of validators
|
||||||
|
// */
|
||||||
|
// private static function convertValidators( $param, $funcArgs, $skipArgs ) {
|
||||||
|
// if ( $param === null ) {
|
||||||
|
// return []; // no validators given
|
||||||
|
// } elseif ( is_array( $param ) && !is_callable( $param, true ) ) {
|
||||||
|
// return $param; // first argument is an array of validators
|
||||||
|
// } else {
|
||||||
|
// return array_slice( $funcArgs, $skipArgs ); // remove fixed params from the beginning
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,995 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
|
||||||
|
public class JCSingleton {
|
||||||
|
// /**
|
||||||
|
// * @var array describes how a title should be handled by JsonConfig extension.
|
||||||
|
// * The structure is an array of array of ...:
|
||||||
|
// * { int_namespace => { name => { allows-sub-namespaces => configuration_array } } }
|
||||||
|
// */
|
||||||
|
// public static $titleMap = [];
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @var String[]|false[] containing all the namespaces handled by JsonConfig
|
||||||
|
// * Maps namespace id (int) => namespace name (String).
|
||||||
|
// * If false, presumes the namespace has been registered by core or another extension
|
||||||
|
// */
|
||||||
|
// public static $namespaces = [];
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @var MapCacheLRU[] contains a cache of recently resolved JCTitle's
|
||||||
|
// * as namespace => MapCacheLRU
|
||||||
|
// */
|
||||||
|
// public static $titleMapCacheLru = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MapCacheLRU[] contains a cache of recently requested content objects
|
||||||
|
* as namespace => MapCacheLRU
|
||||||
|
*/
|
||||||
|
private final Ordered_hash mapCacheLru = Ordered_hash_.New();
|
||||||
|
|
||||||
|
public Xomw_page_fetcher Store() {return store;} public void Store_(Xomw_page_fetcher v) {this.store = v;} private Xomw_page_fetcher store;
|
||||||
|
public Xophp_ary ConfigModels() {return configModels;} private final Xophp_ary configModels = new Xophp_ary();
|
||||||
|
// /**
|
||||||
|
// * @var TitleParser cached invariant title parser
|
||||||
|
// */
|
||||||
|
// public static $titleParser;
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Initializes singleton state by parsing $wgJsonConfig* values
|
||||||
|
// * @throws Exception
|
||||||
|
// */
|
||||||
|
// private static function init() {
|
||||||
|
// static $isInitialized = false;
|
||||||
|
// if ($isInitialized) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// $isInitialized = true;
|
||||||
|
// global $wgNamespaceContentModels, $wgContentHandlers, $wgJsonConfigs, $wgJsonConfigModels;
|
||||||
|
// list(self::$titleMap, self::$namespaces) = self::parseConfiguration(
|
||||||
|
// $wgNamespaceContentModels,
|
||||||
|
// $wgContentHandlers,
|
||||||
|
// array_replace_recursive(
|
||||||
|
// \ExtensionRegistry::getInstance()->getAttribute('JsonConfigs'), $wgJsonConfigs
|
||||||
|
// ),
|
||||||
|
// array_replace_recursive(
|
||||||
|
// \ExtensionRegistry::getInstance()->getAttribute('JsonConfigModels'),
|
||||||
|
// $wgJsonConfigModels
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param array $namespaceContentModels $wgNamespaceContentModels
|
||||||
|
// * @param array $contentHandlers $wgContentHandlers
|
||||||
|
// * @param array $configs $wgJsonConfigs
|
||||||
|
// * @param array $models $wgJsonConfigModels
|
||||||
|
// * @param boolean $warn if true, calls wfLogWarning() for all errors
|
||||||
|
// * @return array [ $titleMap, $namespaces ]
|
||||||
|
// */
|
||||||
|
// public static function parseConfiguration(
|
||||||
|
// array $namespaceContentModels, array $contentHandlers,
|
||||||
|
// array $configs, array $models, $warn = true
|
||||||
|
// ) {
|
||||||
|
// $defaultModelId = 'JsonConfig';
|
||||||
|
// // @codingStandardsIgnoreStart - T154789
|
||||||
|
// $warnFunc = $warn ? 'wfLogWarning' : function() {};
|
||||||
|
// // @codingStandardsIgnoreEnd
|
||||||
|
//
|
||||||
|
// $namespaces = [];
|
||||||
|
// $titleMap = [];
|
||||||
|
// foreach ($configs as $confId => &$conf) {
|
||||||
|
// if (!is_string($confId)) {
|
||||||
|
// $warnFunc(
|
||||||
|
// "JsonConfig: Invalid \$wgJsonConfigs['$confId'], the key must be a String"
|
||||||
|
// );
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if (null == self::getConfObject($warnFunc, $conf, $confId)) {
|
||||||
|
// continue; // warned inside the function
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $modelId = property_exists($conf, 'model')
|
||||||
|
// ? ($conf->model ? : $defaultModelId) : $confId;
|
||||||
|
// if (!array_key_exists($modelId, $models)) {
|
||||||
|
// if ($modelId == $defaultModelId) {
|
||||||
|
// $models[$defaultModelId] = null;
|
||||||
|
// } else {
|
||||||
|
// $warnFunc("JsonConfig: Invalid \$wgJsonConfigs['$confId']: " .
|
||||||
|
// "Model '$modelId' is not defined in \$wgJsonConfigModels");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (array_key_exists($modelId, $contentHandlers)) {
|
||||||
|
// $warnFunc("JsonConfig: Invalid \$wgJsonConfigs['$confId']: Model '$modelId' is " .
|
||||||
|
// "already registered in \$contentHandlers to {$contentHandlers[$modelId]}");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// $conf->model = $modelId;
|
||||||
|
//
|
||||||
|
// $ns = self::getConfVal($conf, 'namespace', NS_CONFIG);
|
||||||
|
// if (!is_int($ns) || $ns % 2 !== 0) {
|
||||||
|
// $warnFunc("JsonConfig: Invalid \$wgJsonConfigs['$confId']: " .
|
||||||
|
// "Namespace $ns should be an even number");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// // Even though we might be able to override default content model for namespace,
|
||||||
|
// // lets keep things clean
|
||||||
|
// if (array_key_exists($ns, $namespaceContentModels)) {
|
||||||
|
// $warnFunc("JsonConfig: Invalid \$wgJsonConfigs['$confId']: Namespace $ns is " .
|
||||||
|
// "already set to handle model '$namespaceContentModels[$ns]'");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // nsName & nsTalk are handled later
|
||||||
|
// self::getConfVal($conf, 'pattern', '');
|
||||||
|
// self::getConfVal($conf, 'cacheExp', 24 * 60 * 60);
|
||||||
|
// self::getConfVal($conf, 'cacheKey', '');
|
||||||
|
// self::getConfVal($conf, 'flaggedRevs', false);
|
||||||
|
// self::getConfVal($conf, 'license', false);
|
||||||
|
// $islocal = self::getConfVal($conf, 'isLocal', true);
|
||||||
|
//
|
||||||
|
// // Decide if matching configs should be stored on this wiki
|
||||||
|
// $storeHere = $islocal || property_exists($conf, 'store');
|
||||||
|
// if (!$storeHere) {
|
||||||
|
// // 'store' does not exist, use it as a flag to indicate remote storage
|
||||||
|
// $conf->store = false;
|
||||||
|
// $remote = self::getConfObject($warnFunc, $conf, 'remote', $confId, 'url');
|
||||||
|
// if (null == $remote) {
|
||||||
|
// continue; // warned inside the function
|
||||||
|
// }
|
||||||
|
// if (self::getConfVal($remote, 'url', '') == '') {
|
||||||
|
// $warnFunc("JsonConfig: Invalid \$wgJsonConfigs['$confId']['remote']['url']: " .
|
||||||
|
// "API URL is not set, and this config is not being stored locally");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// self::getConfVal($remote, 'username', '');
|
||||||
|
// self::getConfVal($remote, 'password', '');
|
||||||
|
// } else {
|
||||||
|
// if (property_exists($conf, 'remote')) {
|
||||||
|
// // non-fatal -- simply ignore the 'remote' setting
|
||||||
|
// $warnFunc("JsonConfig: In \$wgJsonConfigs['$confId']['remote'] is set for " .
|
||||||
|
// "the config that will be stored on this wiki. " .
|
||||||
|
// "'remote' parameter will be ignored."
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// $conf->remote = null;
|
||||||
|
// $store = self::getConfObject($warnFunc, $conf, 'store', $confId);
|
||||||
|
// if (null == $store) {
|
||||||
|
// continue; // warned inside the function
|
||||||
|
// }
|
||||||
|
// self::getConfVal($store, 'cacheNewValue', true);
|
||||||
|
// self::getConfVal($store, 'notifyUrl', '');
|
||||||
|
// self::getConfVal($store, 'notifyUsername', '');
|
||||||
|
// self::getConfVal($store, 'notifyPassword', '');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Too lazy to write proper error messages for all parameters.
|
||||||
|
// if ((isset($conf->nsTalk) && !is_string($conf->nsTalk)) ||
|
||||||
|
// !is_string($conf->pattern) ||
|
||||||
|
// !is_bool($islocal) || !is_int($conf->cacheExp) || !is_string($conf->cacheKey)
|
||||||
|
// || !is_bool($conf->flaggedRevs)
|
||||||
|
// ) {
|
||||||
|
// $warnFunc("JsonConfig: Invalid type of one of the parameters in " .
|
||||||
|
// "\$wgJsonConfigs['$confId'], please check documentation");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if (isset($remote)) {
|
||||||
|
// if (!is_string($remote->url) || !is_string($remote->username) ||
|
||||||
|
// !is_string($remote->password)
|
||||||
|
// ) {
|
||||||
|
// $warnFunc("JsonConfig: Invalid type of one of the parameters in " .
|
||||||
|
// "\$wgJsonConfigs['$confId']['remote'], please check documentation");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (isset($store)) {
|
||||||
|
// if (!is_bool($store->cacheNewValue) || !is_string($store->notifyUrl) ||
|
||||||
|
// !is_string($store->notifyUsername) || !is_string($store->notifyPassword)
|
||||||
|
// ) {
|
||||||
|
// $warnFunc("JsonConfig: Invalid type of one of the parameters in " .
|
||||||
|
// " \$wgJsonConfigs['$confId']['store'], please check documentation");
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if ($storeHere) {
|
||||||
|
// // If nsName is given, add it to the list, together with the talk page
|
||||||
|
// // Otherwise, create a placeholder for it
|
||||||
|
// if (property_exists($conf, 'nsName')) {
|
||||||
|
// if ($conf->nsName == false) {
|
||||||
|
// // Non JC-specific namespace, don't register it
|
||||||
|
// if (!array_key_exists($ns, $namespaces)) {
|
||||||
|
// $namespaces[$ns] = false;
|
||||||
|
// }
|
||||||
|
// } elseif ($ns == NS_CONFIG) {
|
||||||
|
// $warnFunc("JsonConfig: Parameter 'nsName' in \$wgJsonConfigs['$confId'] " .
|
||||||
|
// "is not supported for namespace == NS_CONFIG ($ns)");
|
||||||
|
// } else {
|
||||||
|
// $nsName = $conf->nsName;
|
||||||
|
// $nsTalk = isset($conf->nsTalk) ? $conf->nsTalk : ($nsName . '_talk');
|
||||||
|
// if (!is_string($nsName) || $nsName == '') {
|
||||||
|
// $warnFunc("JsonConfig: Invalid \$wgJsonConfigs['$confId']: " .
|
||||||
|
// "if given, nsName must be a String");
|
||||||
|
// continue;
|
||||||
|
// } elseif (array_key_exists($ns, $namespaces) &&
|
||||||
|
// $namespaces[$ns] !== null
|
||||||
|
// ) {
|
||||||
|
// if ($namespaces[$ns] !== $nsName ||
|
||||||
|
// $namespaces[$ns + 1] !== $nsTalk
|
||||||
|
// ) {
|
||||||
|
// $warnFunc("JsonConfig: \$wgJsonConfigs['$confId'] - " .
|
||||||
|
// "nsName has already been set for namespace $ns");
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// $namespaces[$ns] = $nsName;
|
||||||
|
// $namespaces[$ns + 1] =
|
||||||
|
// isset($conf->nsTalk) ? $conf->nsTalk : ($nsName . '_talk');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } elseif (!array_key_exists($ns, $namespaces) || $namespaces[$ns] == false) {
|
||||||
|
// $namespaces[$ns] = null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!array_key_exists($ns, $titleMap)) {
|
||||||
|
// $titleMap[$ns] = [ $conf ];
|
||||||
|
// } else {
|
||||||
|
// $titleMap[$ns][] = $conf;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Add all undeclared namespaces
|
||||||
|
// $missingNs = 1;
|
||||||
|
// foreach ($namespaces as $ns => $nsName) {
|
||||||
|
// if ($nsName == null) {
|
||||||
|
// $nsName = 'Config';
|
||||||
|
// if ($ns !== NS_CONFIG) {
|
||||||
|
// $nsName .= $missingNs;
|
||||||
|
// $warnFunc(
|
||||||
|
// "JsonConfig: Namespace $ns does not have 'nsName' defined, using '$nsName'"
|
||||||
|
// );
|
||||||
|
// $missingNs += 1;
|
||||||
|
// }
|
||||||
|
// $namespaces[$ns] = $nsName;
|
||||||
|
// $namespaces[$ns + 1] = $nsName . '_talk';
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return [ $titleMap, $namespaces ];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Helper function to check if configuration has a field set, and if not, set it to default
|
||||||
|
// * @param stdClass $conf
|
||||||
|
// * @param String $field
|
||||||
|
// * @param mixed $default
|
||||||
|
// * @return mixed
|
||||||
|
// */
|
||||||
|
// private static function getConfVal(& $conf, $field, $default) {
|
||||||
|
// if (property_exists($conf, $field)) {
|
||||||
|
// return $conf->$field;
|
||||||
|
// }
|
||||||
|
// $conf->$field = $default;
|
||||||
|
// return $default;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Helper function to check if configuration has a field set, and if not, set it to default
|
||||||
|
// * @param $warnFunc
|
||||||
|
// * @param $value
|
||||||
|
// * @param String $field
|
||||||
|
// * @param String $confId
|
||||||
|
// * @param String $treatAsField
|
||||||
|
// * @return null|Object|stdClass
|
||||||
|
// */
|
||||||
|
// private static function getConfObject(
|
||||||
|
// $warnFunc, & $value, $field, $confId = null, $treatAsField = null
|
||||||
|
// ) {
|
||||||
|
// if (!$confId) {
|
||||||
|
// $val = & $value;
|
||||||
|
// } else {
|
||||||
|
// if (!property_exists($value, $field)) {
|
||||||
|
// $value->$field = null;
|
||||||
|
// }
|
||||||
|
// $val = & $value->$field;
|
||||||
|
// }
|
||||||
|
// if ($val == null || $val == true) {
|
||||||
|
// $val = new stdClass();
|
||||||
|
// } elseif (is_array($val)) {
|
||||||
|
// $val = (Object)$val;
|
||||||
|
// } elseif (is_string($val) && $treatAsField !== null) {
|
||||||
|
// // treating this String value as a sub-field
|
||||||
|
// $val = (Object)[ $treatAsField => $val ];
|
||||||
|
// } elseif (!is_object($val)) {
|
||||||
|
// $warnFunc("JsonConfig: Invalid \$wgJsonConfigs" . ($confId ? "['$confId']" : "") .
|
||||||
|
// "['$field'], the value must be either an array or an Object");
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// return $val;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get content Object from the local LRU cache, or null if doesn't exist
|
||||||
|
* @param TitleValue $titleValue
|
||||||
|
* @return null|JCContent
|
||||||
|
*/
|
||||||
|
public JCContent getContentFromLocalCache(String wiki, String ns, String page) {
|
||||||
|
// Some of the titleValues are remote, and their namespace might not be declared
|
||||||
|
// in the current wiki. Since TitleValue is a content Object, it does not validate
|
||||||
|
// the existence of namespace, hence we use it as a simple storage.
|
||||||
|
// Producing an artificial String key by appending (namespaceID . ':' . titleDbKey)
|
||||||
|
// seems wasteful and redundant, plus most of the time there will be just a single
|
||||||
|
// namespace declared, so this structure seems efficient and easy enough.
|
||||||
|
String mapCacheLruKey = String_.Concat(wiki, "|", ns);
|
||||||
|
Ordered_hash cache = (Ordered_hash)mapCacheLru.Get_by(mapCacheLruKey);
|
||||||
|
if (cache == null) {
|
||||||
|
cache = Ordered_hash_.New();
|
||||||
|
mapCacheLru.Add(mapCacheLruKey, cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (JCContent)cache.Get_by(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get content Object for the given title.
|
||||||
|
* Namespace ID does not need to be defined in the current wiki,
|
||||||
|
* as long as it is defined in $wgJsonConfigs.
|
||||||
|
* @param TitleValue|JCTitle $titleValue
|
||||||
|
* @return boolean|JCContent Returns false if the title is not handled by the settings
|
||||||
|
*/
|
||||||
|
public JCContent getContent(String wiki, String ns, String page) {
|
||||||
|
JCContent content = getContentFromLocalCache(wiki, ns, page);
|
||||||
|
|
||||||
|
if (content == null) {
|
||||||
|
byte[] content_bry = store.Get_wtxt(Bry_.new_u8(wiki), Bry_.new_u8(page));
|
||||||
|
if (content_bry != null) {
|
||||||
|
JCContentHandler handler = new JCContentHandler();
|
||||||
|
handler.__construct(JCTabularContent.Model_id, this);
|
||||||
|
content = handler.unserializeContent(content_bry, null, false);
|
||||||
|
}
|
||||||
|
// $jct = self::parseTitle($titleValue);
|
||||||
|
// if ($jct) {
|
||||||
|
// $store = new JCCache($jct);
|
||||||
|
// $content = $store->get();
|
||||||
|
// if (is_string($content)) {
|
||||||
|
// // Convert String to the content Object if needed
|
||||||
|
// $handler = new JCContentHandler($jct->getConfig()->model);
|
||||||
|
// $content = $handler->unserializeContent($content, null, false);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// $content = false;
|
||||||
|
// }
|
||||||
|
// self::mapCacheLru[$titleValue->getNamespace()]
|
||||||
|
// ->set($titleValue->getDBkey(), $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Parse json text into a content Object for the given title.
|
||||||
|
// * Namespace ID does not need to be defined in the current wiki,
|
||||||
|
// * as long as it is defined in $wgJsonConfigs.
|
||||||
|
// * @param TitleValue $titleValue
|
||||||
|
// * @param String $jsonText json content
|
||||||
|
// * @param boolean $isSaving if true, performs extensive validation during unserialization
|
||||||
|
// * @return boolean|JCContent Returns false if the title is not handled by the settings
|
||||||
|
// * @throws Exception
|
||||||
|
// */
|
||||||
|
// public static function parseContent(TitleValue $titleValue, $jsonText, $isSaving = false) {
|
||||||
|
// $jct = self::parseTitle($titleValue);
|
||||||
|
// if ($jct) {
|
||||||
|
// $handler = new JCContentHandler($jct->getConfig()->model);
|
||||||
|
// return $handler->unserializeContent($jsonText, null, $isSaving);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Mostly for debugging purposes, this function returns initialized @gplx.Internal protected JsonConfig settings
|
||||||
|
// * @return array[] map of namespaceIDs to list of configurations
|
||||||
|
// */
|
||||||
|
// public static function getTitleMap() {
|
||||||
|
// self::init();
|
||||||
|
// return self::$titleMap;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the class for a given content model
|
||||||
|
* @param String $modelId
|
||||||
|
* @return null|String
|
||||||
|
*/
|
||||||
|
public XophpClassBldr getContentClass(String modelId) {
|
||||||
|
// global $wgJsonConfigModels;
|
||||||
|
// $configModels = array_replace_recursive(
|
||||||
|
// \ExtensionRegistry::getInstance()->getAttribute('JsonConfigModels'),
|
||||||
|
// $wgJsonConfigModels
|
||||||
|
// );
|
||||||
|
String clz = null;
|
||||||
|
if (configModels.Has(modelId)) {
|
||||||
|
Object val = configModels.Get(modelId);
|
||||||
|
if (Type_.Type_by_obj(val) == Xophp_ary.class) {
|
||||||
|
Xophp_ary val_as_ary = (Xophp_ary)val;
|
||||||
|
if (val_as_ary.Has("class")) {
|
||||||
|
Gfo_usr_dlg_.Instance.Warn_many("", "", "JsonConfig: Invalid +$wgJsonConfigModels['modelId'] array " + "value, 'cl"+ "ass' not found");
|
||||||
|
} else {
|
||||||
|
clz = (String)val_as_ary.Get("class");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clz = (String)val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (clz == null) {
|
||||||
|
clz = "JCContent"; // __NAMESPACE__ . '\JCContent';
|
||||||
|
}
|
||||||
|
return XophpEnv.Instance.ClassBldrs().Get_by_or_null(clz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Given a title (either a user-given String, or as an Object), return JCTitle
|
||||||
|
// * @param Title|TitleValue|String $value
|
||||||
|
// * @param int|null $namespace Only used when title is a String
|
||||||
|
// * @return JCTitle|null|false false if unrecognized namespace,
|
||||||
|
// * and null if namespace is handled but does not match this title
|
||||||
|
// * @throws Exception
|
||||||
|
// */
|
||||||
|
// public static function parseTitle($value, $namespace = null) {
|
||||||
|
// if ($value == null || $value == '' || $value == false) {
|
||||||
|
// // In some weird cases $value is null
|
||||||
|
// return false;
|
||||||
|
// } elseif ($value instanceof JCTitle) {
|
||||||
|
// // Nothing to do
|
||||||
|
// return $value;
|
||||||
|
// } elseif ($namespace !== null && !is_integer($namespace)) {
|
||||||
|
// throw new Exception('$namespace parameter must be either null or an integer');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // figure out the namespace ID (int) - we don't need to parse the String if ns is unknown
|
||||||
|
// if ($value instanceof LinkTarget) {
|
||||||
|
// if ($namespace == null) {
|
||||||
|
// $namespace = $value->getNamespace();
|
||||||
|
// }
|
||||||
|
// } elseif (is_string($value)) {
|
||||||
|
// if ($namespace == null) {
|
||||||
|
// throw new Exception('$namespace parameter is missing for String $value');
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// wfLogWarning('Unexpected title param type ' . gettype($value));
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Search title map for the matching configuration
|
||||||
|
// $map = self::getTitleMap();
|
||||||
|
// if (array_key_exists($namespace, $map)) {
|
||||||
|
// // Get appropriate LRU cache Object
|
||||||
|
// if (!array_key_exists($namespace, self::$titleMapCacheLru)) {
|
||||||
|
// self::$titleMapCacheLru[$namespace] = $cache = new MapCacheLRU(20);
|
||||||
|
// } else {
|
||||||
|
// $cache = self::$titleMapCacheLru[$namespace];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Parse String if needed
|
||||||
|
// // TODO: should the String parsing also be cached?
|
||||||
|
// if (is_string($value)) {
|
||||||
|
// $language = Language::factory('en');
|
||||||
|
// if (!self::$titleParser) {
|
||||||
|
// self::$titleParser =
|
||||||
|
// new MediaWikiTitleCodec(
|
||||||
|
// $language,
|
||||||
|
// new GenderCache(),
|
||||||
|
// [],
|
||||||
|
// new FauxInterwikiLookup());
|
||||||
|
// }
|
||||||
|
// // Interwiki prefixes are a special case for title parsing:
|
||||||
|
// // first letter is not capitalized, namespaces are not resolved, etc.
|
||||||
|
// // So we prepend an interwiki prefix to fool title codec, and later remove it.
|
||||||
|
// try {
|
||||||
|
// $value = FauxInterwikiLookup::INTERWIKI_PREFIX . ':' . $value;
|
||||||
|
// $parts = self::$titleParser->splitTitleString($value);
|
||||||
|
//
|
||||||
|
// // Defensive coding - ensure the parsing has proceeded as expected
|
||||||
|
// if ($parts['dbkey'] == '' || $parts['namespace'] !== 0 ||
|
||||||
|
// $parts['fragment'] !== '' || $parts['local_interwiki'] !== false ||
|
||||||
|
// $parts['interwiki'] !== FauxInterwikiLookup::INTERWIKI_PREFIX
|
||||||
|
// ) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// } catch (MalformedTitleException $e) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // At this point, only support wiki namespaces that capitalize title's first char,
|
||||||
|
// // but do not enable sub-pages.
|
||||||
|
// // This way data can already be stored on Mediawiki namespace everywhere, or
|
||||||
|
// // places like commons and zerowiki.
|
||||||
|
// // Another implicit limitation: there might be an issue if data is stored on a wiki
|
||||||
|
// // with the non-default ucfirst(), e.g. az, kaa, kk, tr -- they convert "i" to "I"
|
||||||
|
// $dbKey = $language->ucfirst($parts['dbkey']);
|
||||||
|
// } else {
|
||||||
|
// $dbKey = $value->getDBkey();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // A bit weird here: cache will store JCTitle objects or false if the namespace
|
||||||
|
// // is known to JsonConfig but the dbkey does not match. But in case the title is not
|
||||||
|
// // handled, this function returns null instead of false if the namespace is known,
|
||||||
|
// // and false otherwise
|
||||||
|
// $result = $cache->get($dbKey);
|
||||||
|
// if ($result == null) {
|
||||||
|
// $result = false;
|
||||||
|
// foreach ($map[$namespace] as $conf) {
|
||||||
|
// $re = $conf->pattern;
|
||||||
|
// if (!$re || preg_match($re, $dbKey)) {
|
||||||
|
// $result = new JCTitle($namespace, $dbKey, $conf);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $cache->set($dbKey, $result);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // return null if the given namespace is mentioned in the config,
|
||||||
|
// // but title doesn't match
|
||||||
|
// return $result ?: null;
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // return false if JC doesn't know anything about this namespace
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns an array with settings if the $titleValue Object is handled by the JsonConfig
|
||||||
|
// * extension, false if unrecognized namespace,
|
||||||
|
// * and null if namespace is handled but not this title
|
||||||
|
// * @param TitleValue $titleValue
|
||||||
|
// * @return stdClass|false|null
|
||||||
|
// * @deprecated use JCSingleton::parseTitle() instead
|
||||||
|
// */
|
||||||
|
// public static function getMetadata($titleValue) {
|
||||||
|
// $jct = self::parseTitle($titleValue);
|
||||||
|
// return $jct ? $jct->getConfig() : $jct;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Only register NS_CONFIG if running on the MediaWiki instance which houses
|
||||||
|
// * the JSON configs (i.e. META)
|
||||||
|
// * @TODO FIXME: Always return true
|
||||||
|
// * @param array &$namespaces
|
||||||
|
// * @return true|void
|
||||||
|
// */
|
||||||
|
// public static function onCanonicalNamespaces(array &$namespaces) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// self::init();
|
||||||
|
// foreach (self::$namespaces as $ns => $name) {
|
||||||
|
// if ($name == false) { // must be already declared
|
||||||
|
// if (!array_key_exists($ns, $namespaces)) {
|
||||||
|
// wfLogWarning("JsonConfig: Invalid \$wgJsonConfigs: Namespace $ns " .
|
||||||
|
// "has not been declared by core or other extensions");
|
||||||
|
// }
|
||||||
|
// } elseif (array_key_exists($ns, $namespaces)) {
|
||||||
|
// wfLogWarning("JsonConfig: Invalid \$wgJsonConfigs: Namespace $ns => '$name' " .
|
||||||
|
// "is already declared as '$namespaces[$ns]'");
|
||||||
|
// } else {
|
||||||
|
// $key = array_search($name, $namespaces);
|
||||||
|
// if ($key !== false) {
|
||||||
|
// wfLogWarning("JsonConfig: Invalid \$wgJsonConfigs: Namespace $ns => '$name' " .
|
||||||
|
// "has identical name with the namespace #$key");
|
||||||
|
// } else {
|
||||||
|
// $namespaces[$ns] = $name;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Initialize state
|
||||||
|
// * @param Title $title
|
||||||
|
// * @param String &$modelId
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onContentHandlerDefaultModelFor($title, &$modelId) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $jct = self::parseTitle($title);
|
||||||
|
// if ($jct) {
|
||||||
|
// $modelId = $jct->getConfig()->model;
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Instantiate JCContentHandler if we can handle this modelId
|
||||||
|
// * @param String $modelId
|
||||||
|
// * @param \ContentHandler &$handler
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onContentHandlerForModelID($modelId, &$handler) {
|
||||||
|
// global $wgJsonConfigModels;
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// self::init();
|
||||||
|
// $models = array_replace_recursive(
|
||||||
|
// \ExtensionRegistry::getInstance()->getAttribute('JsonConfigModels'),
|
||||||
|
// $wgJsonConfigModels
|
||||||
|
// );
|
||||||
|
// if (array_key_exists($modelId, $models)) {
|
||||||
|
// // This is one of our model IDs
|
||||||
|
// $handler = new JCContentHandler($modelId);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * CustomEditor hook handler
|
||||||
|
// * @see https://www.mediawiki.org/wiki/Manual:Hooks/CustomEditor
|
||||||
|
// *
|
||||||
|
// * @param Article $article
|
||||||
|
// * @param User $user
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onCustomEditor($article, $user) {
|
||||||
|
// if (!$article || !self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// $jct = self::parseTitle($article->getTitle());
|
||||||
|
// if (!$jct) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $editor = new \EditPage($article);
|
||||||
|
// $editor->contentFormat = JCContentHandler::CONTENT_FORMAT_JSON_PRETTY;
|
||||||
|
// $editor->edit();
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Declares JSON as the code editor language for Config: pages.
|
||||||
|
// * This hook only runs if the CodeEditor extension is enabled.
|
||||||
|
// * @param Title $title
|
||||||
|
// * @param String &$lang Page language.
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onCodeEditorGetPageLanguage($title, &$lang) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // todo/fixme? We should probably add 'json' lang to only those pages that pass parseTitle()
|
||||||
|
// $handler = ContentHandler::getForModelID($title->getContentModel());
|
||||||
|
// if ($handler->getDefaultFormat() == CONTENT_FORMAT_JSON || self::parseTitle($title)) {
|
||||||
|
// $lang = 'json';
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Validates that the revised contents are valid JSON.
|
||||||
|
// * If not valid, rejects edit with error message.
|
||||||
|
// * @param \IContextSource $context
|
||||||
|
// * @param JCContent $content
|
||||||
|
// * @param \Status $status
|
||||||
|
// * @param String $summary Edit summary provided for edit.
|
||||||
|
// * @param \User $user
|
||||||
|
// * @param boolean $minoredit
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onEditFilterMergedContent(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// $context, $content, $status, $summary, $user, $minoredit
|
||||||
|
// ) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (is_a($content, 'JsonConfig\JCContent')) {
|
||||||
|
// $status->merge($content->getStatus());
|
||||||
|
// if (!$status->isGood()) {
|
||||||
|
// $status->setResult(false, $status->getValue());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Override a per-page specific edit page copyright warning
|
||||||
|
// *
|
||||||
|
// * @param Title $title
|
||||||
|
// * @param String[] &$msg
|
||||||
|
// *
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onEditPageCopyrightWarning($title, &$msg) {
|
||||||
|
// if (self::jsonConfigIsStorage()) {
|
||||||
|
// $jct = self::parseTitle($title);
|
||||||
|
// if ($jct) {
|
||||||
|
// $code = $jct->getConfig()->license;
|
||||||
|
// if ($code) {
|
||||||
|
// $msg = [ 'jsonconfig-license-copyrightwarning-' . $code ];
|
||||||
|
// return false; // Do not allow any other hook handler to override this
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Display a page-specific edit notice
|
||||||
|
// *
|
||||||
|
// * @param Title $title
|
||||||
|
// * @param int $oldid
|
||||||
|
// * @param array &$notices
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onTitleGetEditNotices(Title $title, $oldid, array &$notices) {
|
||||||
|
// if (self::jsonConfigIsStorage()) {
|
||||||
|
// $jct = self::parseTitle($title);
|
||||||
|
// if ($jct) {
|
||||||
|
// $code = $jct->getConfig()->license;
|
||||||
|
// if ($code) {
|
||||||
|
// $noticeText = wfMessage('jsonconfig-license-notice-' . $code)->parse();
|
||||||
|
// $notices['jsonconfig'] =
|
||||||
|
// wfMessage('jsonconfig-license-notice-box-' . $code)
|
||||||
|
// ->rawParams($noticeText)
|
||||||
|
// ->parseAsBlock();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Override with per-page specific copyright message
|
||||||
|
// *
|
||||||
|
// * @param Title $title
|
||||||
|
// * @param String $type
|
||||||
|
// * @param String &$msg
|
||||||
|
// * @param String &$link
|
||||||
|
// *
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onSkinCopyrightFooter($title, $type, &$msg, &$link) {
|
||||||
|
// if (self::jsonConfigIsStorage()) {
|
||||||
|
// $jct = self::parseTitle($title);
|
||||||
|
// if ($jct) {
|
||||||
|
// $code = $jct->getConfig()->license;
|
||||||
|
// if ($code) {
|
||||||
|
// $msg = 'jsonconfig-license';
|
||||||
|
// $link = Html::element('a', [
|
||||||
|
// 'href' => wfMessage('jsonconfig-license-url-' . $code)->plain()
|
||||||
|
// ], wfMessage('jsonconfig-license-name-' . $code)->plain());
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Adds CSS for pretty-printing configuration on NS_CONFIG pages.
|
||||||
|
// * @param \OutputPage &$out
|
||||||
|
// * @param \Skin &$skin
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onBeforePageDisplay(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */ &$out, &$skin
|
||||||
|
// ) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $title = $out->getTitle();
|
||||||
|
// // todo/fixme? We should probably add ext.jsonConfig style to only those pages
|
||||||
|
// // that pass parseTitle()
|
||||||
|
// $handler = ContentHandler::getForModelID($title->getContentModel());
|
||||||
|
// if ($handler->getDefaultFormat() == CONTENT_FORMAT_JSON ||
|
||||||
|
// self::parseTitle($title)
|
||||||
|
// ) {
|
||||||
|
// $out->addModuleStyles('ext.jsonConfig');
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static function onMovePageIsValidMove(
|
||||||
|
// Title $oldTitle, Title $newTitle, Status $status
|
||||||
|
// ) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $jctOld = self::parseTitle($oldTitle);
|
||||||
|
// if ($jctOld) {
|
||||||
|
// $jctNew = self::parseTitle($newTitle);
|
||||||
|
// if (!$jctNew) {
|
||||||
|
// $status->fatal('jsonconfig-move-aborted-ns');
|
||||||
|
// return false;
|
||||||
|
// } elseif ($jctOld->getConfig()->model !== $jctNew->getConfig()->model) {
|
||||||
|
// $status->fatal('jsonconfig-move-aborted-model', $jctOld->getConfig()->model,
|
||||||
|
// $jctNew->getConfig()->model);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static function onAbortMove(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// Title $title, Title $newTitle, $wgUser, &$err, $reason
|
||||||
|
// ) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $status = new \Status();
|
||||||
|
// self::onMovePageIsValidMove($title, $newTitle, $status);
|
||||||
|
// if (!$status->isOK()) {
|
||||||
|
// $err = $status->getHTML();
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Conditionally load API module 'jsondata' depending on whether or not
|
||||||
|
// * this wiki stores any jsonconfig data
|
||||||
|
// *
|
||||||
|
// * @param ApiModuleManager $moduleManager Module manager instance
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onApiMainModuleManager(ApiModuleManager $moduleManager) {
|
||||||
|
// global $wgJsonConfigEnableLuaSupport;
|
||||||
|
// if ($wgJsonConfigEnableLuaSupport) {
|
||||||
|
// $moduleManager->addModule('jsondata', 'action', 'JsonConfig\\JCDataApi');
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static function onPageContentSaveComplete(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// \WikiPage $wikiPage, $user, $content, $summary, $isMinor, $isWatch,
|
||||||
|
// $section, $flags, $revision, $status, $baseRevId
|
||||||
|
// ) {
|
||||||
|
// return self::onArticleChangeComplete($wikiPage, $content);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static function onArticleDeleteComplete(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// $article, &$user, $reason, $id, $content, $logEntry
|
||||||
|
// ) {
|
||||||
|
// return self::onArticleChangeComplete($article);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static function onArticleUndelete(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// $title, $created, $comment, $oldPageId
|
||||||
|
// ) {
|
||||||
|
// return self::onArticleChangeComplete($title);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static function onTitleMoveComplete(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// $title, $newTitle, $wgUser, $pageid, $redirid, $reason
|
||||||
|
// ) {
|
||||||
|
// return self::onArticleChangeComplete($title) ||
|
||||||
|
// self::onArticleChangeComplete($newTitle);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Prohibit creation of the pages that are part of our namespaces but have not been explicitly
|
||||||
|
// * allowed. Bad capitalization is due to "userCan" hook name
|
||||||
|
// * @param Title &$title
|
||||||
|
// * @param User &$user
|
||||||
|
// * @param String $action
|
||||||
|
// * @param null &$result
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public static function onuserCan(
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// &$title, &$user, $action, &$result = null
|
||||||
|
// ) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ($action == 'create' && self::parseTitle($title) == null) {
|
||||||
|
// // prohibit creation of the pages for the namespace that we handle,
|
||||||
|
// // if the title is not matching declared rules
|
||||||
|
// $result = false;
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param Object $value
|
||||||
|
// * @param JCContent $content
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// private static function onArticleChangeComplete($value, $content = null) {
|
||||||
|
// if (!self::jsonConfigIsStorage()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ($value && (!$content || is_a($content, 'JsonConfig\JCContent'))) {
|
||||||
|
// if (method_exists($value, 'getTitle')) {
|
||||||
|
// $value = $value->getTitle();
|
||||||
|
// }
|
||||||
|
// $jct = self::parseTitle($value);
|
||||||
|
// if ($jct && $jct->getConfig()->store) {
|
||||||
|
// $store = new JCCache($jct, $content);
|
||||||
|
// $store->resetCache();
|
||||||
|
//
|
||||||
|
// // Handle remote site notification
|
||||||
|
// $store = $jct->getConfig()->store;
|
||||||
|
// if ($store->notifyUrl) {
|
||||||
|
// $req =
|
||||||
|
// JCUtils::initApiRequestObj($store->notifyUrl, $store->notifyUsername,
|
||||||
|
// $store->notifyPassword);
|
||||||
|
// if ($req) {
|
||||||
|
// $query = [
|
||||||
|
// 'format' => 'json',
|
||||||
|
// 'action' => 'jsonconfig',
|
||||||
|
// 'command' => 'reload',
|
||||||
|
// 'title' => $jct->getNamespace() . ':' . $jct->getDBkey(),
|
||||||
|
// ];
|
||||||
|
// JCUtils::callApi($req, $query, 'notify remote JsonConfig client');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Quick check if the current wiki will store any configurations.
|
||||||
|
// * Faster than doing a full parsing of the $wgJsonConfigs in the JCSingleton::init()
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// private static function jsonConfigIsStorage() {
|
||||||
|
// static $isStorage = null;
|
||||||
|
// if ($isStorage == null) {
|
||||||
|
// global $wgJsonConfigs;
|
||||||
|
// $isStorage = false;
|
||||||
|
// $configs = array_replace_recursive(
|
||||||
|
// \ExtensionRegistry::getInstance()->getAttribute('JsonConfigs'),
|
||||||
|
// $wgJsonConfigs
|
||||||
|
// );
|
||||||
|
// foreach ($configs as $jc) {
|
||||||
|
// if ((!array_key_exists('isLocal', $jc) || $jc['isLocal']) ||
|
||||||
|
// (array_key_exists('store', $jc))
|
||||||
|
// ) {
|
||||||
|
// $isStorage = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return $isStorage;
|
||||||
|
// }
|
||||||
|
public static String Singleton_Id = "JCSingleton";
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
//namespace gplx.xowa.mediawiki.extensions.JsonConfig.includes {
|
||||||
|
// import org.junit.*;
|
||||||
|
// using gplx.langs.jsons;
|
||||||
|
// using gplx.xowa.mediawiki;
|
||||||
|
// using gplx.xowa.xtns.jsonConfigs.scribunto;
|
||||||
|
// public class JCSingleton_tst {
|
||||||
|
// private final JCSingleton_fxt fxt = new JCSingleton_fxt();
|
||||||
|
// @Test public void Get() {
|
||||||
|
// fxt.Init__store("en.wikipedia.org", "Page1"
|
||||||
|
// , Json_doc.Make_str_by_apos
|
||||||
|
// ( "{"
|
||||||
|
// , " 'data':"
|
||||||
|
// , " ["
|
||||||
|
// , " ["
|
||||||
|
// , " 'Q1'"
|
||||||
|
// , " , 'Data:Q1'"
|
||||||
|
// , " ]"
|
||||||
|
// , " ,"
|
||||||
|
// , " ["
|
||||||
|
// , " 'Q2'"
|
||||||
|
// , " , 'Data:Q2'"
|
||||||
|
// , " ]"
|
||||||
|
// , " ]"
|
||||||
|
// , "}"
|
||||||
|
// ));
|
||||||
|
// JCContent actl = fxt.Exec__getContent("en.wikipedia.org", "Page1");
|
||||||
|
// Object o = ((JCTabularContent)actl).getField("data");
|
||||||
|
// Tfds.Write(o);
|
||||||
|
// /*
|
||||||
|
// fxt.Test__get(actl, "data", "Q1")
|
||||||
|
// */
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// class JCSingleton_fxt {
|
||||||
|
// private final JCSingleton singleton;
|
||||||
|
// private final Xomw_page_fetcher__mock store = new Xomw_page_fetcher__mock();
|
||||||
|
// public JCSingleton_fxt() {
|
||||||
|
// Jscfg_xtn_mgr xtn_mgr = new Jscfg_xtn_mgr();
|
||||||
|
// xtn_mgr.Init_xtn();
|
||||||
|
//
|
||||||
|
// singleton = (JCSingleton)XophpEnv.Instance.Singletons().Get_by(JCSingleton.Singleton_Id);
|
||||||
|
// singleton.Store_(store);
|
||||||
|
// }
|
||||||
|
// public void Init__store(String wiki, String page, String json) {
|
||||||
|
// store.Set_wtxt(Bry_.new_u8(wiki), Bry_.new_u8(page), Bry_.new_u8(json));
|
||||||
|
// }
|
||||||
|
// public JCContent Exec__getContent(String wiki, String page) {
|
||||||
|
// return singleton.getContent(wiki, "unknown_ns", page);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.core.primitives.*;
|
||||||
|
import gplx.xowa.mediawiki.*;
|
||||||
|
import gplx.xowa.langs.*;
|
||||||
|
public class JCTabularContent extends JCDataContent {// protected function createDefaultView() {
|
||||||
|
// return new JCTabularContentView();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Returns wiki-table representation of the tabular data
|
||||||
|
// *
|
||||||
|
// * @return String|boolean The raw text, or false if the conversion failed.
|
||||||
|
// */
|
||||||
|
// public function getWikitextForTransclusion() {
|
||||||
|
// $toWiki = function ( $value ) {
|
||||||
|
// if ( is_object( $value ) ) {
|
||||||
|
// global $wgLang;
|
||||||
|
// $value = JCUtils::pickLocalizedString( $value, $wgLang );
|
||||||
|
// }
|
||||||
|
// if ( preg_match( '/^[ .\pL\pN]*$/i', $value ) ) {
|
||||||
|
// // Optimization: spaces, letters, numbers, and dots are returned without <nowiki>
|
||||||
|
// return $value;
|
||||||
|
// }
|
||||||
|
// return '<nowiki>' . htmlspecialchars( $value ) . '</nowiki>';
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// $data = $this->getData();
|
||||||
|
// $result = "{| class='wikitable sortable'\n";
|
||||||
|
//
|
||||||
|
// // Create header
|
||||||
|
// $result .= '!' . implode( "!!",
|
||||||
|
// array_map(
|
||||||
|
// function ( $field ) use ( $toWiki ) {
|
||||||
|
// return $toWiki( $field->title ? : $field->name );
|
||||||
|
// },
|
||||||
|
// $data->schema->fields
|
||||||
|
// )
|
||||||
|
// ) . "\n";
|
||||||
|
//
|
||||||
|
// // Create table content
|
||||||
|
// foreach ( $data->data as $row ) {
|
||||||
|
// $result .= "|-\n|" . implode( '||', array_map( $toWiki, $row ) ) . "\n";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $result .= "\n|}\n";
|
||||||
|
//
|
||||||
|
// return $result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived classes must implement this method to perform custom validation
|
||||||
|
* using the check(...) calls
|
||||||
|
*/
|
||||||
|
public void validateContent() {
|
||||||
|
// parent::validateContent();
|
||||||
|
//
|
||||||
|
// $validators = [ JCValidators::isList() ];
|
||||||
|
// $typeValidators = [];
|
||||||
|
// $fieldsPath = [ 'schema', 'fields' ];
|
||||||
|
// if ( $this->test( 'schema', JCValidators::isDictionary() ) &&
|
||||||
|
// $this->test( $fieldsPath, JCValidators::isList() ) &&
|
||||||
|
// $this->testEach( $fieldsPath, JCValidators::isDictionary() )
|
||||||
|
// ) {
|
||||||
|
// $hasError = false;
|
||||||
|
// $allHeaders = [];
|
||||||
|
// $fieldCount = count( $this->getField( $fieldsPath )->getValue() );
|
||||||
|
// for ( $idx = 0; $idx < $fieldCount; $idx++ ) {
|
||||||
|
// $header = false;
|
||||||
|
// $hasError |= !$this->test( [ 'schema', 'fields', $idx, 'name' ],
|
||||||
|
// JCValidators::isHeaderString( $allHeaders ),
|
||||||
|
// function ( JCValue $jcv ) use ( &$header ) {
|
||||||
|
// $header = $jcv->getValue();
|
||||||
|
// return true;
|
||||||
|
// } );
|
||||||
|
// $hasError |= !$this->test( [ 'schema', 'fields', $idx, 'type' ],
|
||||||
|
// JCValidators::validateDataType( $typeValidators ) );
|
||||||
|
// if ( $header ) {
|
||||||
|
// $hasError |= !$this->testOptional( [ 'schema', 'fields', $idx, 'title' ],
|
||||||
|
// function () use ( $header ) {
|
||||||
|
// return (Object)[ 'en' => $header ];
|
||||||
|
// }, JCValidators::isLocalizedString() );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// $countValidator = JCValidators::checkListSize( $fieldCount, 'schema/fields' );
|
||||||
|
// $validators[] = $countValidator;
|
||||||
|
//
|
||||||
|
// if ( !$hasError ) {
|
||||||
|
// $this->testEach( $fieldsPath, JCValidators::noExtraValues() );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// $this->test( 'schema', JCValidators::noExtraValues() );
|
||||||
|
//
|
||||||
|
// if ( !$this->thorough() ) {
|
||||||
|
// // We are not doing any modifications to the data, so no need to validate it
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $this->test( 'data', JCValidators::isList() );
|
||||||
|
// $this->test( [], JCValidators::noExtraValues() );
|
||||||
|
// $this->testEach( 'data', $validators );
|
||||||
|
// if ( $typeValidators ) {
|
||||||
|
// /** @noinspection PhpUnusedParameterInspection */
|
||||||
|
// $this->testEach( 'data', function ( JCValue $v, array $path ) use ( $typeValidators ) {
|
||||||
|
// $isOk = true;
|
||||||
|
// $lastIdx = count( $path );
|
||||||
|
// foreach ( array_keys( $typeValidators ) as $k ) {
|
||||||
|
// $path[$lastIdx] = $k;
|
||||||
|
// $isOk &= $this->test( $path, $typeValidators[$k] );
|
||||||
|
// }
|
||||||
|
// return $isOk;
|
||||||
|
// } );
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve @Override any specific localizations, and add it to $result
|
||||||
|
* @param Object $result
|
||||||
|
* @param Language $lang
|
||||||
|
*/
|
||||||
|
@Override protected void localizeData(XophpStdClass result, Xol_lang_itm lang) {
|
||||||
|
super.localizeData(result, lang);
|
||||||
|
|
||||||
|
XophpStdClass data = this.getData();
|
||||||
|
JCLocalizeItmFunc localize = new JCLocalizeItmFunc(lang);
|
||||||
|
|
||||||
|
Int_list isLocalized = new Int_list();
|
||||||
|
result.Set_by_as_itm("schema", new XophpStdClass());
|
||||||
|
|
||||||
|
XophpStdClass result_schema_flds = new XophpStdClass();
|
||||||
|
result.Set_by_as_itm(String_.Ary("schema", "fields"), result_schema_flds);
|
||||||
|
XophpStdClass flds = data.Get_by_ary_as_itm("schema", "fields");
|
||||||
|
int flds_len = flds.Len();
|
||||||
|
for (int ind = 0; ind < flds_len; ind++) {
|
||||||
|
XophpStdClass fld = flds.Get_at_as_itm(ind);
|
||||||
|
if (fld.Comp_str("type", "localized")) {
|
||||||
|
isLocalized.Add(ind);
|
||||||
|
}
|
||||||
|
XophpStdClass rslt_fld = new XophpStdClass();
|
||||||
|
rslt_fld.Set_by_as_str("name", fld.Get_by_as_str("name"));
|
||||||
|
rslt_fld.Set_by_as_str("type", fld.Get_by_as_str("type"));
|
||||||
|
rslt_fld.Set_by_as_str("title", fld.Has("title") ? localize.Localize(fld.Get_by_as_itm("title")) : fld.Get_by_as_str("name"));
|
||||||
|
result_schema_flds.Add_at_as_itm(rslt_fld);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLocalized.Len() == 0) {
|
||||||
|
// There are no localized strings in the data, optimize
|
||||||
|
result.Set_by_as_itm("data", data.Get_by_as_itm("data"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JCArrayFunc array_map_func = new JCArrayFunc();
|
||||||
|
result.Set_by_as_itm("data", array_map_func.Array_map(new JCLocalizeAryFunc(localize, isLocalized), data.Get_by_as_itm("data")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static final String Model_id = "JCTabularContent";
|
||||||
|
}
|
||||||
|
class JCArrayFunc {
|
||||||
|
public XophpStdClass Array_map(JCLocalizeAryFunc func, XophpStdClass src) {
|
||||||
|
XophpStdClass trg = new XophpStdClass();
|
||||||
|
int len = src.Len();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
XophpStdClass src_sub = src.Get_at_as_itm(i);
|
||||||
|
XophpStdClass trg_sub = func.Array_map(src_sub);
|
||||||
|
trg.Add_at_as_itm(trg_sub);
|
||||||
|
}
|
||||||
|
return trg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class JCLocalizeAryFunc {
|
||||||
|
private final JCLocalizeItmFunc localize;
|
||||||
|
private final Int_list isLocalized;
|
||||||
|
public JCLocalizeAryFunc(JCLocalizeItmFunc localize, Int_list isLocalized) {
|
||||||
|
this.localize = localize;
|
||||||
|
this.isLocalized = isLocalized;
|
||||||
|
}
|
||||||
|
public XophpStdClass Array_map(XophpStdClass row) {
|
||||||
|
int len = isLocalized.Len();
|
||||||
|
for (int ind = 0; ind < len; ind++) {
|
||||||
|
XophpStdClass val = row.Get_at_as_itm(ind);
|
||||||
|
if (val != null) {
|
||||||
|
row.Set_at_as_str(ind, localize.Localize(val)); // NOTE: will reduce a map to a String; EX: name={en='a',fr='b'} => name={'a'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class JCLocalizeItmFunc {
|
||||||
|
private final Xol_lang_itm lang;
|
||||||
|
public JCLocalizeItmFunc(Xol_lang_itm lang) {
|
||||||
|
this.lang = lang;
|
||||||
|
}
|
||||||
|
public String Localize(XophpStdClass val) {
|
||||||
|
return JCUtils.pickLocalizedString(val, lang);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.mediawiki.*;
|
||||||
|
public class JCTabularContentFactory implements XophpClassBldr {
|
||||||
|
public String Id() {return JCTabularContent.Model_id;}
|
||||||
|
public Object Make(Object... args) {
|
||||||
|
JCTabularContent rv = new JCTabularContent();
|
||||||
|
byte[] text = (byte[])args[0];
|
||||||
|
String modelId = (String)args[1];
|
||||||
|
boolean thorough = Bool_.Cast(args[2]);
|
||||||
|
rv.__construct(text, modelId, thorough);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.langs.*;
|
||||||
|
import gplx.xowa.mediawiki.*;
|
||||||
|
class JCUtils {
|
||||||
|
/**
|
||||||
|
* Find a message in a dictionary for the given language,
|
||||||
|
* or use language fallbacks if message is not defined.
|
||||||
|
* @param stdClass map Dictionary of languageCode => String
|
||||||
|
* @param Language|StubUserLang lang language Object
|
||||||
|
* @param boolean|String $defaultValue if non-false, use this value in case no fallback and no 'en'
|
||||||
|
* @return String message from the dictionary or "" if nothing found
|
||||||
|
*/
|
||||||
|
public static String pickLocalizedString(XophpStdClass map, Xol_lang_itm lang) {return pickLocalizedString(map, lang, null);}
|
||||||
|
public static String pickLocalizedString(XophpStdClass map, Xol_lang_itm lang, String defaultValue) {
|
||||||
|
String langCode = lang.Key_str();
|
||||||
|
if (map.Has(langCode)) {
|
||||||
|
return map.Get_by_as_str(langCode);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
for+each (lang.getFallbackLanguages() as l) {
|
||||||
|
if (property_exists(map, l)) {
|
||||||
|
return map.l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If fallbacks fail, check if english is defined
|
||||||
|
if (map.Has("en") ) {
|
||||||
|
return map.Get_by_as_str("en");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a custom default, return that
|
||||||
|
if (defaultValue != null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return first available value, or an empty String
|
||||||
|
// There might be a better way to get the first value from an Object
|
||||||
|
return map.Len() == 0 ? "" : map.Get_at_as_str(0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
import gplx.xowa.xtns.scribunto.*;
|
||||||
|
import gplx.xowa.mediawiki.*;
|
||||||
|
public class JCValue {
|
||||||
|
private Ordered_hash value = Ordered_hash_.New();
|
||||||
|
private int statusVal;
|
||||||
|
private XophpStdClass value_as_obj;
|
||||||
|
private Xophp_ary value_as_ary;
|
||||||
|
private Object value_as_prim;
|
||||||
|
private int value_tid;
|
||||||
|
private boolean sameAsDefaultVal = false;
|
||||||
|
private boolean defaultUsedVal = false;
|
||||||
|
private Object errorVal = null;
|
||||||
|
|
||||||
|
private static final int NULL = -1;
|
||||||
|
|
||||||
|
/** Value has not been checked */
|
||||||
|
public static final int UNCHECKED = 0;
|
||||||
|
/** Value was explicitly checked (might be an error) */
|
||||||
|
// private static final int CHECKED = 1;
|
||||||
|
/** field is missing in the data, but is being explicitly tested for.
|
||||||
|
* This value should never be stored in JCObjContent::validationData.
|
||||||
|
* Setting this value for any field in validator will delete it. */
|
||||||
|
private static final int MISSING = 2;
|
||||||
|
/** field was not explicitly tested, but it was listed as a parent of one of the tested fields */
|
||||||
|
// private static final int VISITED = 3;
|
||||||
|
|
||||||
|
private static final int Value_tid__obj = 1, Value_tid__ary = 2, Value_tid__prim = 3;
|
||||||
|
|
||||||
|
/** @param int status
|
||||||
|
* @param mixed value
|
||||||
|
*/
|
||||||
|
public JCValue(int status, XophpStdClass value_as_obj, Xophp_ary value_as_ary, Object value_as_prim) {
|
||||||
|
this.statusVal = status;
|
||||||
|
this.value_as_obj = value_as_obj;
|
||||||
|
this.value_as_ary = value_as_ary;
|
||||||
|
this.value_as_prim = value_as_prim;
|
||||||
|
if (value_as_obj != null) {
|
||||||
|
value_tid = Value_tid__obj;
|
||||||
|
}
|
||||||
|
else if (value_as_ary != null) {
|
||||||
|
value_tid = Value_tid__ary;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value_tid = Value_tid__prim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return mixed */
|
||||||
|
public Object getValue() {
|
||||||
|
switch (value_tid) {
|
||||||
|
case Value_tid__obj:
|
||||||
|
return value_as_obj;
|
||||||
|
case Value_tid__ary:
|
||||||
|
return value_as_ary;
|
||||||
|
case Value_tid__prim:
|
||||||
|
return value_as_prim;
|
||||||
|
default:
|
||||||
|
throw Err_.new_unhandled_default(value_tid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Ordered_hash value) {this.setValue(value, NULL);}
|
||||||
|
public void setValue(Ordered_hash value, int status) {
|
||||||
|
this.value = value;
|
||||||
|
if (status != NULL) {
|
||||||
|
this.status(status);
|
||||||
|
} else if (this.isMissing()) {
|
||||||
|
// Convenience - if we are setting a new value, assume we are setting a default
|
||||||
|
this.status(JCValue.UNCHECKED);
|
||||||
|
this.defaultUsed(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int status() {return status(NULL);}
|
||||||
|
public int status(int o) {
|
||||||
|
int val = this.statusVal;
|
||||||
|
if (o != NULL) {
|
||||||
|
this.statusVal = o;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sameAsDefault() {return sameAsDefault(null);}
|
||||||
|
public boolean sameAsDefault(Object o) {
|
||||||
|
boolean val = this.sameAsDefaultVal;
|
||||||
|
if (o != null) {
|
||||||
|
this.sameAsDefaultVal = Bool_.Cast(o);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean defaultUsed() {return defaultUsed(null);}
|
||||||
|
public boolean defaultUsed(Object o) {
|
||||||
|
boolean val = this.defaultUsedVal;
|
||||||
|
if (o != null) {
|
||||||
|
this.defaultUsedVal = Bool_.Cast(o);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMissing() {
|
||||||
|
return this.statusVal == JCValue.MISSING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUnchecked() {
|
||||||
|
return this.statusVal == JCValue.UNCHECKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Helper function - same arguments as wfMessage, or true if message was already added.
|
||||||
|
* false clears this message status, and null returns current state without changing it
|
||||||
|
* @param null|boolean|String $key message id, or if boolean, sets/removes error status
|
||||||
|
* @param array $fieldPath path to the erroneous field. Will be converted to a a/b/c[0]/d style
|
||||||
|
* @return boolean|Message
|
||||||
|
*/
|
||||||
|
// public String error($key = null, $fieldPath = null /*...*/)
|
||||||
|
public Object error(Object key, String... fieldPath) {
|
||||||
|
if (Type_.Type_by_obj(key) == Bool_.Cls_ref_type) {
|
||||||
|
this.errorVal = Bool_.Cast(key);
|
||||||
|
}
|
||||||
|
else if (key != null) {
|
||||||
|
// $args = func_get_args();
|
||||||
|
// if (is_array($fieldPath)) {
|
||||||
|
// // Convert field path to a printable String
|
||||||
|
// $args[1] = JCUtils::fieldPathToString($fieldPath);
|
||||||
|
// }
|
||||||
|
// $this.errorVal = call_user_func_array('wfMessage', $args);
|
||||||
|
}
|
||||||
|
return this.errorVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param String|int $fld
|
||||||
|
* @param mixed value
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void setField(Object fld, Object o) {
|
||||||
|
int fld_type = To_type_id(fld);
|
||||||
|
if (value_tid == Value_tid__obj && fld_type == Type_ids_.Id__str) {
|
||||||
|
value_as_obj.Add_by_as_obj((String)fld, o);
|
||||||
|
}
|
||||||
|
else if (value_tid == Value_tid__ary && (fld_type == Type_ids_.Id__str || fld_type == Type_ids_.Id__int)) {
|
||||||
|
if (fld_type == Type_ids_.Id__str)
|
||||||
|
value_as_ary.Add((String)fld, o);
|
||||||
|
else
|
||||||
|
value_as_ary.Add(Int_.Cast(fld), o);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw Err_.new_wo_type("Type mismatch for field " + fld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param String|int $fld
|
||||||
|
* @throws \Exception
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public Object deleteField(Object fld) {
|
||||||
|
int fld_type = To_type_id(fld);
|
||||||
|
Object tmp = null;
|
||||||
|
if (value_tid == Value_tid__obj && fld_type == Type_ids_.Id__str) {
|
||||||
|
String key = (String)fld;
|
||||||
|
tmp = value_as_obj.Get_by_as_obj(key);
|
||||||
|
value_as_obj.Del_by(key);
|
||||||
|
}
|
||||||
|
else if (value_tid == Value_tid__ary && (fld_type == Type_ids_.Id__str || fld_type == Type_ids_.Id__int)) {
|
||||||
|
tmp = value_as_ary.Get(fld);
|
||||||
|
if (fld_type == Type_ids_.Id__str)
|
||||||
|
value_as_ary.Unset((String)fld);
|
||||||
|
else
|
||||||
|
value_as_ary.Unset(Int_.Cast(fld));
|
||||||
|
value.Del(fld);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw Err_.new_wo_type("Type mismatch for field " + fld);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param String|int $fld
|
||||||
|
* @throws \Exception
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean fieldExists(Object fld) {
|
||||||
|
int fld_type = To_type_id(fld);
|
||||||
|
if (value_tid == Value_tid__obj && fld_type == Type_ids_.Id__str) {
|
||||||
|
return value_as_obj.Has((String)fld);
|
||||||
|
}
|
||||||
|
else if (value_tid == Value_tid__ary && (fld_type == Type_ids_.Id__str || fld_type == Type_ids_.Id__int)) {
|
||||||
|
return value_as_ary.Has(fld);
|
||||||
|
}
|
||||||
|
throw Err_.new_wo_type("Type mismatch for field " + fld);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param String|int $fld
|
||||||
|
* @throws \Exception
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public Object getField(Object fld) {
|
||||||
|
int fld_type = To_type_id(fld);
|
||||||
|
if (value_tid == Value_tid__obj && fld_type == Type_ids_.Id__str) {
|
||||||
|
return value_as_obj.Get_by_as_obj((String)fld);
|
||||||
|
}
|
||||||
|
else if (value_tid == Value_tid__ary && (fld_type == Type_ids_.Id__str || fld_type == Type_ids_.Id__int)) {
|
||||||
|
return value_as_ary.Get(fld);
|
||||||
|
}
|
||||||
|
throw Err_.new_wo_type("Type mismatch for field " + fld);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int To_type_id(Object o) {
|
||||||
|
Class<?> type = Type_.Type_by_obj(o);
|
||||||
|
if (Type_.Eq(type, String.class))
|
||||||
|
return Type_ids_.Id__str;
|
||||||
|
else if (Type_.Eq(type, int.class))
|
||||||
|
return Type_ids_.Id__int;
|
||||||
|
else
|
||||||
|
return Type_ids_.Id__null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class XomwTypeUtl {
|
||||||
|
public static int To_type_id(Object o) {
|
||||||
|
if (o == null)
|
||||||
|
return Type_ids_.Id__null;
|
||||||
|
Class<?> type = Type_.Type_by_obj(o);
|
||||||
|
if (Type_.Eq(type, String.class))
|
||||||
|
return Type_ids_.Id__str;
|
||||||
|
else if (Type_.Eq(type, int.class))
|
||||||
|
return Type_ids_.Id__int;
|
||||||
|
else if (Type_.Is_array(type))
|
||||||
|
return Type_ids_.Id__array;
|
||||||
|
else
|
||||||
|
return Type_ids_.Id__obj;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
public class XomwStatus {
|
||||||
|
public boolean isGood() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.extensions.JsonConfig.includes; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.JsonConfig.*;
|
||||||
|
public interface Xomw_page_fetcher {
|
||||||
|
byte[] Get_wtxt(byte[] wiki, byte[] page);
|
||||||
|
}
|
||||||
|
class Xomw_page_fetcher__mock implements Xomw_page_fetcher {
|
||||||
|
private final Ordered_hash hash = Ordered_hash_.New_bry();
|
||||||
|
public void Set_wtxt(byte[] wiki, byte[] page, byte[] wtxt) {
|
||||||
|
hash.Add(Make_key(wiki, page), wtxt);
|
||||||
|
}
|
||||||
|
public byte[] Get_wtxt(byte[] wiki, byte[] page) {
|
||||||
|
return (byte[])hash.Get_by(Make_key(wiki, page));
|
||||||
|
}
|
||||||
|
private static byte[] Make_key(byte[] wiki, byte[] page) {
|
||||||
|
return Bry_.Add(wiki, Byte_ascii.Pipe_bry, page);
|
||||||
|
}
|
||||||
|
}
|
@ -261,20 +261,20 @@ public class XomwDefines {
|
|||||||
// define( 'PROTO_INTERNAL', 2 );
|
// define( 'PROTO_INTERNAL', 2 );
|
||||||
// /**@}*/
|
// /**@}*/
|
||||||
//
|
//
|
||||||
// /**@{
|
/**@{
|
||||||
// * Content model ids, used by Content and ContentHandler.
|
* Content model ids, used by Content and ContentHandler.
|
||||||
// * These IDs will be exposed in the API and XML dumps.
|
* These IDs will be exposed in the API and XML dumps.
|
||||||
// *
|
*
|
||||||
// * Extensions that define their own content model IDs should take
|
* Extensions that define their own content model IDs should take
|
||||||
// * care to avoid conflicts. Using the extension name as a prefix is recommended,
|
* care to avoid conflicts. Using the extension name as a prefix is recommended,
|
||||||
// * for example 'myextension-somecontent'.
|
* for example 'myextension-somecontent'.
|
||||||
// */
|
*/
|
||||||
// define( 'CONTENT_MODEL_WIKITEXT', 'wikitext' );
|
public static final String CONTENT_MODEL_WIKITEXT = "wikitext";
|
||||||
// define( 'CONTENT_MODEL_JAVASCRIPT', 'javascript' );
|
public static final String CONTENT_MODEL_JAVASCRIPT = "javascript";
|
||||||
// define( 'CONTENT_MODEL_CSS', 'css' );
|
public static final String CONTENT_MODEL_CSS = "css";
|
||||||
// define( 'CONTENT_MODEL_TEXT', 'text' );
|
public static final String CONTENT_MODEL_TEXT = "text";
|
||||||
// define( 'CONTENT_MODEL_JSON', 'json' );
|
public static final String CONTENT_MODEL_JSON = "json";
|
||||||
// /**@}*/
|
/**@}*/
|
||||||
|
|
||||||
/**@{
|
/**@{
|
||||||
* Content formats, used by Content and ContentHandler.
|
* Content formats, used by Content and ContentHandler.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.includes.content; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
|
||||||
|
public class TextContent {
|
||||||
|
// AbstractContent
|
||||||
|
/**
|
||||||
|
* @since 1.21
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*
|
||||||
|
* @see Content::isRedirect
|
||||||
|
*/
|
||||||
|
// public function isRedirect() {
|
||||||
|
// return $this->getRedirectTarget() !== null;
|
||||||
|
// }
|
||||||
|
public boolean isRedirect() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] mText;
|
||||||
|
/**
|
||||||
|
* @param String $text
|
||||||
|
* @param String $model_id
|
||||||
|
* @throws MWException
|
||||||
|
*/
|
||||||
|
public void __construct(byte[] text, String model_id) { // = CONTENT_MODEL_TEXT
|
||||||
|
// parent::__construct( $model_id );
|
||||||
|
//
|
||||||
|
// if ( $text === null || $text === false ) {
|
||||||
|
// wfWarn( "TextContent constructed with \$text = " . var_export( $text, true ) . "! "
|
||||||
|
// . "This may indicate an error in the caller's scope.", 2 );
|
||||||
|
//
|
||||||
|
// $text = '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ( !is_string( $text ) ) {
|
||||||
|
// throw new MWException( "TextContent expects a String in the constructor." );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
this.mText = text;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @note Mutable subclasses MUST override this to return a copy!
|
||||||
|
// *
|
||||||
|
// * @return Content this
|
||||||
|
// */
|
||||||
|
// public function copy() {
|
||||||
|
// return this; # NOTE: this is ok since TextContent are immutable.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function getTextForSummary( $maxlength = 250 ) {
|
||||||
|
// global $wgContLang;
|
||||||
|
//
|
||||||
|
// $text = this.getNativeData();
|
||||||
|
//
|
||||||
|
// $truncatedtext = $wgContLang.truncate(
|
||||||
|
// preg_replace( "/[\n\r]/", ' ', $text ),
|
||||||
|
// max( 0, $maxlength ) );
|
||||||
|
//
|
||||||
|
// return $truncatedtext;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns the text's size in bytes.
|
||||||
|
// *
|
||||||
|
// * @return int
|
||||||
|
// */
|
||||||
|
// public function getSize() {
|
||||||
|
// $text = this.getNativeData();
|
||||||
|
//
|
||||||
|
// return strlen( $text );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns true if this content is not a redirect, and $wgArticleCountMethod
|
||||||
|
// * is "any".
|
||||||
|
// *
|
||||||
|
// * @param boolean|null $hasLinks If it is known whether this content contains links,
|
||||||
|
// * provide this information here, to avoid redundant parsing to find out.
|
||||||
|
// *
|
||||||
|
// * @return boolean
|
||||||
|
// */
|
||||||
|
// public function isCountable( $hasLinks = null ) {
|
||||||
|
// global $wgArticleCountMethod;
|
||||||
|
//
|
||||||
|
// if ( this.isRedirect() ) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ( $wgArticleCountMethod === 'any' ) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the text represented by this Content Object, as a String.
|
||||||
|
*
|
||||||
|
* @return String The raw text.
|
||||||
|
*/
|
||||||
|
public byte[] getNativeData() {
|
||||||
|
return this.mText;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Returns the text represented by this Content Object, as a String.
|
||||||
|
// *
|
||||||
|
// * @return String The raw text.
|
||||||
|
// */
|
||||||
|
// public function getTextForSearchIndex() {
|
||||||
|
// return this.getNativeData();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns attempts to convert this content Object to wikitext,
|
||||||
|
// * and then returns the text String. The conversion may be lossy.
|
||||||
|
// *
|
||||||
|
// * @note this allows any text-based content to be transcluded as if it was wikitext.
|
||||||
|
// *
|
||||||
|
// * @return String|boolean The raw text, or false if the conversion failed.
|
||||||
|
// */
|
||||||
|
// public function getWikitextForTransclusion() {
|
||||||
|
// $wikitext = this.convert( CONTENT_MODEL_WIKITEXT, 'lossy' );
|
||||||
|
//
|
||||||
|
// if ( $wikitext ) {
|
||||||
|
// return $wikitext.getNativeData();
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Do a "\r\n" . "\n" and "\r" . "\n" transformation
|
||||||
|
// * as well as trim trailing whitespace
|
||||||
|
// *
|
||||||
|
// * This was formerly part of Parser::preSaveTransform, but
|
||||||
|
// * for non-wikitext content models they probably still want
|
||||||
|
// * to normalize line endings without all of the other PST
|
||||||
|
// * changes.
|
||||||
|
// *
|
||||||
|
// * @since 1.28
|
||||||
|
// * @param $text
|
||||||
|
// * @return String
|
||||||
|
// */
|
||||||
|
// public static function normalizeLineEndings( $text ) {
|
||||||
|
// return str_replace( [ "\r\n", "\r" ], "\n", rtrim( $text ) );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns a Content Object with pre-save transformations applied.
|
||||||
|
// *
|
||||||
|
// * At a minimum, subclasses should make sure to call TextContent::normalizeLineEndings()
|
||||||
|
// * either directly or part of Parser::preSaveTransform().
|
||||||
|
// *
|
||||||
|
// * @param Title $title
|
||||||
|
// * @param User $user
|
||||||
|
// * @param ParserOptions $popts
|
||||||
|
// *
|
||||||
|
// * @return Content
|
||||||
|
// */
|
||||||
|
// public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
|
||||||
|
// $text = this.getNativeData();
|
||||||
|
// $pst = self::normalizeLineEndings( $text );
|
||||||
|
//
|
||||||
|
// return ( $text === $pst ) ? this : new static( $pst, this.getModel() );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Diff this content Object with another content Object.
|
||||||
|
// *
|
||||||
|
// * @since 1.21
|
||||||
|
// *
|
||||||
|
// * @param Content $that The other content Object to compare this content Object to.
|
||||||
|
// * @param Language $lang The language Object to use for text segmentation.
|
||||||
|
// * If not given, $wgContentLang is used.
|
||||||
|
// *
|
||||||
|
// * @return Diff A diff representing the changes that would have to be
|
||||||
|
// * made to this content Object to make it equal to $that.
|
||||||
|
// */
|
||||||
|
// public function diff( Content $that, Language $lang = null ) {
|
||||||
|
// global $wgContLang;
|
||||||
|
//
|
||||||
|
// this.checkModelID( $that.getModel() );
|
||||||
|
//
|
||||||
|
// // @todo could implement this in DifferenceEngine and just delegate here?
|
||||||
|
//
|
||||||
|
// if ( !$lang ) {
|
||||||
|
// $lang = $wgContLang;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $otext = this.getNativeData();
|
||||||
|
// $ntext = $that.getNativeData();
|
||||||
|
//
|
||||||
|
// # Note: Use native PHP diff, external engines don't give us abstract output
|
||||||
|
// $ota = explode( "\n", $lang.segmentForDiff( $otext ) );
|
||||||
|
// $nta = explode( "\n", $lang.segmentForDiff( $ntext ) );
|
||||||
|
//
|
||||||
|
// $diff = new Diff( $ota, $nta );
|
||||||
|
//
|
||||||
|
// return $diff;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Fills the provided ParserOutput Object with information derived from the content.
|
||||||
|
// * Unless $generateHtml was false, this includes an HTML representation of the content
|
||||||
|
// * provided by getHtml().
|
||||||
|
// *
|
||||||
|
// * For content models listed in $wgTextModelsToParse, this method will call the MediaWiki
|
||||||
|
// * wikitext parser on the text to extract any (wikitext) links, magic words, etc.
|
||||||
|
// *
|
||||||
|
// * Subclasses may override this to provide custom content processing.
|
||||||
|
// * For custom HTML generation alone, it is sufficient to override getHtml().
|
||||||
|
// *
|
||||||
|
// * @param Title $title Context title for parsing
|
||||||
|
// * @param int $revId Revision ID (for {{REVISIONID}})
|
||||||
|
// * @param ParserOptions $options Parser options
|
||||||
|
// * @param boolean $generateHtml Whether or not to generate HTML
|
||||||
|
// * @param ParserOutput $output The output Object to fill (reference).
|
||||||
|
// */
|
||||||
|
// protected function fillParserOutput( Title $title, $revId,
|
||||||
|
// ParserOptions $options, $generateHtml, ParserOutput &$output
|
||||||
|
// ) {
|
||||||
|
// global $wgParser, $wgTextModelsToParse;
|
||||||
|
//
|
||||||
|
// if ( in_array( this.getModel(), $wgTextModelsToParse ) ) {
|
||||||
|
// // parse just to get links etc into the database, HTML is replaced below.
|
||||||
|
// $output = $wgParser.parse( this.getNativeData(), $title, $options, true, true, $revId );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ( $generateHtml ) {
|
||||||
|
// $html = this.getHtml();
|
||||||
|
// } else {
|
||||||
|
// $html = '';
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $output.setText( $html );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Generates an HTML version of the content, for display. Used by
|
||||||
|
// * fillParserOutput() to provide HTML for the ParserOutput Object.
|
||||||
|
// *
|
||||||
|
// * Subclasses may override this to provide a custom HTML rendering.
|
||||||
|
// * If further information is to be derived from the content (such as
|
||||||
|
// * categories), the fillParserOutput() method can be overridden instead.
|
||||||
|
// *
|
||||||
|
// * For backwards-compatibility, this default implementation just calls
|
||||||
|
// * getHighlightHtml().
|
||||||
|
// *
|
||||||
|
// * @return String An HTML representation of the content
|
||||||
|
// */
|
||||||
|
// protected function getHtml() {
|
||||||
|
// return this.getHighlightHtml();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Generates an HTML version of the content, for display.
|
||||||
|
// *
|
||||||
|
// * This default implementation returns an HTML-escaped version
|
||||||
|
// * of the raw text content.
|
||||||
|
// *
|
||||||
|
// * @note The functionality of this method should really be implemented
|
||||||
|
// * in getHtml(), and subclasses should override getHtml() if needed.
|
||||||
|
// * getHighlightHtml() is kept around for backward compatibility with
|
||||||
|
// * extensions that already override it.
|
||||||
|
// *
|
||||||
|
// * @deprecated since 1.24. Use getHtml() instead. In particular, subclasses overriding
|
||||||
|
// * getHighlightHtml() should override getHtml() instead.
|
||||||
|
// *
|
||||||
|
// * @return String An HTML representation of the content
|
||||||
|
// */
|
||||||
|
// protected function getHighlightHtml() {
|
||||||
|
// return htmlspecialchars( this.getNativeData() );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * This implementation provides lossless conversion between content models based
|
||||||
|
// * on TextContent.
|
||||||
|
// *
|
||||||
|
// * @param String $toModel The desired content model, use the CONTENT_MODEL_XXX flags.
|
||||||
|
// * @param String $lossy Flag, set to "lossy" to allow lossy conversion. If lossy conversion is not
|
||||||
|
// * allowed, full round-trip conversion is expected to work without losing information.
|
||||||
|
// *
|
||||||
|
// * @return Content|boolean A content Object with the content model $toModel, or false if that
|
||||||
|
// * conversion is not supported.
|
||||||
|
// *
|
||||||
|
// * @see Content::convert()
|
||||||
|
// */
|
||||||
|
// public function convert( $toModel, $lossy = '' ) {
|
||||||
|
// $converted = parent::convert( $toModel, $lossy );
|
||||||
|
//
|
||||||
|
// if ( $converted !== false ) {
|
||||||
|
// return $converted;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $toHandler = ContentHandler::getForModelID( $toModel );
|
||||||
|
//
|
||||||
|
// if ( $toHandler instanceof TextContentHandler ) {
|
||||||
|
// // NOTE: ignore content serialization format - it's just text anyway.
|
||||||
|
// $text = this.getNativeData();
|
||||||
|
// $converted = $toHandler.unserializeContent( $text );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return $converted;
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
XOWA: the XOWA Offline Wiki Application
|
||||||
|
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||||
|
|
||||||
|
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||||
|
or alternatively under the terms of the Apache License Version 2.0.
|
||||||
|
|
||||||
|
You may use XOWA according to either of these licenses as is most appropriate
|
||||||
|
for your project on a case-by-case basis.
|
||||||
|
|
||||||
|
The terms of each license can be found in the source code repository:
|
||||||
|
|
||||||
|
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||||
|
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||||
|
*/
|
||||||
|
package gplx.xowa.mediawiki.includes.content; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
|
||||||
|
public class TextContentHandler extends ContentHandler { // @codingStandardsIgnoreStart bug 57585
|
||||||
|
public void __construct() {this.__construct(XomwDefines.CONTENT_MODEL_TEXT, XomwDefines.CONTENT_FORMAT_TEXT);}
|
||||||
|
@Override public void __construct(String modelId, String... formats) {
|
||||||
|
super.__construct(modelId, formats);
|
||||||
|
}
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns the content's text as-is.
|
||||||
|
// *
|
||||||
|
// * @param Content $content
|
||||||
|
// * @param String $format The serialization format to check
|
||||||
|
// *
|
||||||
|
// * @return mixed
|
||||||
|
// */
|
||||||
|
// public function serializeContent(Content $content, $format = null) {
|
||||||
|
// $this->checkFormat($format);
|
||||||
|
//
|
||||||
|
// return $content->getNativeData();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Attempts to merge differences between three versions. Returns a new
|
||||||
|
// * Content Object for a clean merge and false for failure or a conflict.
|
||||||
|
// *
|
||||||
|
// * All three Content objects passed as parameters must have the same
|
||||||
|
// * content model.
|
||||||
|
// *
|
||||||
|
// * This text-based implementation uses wfMerge().
|
||||||
|
// *
|
||||||
|
// * @param Content $oldContent The page's previous content.
|
||||||
|
// * @param Content $myContent One of the page's conflicting contents.
|
||||||
|
// * @param Content $yourContent One of the page's conflicting contents.
|
||||||
|
// *
|
||||||
|
// * @return Content|boolean
|
||||||
|
// */
|
||||||
|
// public function merge3(Content $oldContent, Content $myContent, Content $yourContent) {
|
||||||
|
// $this->checkModelID($oldContent->getModel());
|
||||||
|
// $this->checkModelID($myContent->getModel());
|
||||||
|
// $this->checkModelID($yourContent->getModel());
|
||||||
|
//
|
||||||
|
// $format = $this->getDefaultFormat();
|
||||||
|
//
|
||||||
|
// $old = $this->serializeContent($oldContent, $format);
|
||||||
|
// $mine = $this->serializeContent($myContent, $format);
|
||||||
|
// $yours = $this->serializeContent($yourContent, $format);
|
||||||
|
//
|
||||||
|
// $ok = wfMerge($old, $mine, $yours, $result);
|
||||||
|
//
|
||||||
|
// if (!$ok) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!$result) {
|
||||||
|
// return $this->makeEmptyContent();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $mergedContent = $this->unserializeContent($result, $format);
|
||||||
|
//
|
||||||
|
// return $mergedContent;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns the name of the associated Content class, to
|
||||||
|
// * be used when creating new objects. Override expected
|
||||||
|
// * by subclasses.
|
||||||
|
// *
|
||||||
|
// * @since 1.24
|
||||||
|
// *
|
||||||
|
// * @return String
|
||||||
|
// */
|
||||||
|
// protected function getContentClass() {
|
||||||
|
// return TextContent::class;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Unserializes a Content Object of the type supported by this ContentHandler.
|
||||||
|
// *
|
||||||
|
// * @since 1.21
|
||||||
|
// *
|
||||||
|
// * @param String $text Serialized form of the content
|
||||||
|
// * @param String $format The format used for serialization
|
||||||
|
// *
|
||||||
|
// * @return Content The TextContent Object wrapping $text
|
||||||
|
// */
|
||||||
|
// public function unserializeContent($text, $format = null) {
|
||||||
|
// $this->checkFormat($format);
|
||||||
|
//
|
||||||
|
// $class = $this->getContentClass();
|
||||||
|
// return new $class($text);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Creates an empty TextContent Object.
|
||||||
|
// *
|
||||||
|
// * @since 1.21
|
||||||
|
// *
|
||||||
|
// * @return Content A new TextContent Object with empty text.
|
||||||
|
// */
|
||||||
|
// public function makeEmptyContent() {
|
||||||
|
// $class = $this->getContentClass();
|
||||||
|
// return new $class('');
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @see ContentHandler::supportsDirectEditing
|
||||||
|
// *
|
||||||
|
// * @return boolean Default is true for TextContent and derivatives.
|
||||||
|
// */
|
||||||
|
// public function supportsDirectEditing() {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function getFieldsForSearchIndex(SearchEngine $engine) {
|
||||||
|
// $fields = parent::getFieldsForSearchIndex($engine);
|
||||||
|
// $fields['language'] =
|
||||||
|
// $engine->makeSearchFieldMapping('language', SearchIndexField::INDEX_TYPE_KEYWORD);
|
||||||
|
//
|
||||||
|
// return $fields;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public function getDataForSearchIndex(WikiPage $page, ParserOutput $output,
|
||||||
|
// SearchEngine $engine) {
|
||||||
|
// $fields = parent::getDataForSearchIndex($page, $output, $engine);
|
||||||
|
// $fields['language'] =
|
||||||
|
// $this->getPageLanguage($page->getTitle(), $page->getContent())->getCode();
|
||||||
|
// return $fields;
|
||||||
|
// }
|
||||||
|
}
|
@ -41,7 +41,7 @@ public class XomwInterwikiLookupAdapter implements XomwInterwikiLookup {
|
|||||||
* @return boolean Whether it exists
|
* @return boolean Whether it exists
|
||||||
*/
|
*/
|
||||||
public boolean isValidInterwiki(byte[] prefix) {
|
public boolean isValidInterwiki(byte[] prefix) {
|
||||||
return XophpArray.array_key_exists(prefix, this.getInterwikiMap());
|
return XophpArrayUtl.array_key_exists(prefix, this.getInterwikiMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,7 +71,7 @@ public class XomwInterwikiLookupAdapter implements XomwInterwikiLookup {
|
|||||||
*/
|
*/
|
||||||
public byte[][] getAllPrefixes(boolean local) {
|
public byte[][] getAllPrefixes(boolean local) {
|
||||||
if (!local) {
|
if (!local) {
|
||||||
XophpArray.array_keys_bry(this.getInterwikiMap());
|
XophpArrayUtl.array_keys_bry(this.getInterwikiMap());
|
||||||
}
|
}
|
||||||
List_adp res = List_adp_.New();
|
List_adp res = List_adp_.New();
|
||||||
Ordered_hash hash = this.getInterwikiMap();
|
Ordered_hash hash = this.getInterwikiMap();
|
||||||
|
@ -48,13 +48,13 @@ public class Xomw_table_wkr implements gplx.core.brys.Bry_split_wkr {// THREAD.U
|
|||||||
|
|
||||||
// Closing open td, tr && table
|
// Closing open td, tr && table
|
||||||
while (td_history.Len() > 0) {
|
while (td_history.Len() > 0) {
|
||||||
if (XophpArray.popBoolOrN(td_history)) {
|
if (XophpArrayUtl.popBoolOrN(td_history)) {
|
||||||
bfr.Add_str_a7("</td>\n");
|
bfr.Add_str_a7("</td>\n");
|
||||||
}
|
}
|
||||||
if (XophpArray.popBoolOrN(tr_history)) {
|
if (XophpArrayUtl.popBoolOrN(tr_history)) {
|
||||||
bfr.Add_str_a7("</tr>\n");
|
bfr.Add_str_a7("</tr>\n");
|
||||||
}
|
}
|
||||||
if (!XophpArray.popBoolOrN(has_opened_tr)) {
|
if (!XophpArrayUtl.popBoolOrN(has_opened_tr)) {
|
||||||
bfr.Add_str_a7("<tr><td></td></tr>\n");
|
bfr.Add_str_a7("<tr><td></td></tr>\n");
|
||||||
}
|
}
|
||||||
bfr.Add_str_a7("</table>\n");
|
bfr.Add_str_a7("</table>\n");
|
||||||
@ -123,20 +123,20 @@ public class Xomw_table_wkr implements gplx.core.brys.Bry_split_wkr {// THREAD.U
|
|||||||
else if (Bry_.Eq(first_2, Wtxt__tb__end)) {
|
else if (Bry_.Eq(first_2, Wtxt__tb__end)) {
|
||||||
// We are ending a table
|
// We are ending a table
|
||||||
line = tmp.Add_str_a7("</table>").Add_mid(line, 2, line.length).To_bry_and_clear();
|
line = tmp.Add_str_a7("</table>").Add_mid(line, 2, line.length).To_bry_and_clear();
|
||||||
byte[] last_tag = XophpArray.popBryOrNull(last_tag_history);
|
byte[] last_tag = XophpArrayUtl.popBryOrNull(last_tag_history);
|
||||||
|
|
||||||
if (!XophpArray.popBoolOrN(has_opened_tr)) {
|
if (!XophpArrayUtl.popBoolOrN(has_opened_tr)) {
|
||||||
line = tmp.Add_str_a7("<tr><td></td></tr>").Add(line).To_bry_and_clear();
|
line = tmp.Add_str_a7("<tr><td></td></tr>").Add(line).To_bry_and_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XophpArray.popBoolOrN(tr_history)) {
|
if (XophpArrayUtl.popBoolOrN(tr_history)) {
|
||||||
line = tmp.Add_str_a7("</tr>").Add(line).To_bry_and_clear();
|
line = tmp.Add_str_a7("</tr>").Add(line).To_bry_and_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XophpArray.popBoolOrN(td_history)) {
|
if (XophpArrayUtl.popBoolOrN(td_history)) {
|
||||||
line = tmp.Add_str_a7("</").Add(last_tag).Add_byte(Byte_ascii.Angle_end).Add(line).To_bry_and_clear();
|
line = tmp.Add_str_a7("</").Add(last_tag).Add_byte(Byte_ascii.Angle_end).Add(line).To_bry_and_clear();
|
||||||
}
|
}
|
||||||
XophpArray.popBryOrNull(tr_attributes);
|
XophpArrayUtl.popBryOrNull(tr_attributes);
|
||||||
// PORTED:$outLine = $line . str_repeat( '</dd></dl>', $indent_level );
|
// PORTED:$outLine = $line . str_repeat( '</dd></dl>', $indent_level );
|
||||||
tmp.Add(line);
|
tmp.Add(line);
|
||||||
for (int j = 0; j < indent_level; j++)
|
for (int j = 0; j < indent_level; j++)
|
||||||
@ -152,19 +152,19 @@ public class Xomw_table_wkr implements gplx.core.brys.Bry_split_wkr {// THREAD.U
|
|||||||
sanitizer.fixTagAttributes(tmp, Name__tr, atrs);
|
sanitizer.fixTagAttributes(tmp, Name__tr, atrs);
|
||||||
atrs = tmp.To_bry_and_clear();
|
atrs = tmp.To_bry_and_clear();
|
||||||
|
|
||||||
XophpArray.popBryOrNull(tr_attributes);
|
XophpArrayUtl.popBryOrNull(tr_attributes);
|
||||||
tr_attributes.Add(atrs);
|
tr_attributes.Add(atrs);
|
||||||
|
|
||||||
line = Bry_.Empty;
|
line = Bry_.Empty;
|
||||||
byte[] last_tag = XophpArray.popBryOrNull(last_tag_history);
|
byte[] last_tag = XophpArrayUtl.popBryOrNull(last_tag_history);
|
||||||
XophpArray.popBoolOrN(has_opened_tr);
|
XophpArrayUtl.popBoolOrN(has_opened_tr);
|
||||||
has_opened_tr.Add(true);
|
has_opened_tr.Add(true);
|
||||||
|
|
||||||
if (XophpArray.popBoolOrN(tr_history)) {
|
if (XophpArrayUtl.popBoolOrN(tr_history)) {
|
||||||
line = Html__tr__end;
|
line = Html__tr__end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XophpArray.popBoolOrN(td_history)) {
|
if (XophpArrayUtl.popBoolOrN(td_history)) {
|
||||||
line = tmp.Add_str_a7("</").Add(last_tag).Add_byte(Byte_ascii.Gt).Add(line).To_bry_and_clear();
|
line = tmp.Add_str_a7("</").Add(last_tag).Add_byte(Byte_ascii.Gt).Add(line).To_bry_and_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,19 +205,19 @@ public class Xomw_table_wkr implements gplx.core.brys.Bry_split_wkr {// THREAD.U
|
|||||||
byte[] cell = cells[j];
|
byte[] cell = cells[j];
|
||||||
previous = Bry_.Empty;
|
previous = Bry_.Empty;
|
||||||
if (first_char != Byte_ascii.Plus) {
|
if (first_char != Byte_ascii.Plus) {
|
||||||
byte[] tr_after = XophpArray.popBryOrNull(tr_attributes);
|
byte[] tr_after = XophpArrayUtl.popBryOrNull(tr_attributes);
|
||||||
if (!XophpArray.popBoolOrN(tr_history)) {
|
if (!XophpArrayUtl.popBoolOrN(tr_history)) {
|
||||||
previous = tmp.Add_str_a7("<tr").Add(tr_after).Add_str_a7(">\n").To_bry_and_clear();
|
previous = tmp.Add_str_a7("<tr").Add(tr_after).Add_str_a7(">\n").To_bry_and_clear();
|
||||||
}
|
}
|
||||||
tr_history.Add(true);
|
tr_history.Add(true);
|
||||||
tr_attributes.Add(Bry_.Empty);
|
tr_attributes.Add(Bry_.Empty);
|
||||||
XophpArray.popBoolOrN(has_opened_tr);
|
XophpArrayUtl.popBoolOrN(has_opened_tr);
|
||||||
has_opened_tr.Add(true);
|
has_opened_tr.Add(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] last_tag = XophpArray.popBryOrNull(last_tag_history);
|
byte[] last_tag = XophpArrayUtl.popBryOrNull(last_tag_history);
|
||||||
|
|
||||||
if (XophpArray.popBoolOrN(td_history)) {
|
if (XophpArrayUtl.popBoolOrN(td_history)) {
|
||||||
previous = tmp.Add_str_a7("</").Add(last_tag).Add_str_a7(">\n").Add(previous).To_bry_and_clear();
|
previous = tmp.Add_str_a7("</").Add(last_tag).Add_str_a7(">\n").Add(previous).To_bry_and_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,14 +103,14 @@ public class XomwSiteList extends XomwGenericArrayObject { public int Len() {ret
|
|||||||
*/
|
*/
|
||||||
XomwSite site = (XomwSite)this.offsetGet(index);
|
XomwSite site = (XomwSite)this.offsetGet(index);
|
||||||
|
|
||||||
XophpArray.unset(this.byGlobalId, site.getGlobalId());
|
XophpArrayUtl.unset(this.byGlobalId, site.getGlobalId());
|
||||||
XophpArray.unset(this.byInternalId, site.getInternalId());
|
XophpArrayUtl.unset(this.byInternalId, site.getInternalId());
|
||||||
|
|
||||||
Ordered_hash ids = site.getNavigationIds();
|
Ordered_hash ids = site.getNavigationIds();
|
||||||
int len = ids.Len();
|
int len = ids.Len();
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
int navId = Int_.Cast(ids.Get_at(i));
|
int navId = Int_.Cast(ids.Get_at(i));
|
||||||
XophpArray.unset(this.byNavigationId, navId);
|
XophpArrayUtl.unset(this.byNavigationId, navId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ public class XomwSiteList extends XomwGenericArrayObject { public int Len() {ret
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public String[] getGlobalIdentifiers() {
|
public String[] getGlobalIdentifiers() {
|
||||||
return XophpArray.array_keys_str(this.byGlobalId);
|
return XophpArrayUtl.array_keys_str(this.byGlobalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,7 +137,7 @@ public class XomwSiteList extends XomwGenericArrayObject { public int Len() {ret
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public boolean hasSite(String globalSiteId) {
|
public boolean hasSite(String globalSiteId) {
|
||||||
return XophpArray.array_key_exists(globalSiteId, this.byGlobalId);
|
return XophpArrayUtl.array_key_exists(globalSiteId, this.byGlobalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -174,7 +174,7 @@ public class XomwSiteList extends XomwGenericArrayObject { public int Len() {ret
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
@Override public boolean isEmpty() {
|
@Override public boolean isEmpty() {
|
||||||
return XophpArray.array_is_empty(this.byGlobalId);
|
return XophpArrayUtl.array_is_empty(this.byGlobalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -185,7 +185,7 @@ public class XomwSiteList extends XomwGenericArrayObject { public int Len() {ret
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public boolean hasInternalId(int id) {
|
public boolean hasInternalId(int id) {
|
||||||
return XophpArray.array_key_exists(id, this.byInternalId);
|
return XophpArrayUtl.array_key_exists(id, this.byInternalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -222,7 +222,7 @@ public class XomwSiteList extends XomwGenericArrayObject { public int Len() {ret
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public boolean hasNavigationId(String id) {
|
public boolean hasNavigationId(String id) {
|
||||||
return XophpArray.array_key_exists(id, this.byNavigationId);
|
return XophpArrayUtl.array_key_exists(id, this.byNavigationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1 +1 @@
|
|||||||
wikidata
|
v4.5.19.1801
|
||||||
|
Loading…
Reference in New Issue
Block a user