1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2015-07-12 21:10:02 -04:00
commit 794b5a232f
3099 changed files with 238212 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
public class Pfunc_if extends Pf_func_base {
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
byte[] val = Eval_argx(ctx, src, caller, self);
boolean val_is_empty = true; int val_len = val.length;
for (int i = 0; i < val_len; i++) {
switch (val[i]) {
case Byte_ascii.Space: case Byte_ascii.Nl: case Byte_ascii.Tab: break; // ws; continue
default: val_is_empty = false; i = val_len; break; // non-ws; break loop
}
}
if (val_is_empty)
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), 1));
else
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), 0));
}
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_if;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_if().Name_(name);}
}

View File

@@ -0,0 +1,45 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_if_tst {
private Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void If_y() {fxt.Test_parse_tmpl_str_test("{{#if:1|a|b}}" , "{{test}}" , "a");}
@Test public void If_n() {fxt.Test_parse_tmpl_str_test("{{#if:|a|b}}" , "{{test}}" , "b");}
@Test public void If_n_ws() {fxt.Test_parse_tmpl_str_test("{{#if: |a|b}}" , "{{test}}" , "b");}
@Test public void If_y_ws() {fxt.Test_parse_tmpl_str_test("{{#if: |a|b \n}}" , "{{test}}" , "b");}
@Test public void If_y_ws1() {fxt.Test_parse_tmpl_str_test("{{#if: |a|{{#if: |a|b}}\n}}" , "{{test}}" , "b");}
@Test public void If_prm_n() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{{1}}}|b}}" , "{{test}}" , "b");}
@Test public void If_prm_y() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{{1}}}|b}}" , "{{test|a}}" , "a");}
@Test public void If_prm_n_dflt_ws() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1| }}}|a|b}}" , "{{test}}" , "b");}
@Test public void If_prm_nest_0() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{#if:{{{2|}}}|a|b}}|c}}" , "{{test}}" , "c");}
@Test public void If_prm_nest_1() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{#if:{{{2|}}}|a|b}}|c}}" , "{{test|1}}" , "b");}
@Test public void If_prm_nest_2() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1|}}}|{{#if:{{{2|}}}|a|b}}|c}}" , "{{test|1|2}}" , "a");}
@Test public void If_ignore_key() {fxt.Test_parse_tmpl_str_test("{{#if:|<i id=1|<i id=2}}" , "{{test}}" , "<i id=2");}
@Test public void If_newline() { // PURPOSE: new_line in comments; WP:[[redirect-distinguish|a|b]]
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
( "{{#if:1<!--"
, "-->|a<!--"
, "-->|b<!--"
, "-->}}"
)
, "{{test}}", "a");
}
@Test public void If_rel2abs() {fxt.Test_parse_tmpl_str_test("{{#if:{{{1}}}|y}}" , "{{test|http://a.org/c/}}" , "y");} // PURPOSE.fix: trailing slash should not trigger rel2abs code; DATE:2013-04-06
}

View File

@@ -0,0 +1,32 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
public class Pfunc_ifeq extends Pf_func_base {
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
int self_args_len = self.Args_len(); if (self_args_len < 2) return; // no equal/not_equal clauses defined; return; EX: {{#if:a}} {{#if:a|b}}
byte[] lhs = Eval_argx(ctx, src, caller, self);
byte[] rhs = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0);
if (Pf_func_.Eq_(lhs, rhs))
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1));
else
bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 2));
}
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_ifeq;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ifeq().Name_(name);}
}

View File

@@ -0,0 +1,48 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_ifeq_tst {
private Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Ifeq_y() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|1|a|b}}" , "{{test}}" , "a");}
@Test public void Ifeq_n() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|2|a|b}}" , "{{test}}" , "b");}
@Test public void Ifeq_prm_arg() {fxt.Test_parse_tmpl_str_test("{{#ifeq:{{{1}}}|1|a|b}}" , "{{test|1}}" , "a");}
@Test public void Ifeq_prm_arg_n() {fxt.Test_parse_tmpl_str_test("{{#ifeq:{{{1}}}|1|a|b}}" , "{{test|2}}" , "b");}
@Test public void Ifeq_prm_blank_y() {fxt.Test_parse_tmpl_str_test("{{#ifeq:||a|b}}" , "{{test}}" , "a");}
@Test public void Ifeq_prm_blank_n() {fxt.Test_parse_tmpl_str_test("{{#ifeq:|1|a|b}}" , "{{test}}" , "b");}
@Test public void Ifeq_numeric() {fxt.Test_parse_tmpl_str_test("{{#ifeq:003|3.0|y|n}}" , "{{test}}" , "y");}
@Test public void Ifeq_numeric_neg() {fxt.Test_parse_tmpl_str_test("{{#ifeq:-1.0|-1|y|n}}" , "{{test}}" , "y");}
@Test public void Ifeq_prm_arg0() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|{{{1}}}|a|b}}" , "{{test|1}}" , "a");}
@Test public void Ifeq_expr_err() {fxt.Test_parse_tmpl_str_test("{{#ifeq:{{#expr:a}}|0|y|n}}" , "{{test}}" , "n");}
@Test public void Ifeq_blank() {fxt.Test_parse_tmpl_str_test("{{#ifeq:0||y|n}}" , "{{test}}" , "n");}
@Test public void Ifeq_exc_args_0() {fxt.Test_parse_tmpl_str_test("{{#ifeq:}}" , "{{test}}" , "");}
@Test public void Ifeq_exc_args_1() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|1}}" , "{{test}}" , "");}
@Test public void Ifeq_exc_args_2() {fxt.Test_parse_tmpl_str_test("{{#ifeq:1|1|a}}" , "{{test}}" , "a");}
@Test public void Ifeq_exp() {fxt.Test_parse_tmpl_str_test("{{#ifeq:0.006|+6.0E-3|y|n}}" , "{{test}}" , "y");}
@Test public void Ifeq_plus_minus() {fxt.Test_parse_tmpl_str_test("{{#ifeq:+|-|y}}" , "{{test}}" , "");} // PURPOSE: was evaluating to y; PAGE:en.w:Permian-Triassic extinction
@Test public void Tab_ent() { // PURPOSE: hack; tabs are materialized as "&#09;" which causes trimming problems; PAGE:en.w:Template:Cretaceous_graphical_timeline and "|period11= Campanian\s\t"
fxt.Test_parse_page_all_str("{{#ifeq:a|a &#09;|y|n}}", "y"); // note that "|a\s\t" gets trimmed to "a"
}
@Test public void Ifeq_hex() {fxt.Test_parse_tmpl_str_test("{{#ifeq:44|0X002C|y|n}}" , "{{test}}" , "y");} // PURPOSE: hex compares to int; EX:w:Comma
@Test public void Colon_2() { // PURPOSE: 2nd colon causes error b/c of bad whitespace evaluation; PAGE:en.w:de.wiktionary.org/wiki/glitschig; DATE:2013-12-10
fxt.Test_parse_tmpl_str_test("{{#ifeq: :|a|b|c}}" , "{{test}}" , "c");
}
}

View File

@@ -0,0 +1,123 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import gplx.core.primitives.*; import gplx.core.btries.*;
public class Pfunc_iferror extends Pf_func_base {
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
int self_args_len = self.Args_len();
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self);
if (val_dat_ary == null) return;
if (Error_exists(val_dat_ary))
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0));
else {
if (self_args_len < 2) // pass clause absent; add original
bb.Add(val_dat_ary);
else
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1));
}
}
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_iferror;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_iferror().Name_(name);}
boolean Error_exists(byte[] src) {
// NOTE: approximation of MW code. basically checking for <tag class=error; REF.MW: ParserFunctions_body.php|iferror
// /<(?:strong|span|p|div)\s(?:[^\s>]*\s+)*?class="(?:[^"\s>]*\s+)*?error(?:\s[^">]*)?"/
int src_len = src.length;
byte state = State_null;
int pos = 0;
boolean valid = false;
while (true) {
if (pos == src_len) break;
byte b = src[pos];
Object o = trie.Match_bgn_w_byte(b, src, pos, src_len);
if (o == null)
++pos;
else {
Byte_obj_val bv = (Byte_obj_val)o;
int pos_nxt = trie.Match_pos();
if (pos_nxt == src_len) return false; // each of the three states requires at least one character afterwards
switch (bv.Val()) {
case State_close: // >: reset state
state = State_null;
break;
case State_nde: // <(?:strong|span|p|div)\s
switch (src[pos_nxt]) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:
state = State_nde;
++pos_nxt;
break;
}
break;
case State_class:
if (state == State_nde) {
valid = true;
switch (src[pos - 1]) {
case Byte_ascii.Quote: case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:
break;
default:
valid = false;
break;
}
if (valid) {
state = State_class;
++pos_nxt;
}
}
break;
case State_error:
if (state == State_class) {
valid = true;
switch (src[pos - 1]) {
case Byte_ascii.Quote: case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:
break;
default:
valid = false;
break;
}
switch (src[pos_nxt]) {
case Byte_ascii.Quote: case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:
break;
default:
valid = false;
break;
}
if (valid)
return true;
}
break;
}
pos = pos_nxt;
}
}
return false;
}
private static final Btrie_slim_mgr trie = trie_();
static final byte State_null = 0, State_nde = 1, State_class = 2, State_error = 3, State_close = 4;
private static Btrie_slim_mgr trie_() {
Btrie_slim_mgr rv = Btrie_slim_mgr.ci_ascii_(); // NOTE:ci.ascii:MW_const.en
trie_init(rv, State_nde , "<strong");
trie_init(rv, State_nde , "<span");
trie_init(rv, State_nde , "<p");
trie_init(rv, State_nde , "<div");
trie_init(rv, State_class, "class=");
trie_init(rv, State_error, "error");
trie_init(rv, State_close, ">");
return rv;
}
private static void trie_init(Btrie_slim_mgr trie, byte b, String s) {trie.Add_obj(s, Byte_obj_val.new_(b));}
}

View File

@@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_iferror_tst {
private Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Basic_pass() {fxt.Test_parse_tmpl_str_test("{{#iferror: {{#expr: 1 + 2 }} | error | ok }}" , "{{test}}" , "ok");}
@Test public void Basic_fail() {fxt.Test_parse_tmpl_str_test("{{#iferror: {{#expr: 1 + X }} | error | ok }}" , "{{test}}" , "error");}
@Test public void Basic_omit() {fxt.Test_parse_tmpl_str_test("{{#iferror: ok | error}}" , "{{test}}" , "ok");}
@Test public void NoMatch_0() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong>error</strong> | error | ok }}" , "{{test}}" , "ok");}
@Test public void NoMatch_1() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong test=\"error\"></strong> | error | ok }}" , "{{test}}" , "ok");}
@Test public void NoMatch_2() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong class=\"errora\"></strong> | error | ok }}" , "{{test}}" , "ok");}
//@Test public void NoMatch_3() {fxt.Test_parse_tmpl_str_test("{{#iferror: <strong class=\"error a| error | ok }}" , "{{test}}" , "ok");} // FUTURE: match for ">
}

View File

@@ -0,0 +1,35 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
public class Pfunc_ifexist extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_iferror;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ifexist().Name_(name);}
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr rslt_bfr) {
int args_len = self.Args_len();
byte[] val_bry = Eval_argx(ctx, src, caller, self);
if (Exists(ctx.Wiki(), val_bry))
rslt_bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 0));
else
rslt_bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 1));
}
public static boolean Exists(Xowe_wiki wiki, byte[] ttl_bry) {
synchronized (Mgr) {return Mgr.Exists(wiki, ttl_bry);}
}
public static final Pfunc_ifexist_mgr Mgr = new Pfunc_ifexist_mgr();
}

View File

@@ -0,0 +1,78 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import gplx.xowa.wmfs.apis.*; import gplx.xowa.wikis.data.tbls.*;
public class Pfunc_ifexist_mgr {
private Xowd_page_itm db_page = Xowd_page_itm.new_tmp();
private Hash_adp regy = Hash_adp_bry.cs_();
public void Clear() {regy.Clear();}
public boolean Exists(Xowe_wiki wiki, byte[] raw_bry) {
if (Bry_.Len_eq_0(raw_bry)) return false; // return early; NOTE: {{autolink}} can pass in "" (see test)
Xoa_ttl ttl = Xoa_ttl.parse_(wiki, raw_bry); if (ttl == null) return false;
byte[] ttl_bry = ttl.Page_db(); // NOTE: must use Page_db; EX: {{#ifexist:File:Peter & Paul fortress in SPB 03.jpg|y|n}}
Object exists_obj = regy.Get_by(ttl_bry);
if (exists_obj != null) return ((Pfunc_ifexist_itm)exists_obj).Exists();
Pfunc_ifexist_itm exists_itm = new Pfunc_ifexist_itm(ttl_bry);
regy.Add(ttl_bry, exists_itm);
db_page.Clear();
Xow_ns ttl_ns = ttl.Ns();
boolean rv = false;
switch (ttl_ns.Id()) {
case Xow_ns_.Id_special: rv = true; break; // NOTE: some pages call for [[Special]]; always return true for now; DATE:2014-07-17
case Xow_ns_.Id_media: rv = Find_ttl_for_media_ns(exists_itm, wiki, ttl_ns, ttl_bry); break;
default: rv = Find_ttl_in_db(exists_itm, wiki, ttl_ns, ttl_bry); break;
}
exists_itm.Exists_(rv);
return rv;
}
private boolean Find_ttl_in_db(Pfunc_ifexist_itm itm, Xowe_wiki wiki, Xow_ns ns, byte[] ttl_bry) {
boolean rv = wiki.Db_mgr().Load_mgr().Load_by_ttl(db_page, ns, ttl_bry);
if ( !rv
&& wiki.Lang().Vnt_mgr().Enabled()) {
Xowd_page_itm page = wiki.Lang().Vnt_mgr().Convert_ttl(wiki, ns, ttl_bry);
if (page != Xowd_page_itm.Null)
rv = page.Exists();
}
itm.Exists_(rv);
return rv;
}
private boolean Find_ttl_for_media_ns(Pfunc_ifexist_itm itm, Xowe_wiki wiki, Xow_ns ns, byte[] ttl_bry) {
Xow_ns file_ns = wiki.Ns_mgr().Ns_file();
boolean rv = Find_ttl_in_db(itm, wiki, file_ns, ttl_bry); if (rv) return true; // rarely true, but check local wiki's [[File:]] table anyway
Xowe_wiki commons_wiki = wiki.Appe().Wiki_mgr().Wiki_commons();
boolean env_is_testing = Env_.Mode_testing();
if ( commons_wiki != null // null check
&& ( commons_wiki.Init_assert().Db_mgr().Tid() == gplx.xowa.dbs.Xodb_mgr_sql.Tid_sql // make sure tid=sql; tid=txt automatically created for online images; DATE:2014-09-21
|| env_is_testing
)
) {
file_ns = commons_wiki.Ns_mgr().Ns_file();
return Find_ttl_in_db(itm, commons_wiki, file_ns, ttl_bry); // accurate test using page table in commons wiki (provided commons is up to date)
}
else {
if (!env_is_testing)
wiki.File_mgr().Init_file_mgr_by_load(wiki); // NOTE: must init Fsdb_mgr (else conn == null), and with bin_wkrs (else no images will ever load); DATE:2014-09-21
return wiki.File_mgr().Exists(ttl_bry); // less-accurate test using either (1) orig_wiki table in local wiki (v2) or (2) meta_db_mgr (v1)
}
}
}
class Pfunc_ifexist_itm {
public Pfunc_ifexist_itm(byte[] ttl) {this.ttl = ttl;}
public byte[] Ttl() {return ttl;} private byte[] ttl;
public boolean Exists() {return exists;} public void Exists_(boolean v) {exists = v;} private boolean exists;
}

View File

@@ -0,0 +1,50 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_ifexist_tst {
private Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Basic_pass() {fxt.Test_parse_tmpl_str_test("{{#ifexist: Abc | exists | doesn't exist }}" , "{{test}}" , "doesn't exist");}
@Test public void Empty() {fxt.Test_parse_tmpl_str_test("{{#ifexist:|y|n}}" , "{{test}}" , "n");} // NOTE: {{autolink}} can pass in ""
@Test public void Db_key() { // PURPOSE: test that (1) & is encoded; (2) " " becomes "_"; EX: {{#ifexist:File:Peter & Paul fortress in SPB 03.jpg|y|n}}
fxt.Init_page_create("A_&_b", "");
fxt.Test_parse_tmpl_str_test("{{#ifexist:A & b|y|n}}", "{{test}}", "y");
}
@Test public void Media_n() {// DATE:2014-07-04
Pfunc_ifexist.Mgr.Clear();
fxt.Test_parse_tmpl_str_test("{{#ifexist:Media:A.png|y|n}}", "{{test}}", "n");
}
@Test public void Media_y_wiki() {// DATE:2014-07-04
Pfunc_ifexist.Mgr.Clear();
fxt.Init_page_create("File:A.png", "");
fxt.Test_parse_tmpl_str_test("{{#ifexist:Media:A.png|y|n}}", "{{test}}", "y");
}
@Test public void Media_y_commons() {// DATE:2014-07-04
Pfunc_ifexist.Mgr.Clear();
Xowe_wiki commons_wiki = fxt.App().Wiki_mgr().Get_by_key_or_make(gplx.xowa.wikis.Xow_domain_.Domain_bry_commons);
fxt.Init_page_create(commons_wiki, "File:A.png", "");
fxt.Test_parse_tmpl_str_test("{{#ifexist:Media:A.png|y|n}}", "{{test}}", "y");
}
@Test public void Media_y_file_v1() {// DATE:2014-07-04
Pfunc_ifexist.Mgr.Clear();
Xof_meta_itm meta_itm = fxt.Wiki().File_mgr().Meta_mgr().Get_itm_or_new(Bry_.new_a7("A.png"));
meta_itm.Orig_exists_(Bool_.Y_byte);
fxt.Test_parse_tmpl_str_test("{{#ifexist:Media:A.png|y|n}}", "{{test}}", "y");
}
}

View File

@@ -0,0 +1,42 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import gplx.xowa.xtns.pfuncs.exprs.*;
public class Pfunc_ifexpr extends Pf_func_base {
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb) {
int self_args_len = self.Args_len();
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self);
if (val_dat_ary == null) return;
DecimalAdp result = shunter.Evaluate(ctx, val_dat_ary);
boolean is_nan = result == Pfunc_expr_shunter.Null_rslt;
if (is_nan && shunter.Err().Len() > 0) {
bb.Add_bfr_and_preserve(shunter.Err());
shunter.Err().Clear();
}
else {
if (is_nan || result.Xto_int() == 0)
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1));
else
bb.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0));
}
}
Pfunc_expr_shunter shunter = Pfunc_expr_shunter._;
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_ifexpr;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_ifexpr().Name_(name);}
}

View File

@@ -0,0 +1,31 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_ifexpr_tst {
private Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset();}
@Test public void Basic_y() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 1 > 0 |y|n}}" , "{{test}}" , "y");}
@Test public void Basic_n() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 1 < 0 |y|n}}" , "{{test}}" , "n");}
@Test public void Blank_n() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: |y|n}}" , "{{test}}" , "n");}
@Test public void Args_0_n() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 1 > 0}}" , "{{test}}" , "");}
@Test public void Args_0_y() {fxt.Test_parse_tmpl_str_test("{{#ifexpr: 0 > 1}}" , "{{test}}" , "");}
@Test public void Err() {fxt.Test_parse_tmpl_str_test("{{#ifexpr:20abc >1|y|n}}" , "{{test}}" , "<strong class=\"error\">Expression error: Unrecognised word \"abc \"</strong>");} // HACK: shouldn't be "abc "
}
/*
*/

View File

@@ -0,0 +1,89 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
public class Pfunc_switch extends Pf_func_base {
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_switch;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_switch().Name_(name);}
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {// REF.MW:ParserFunctions_body.php
int self_args_len = self.Args_len(); if (self_args_len == 0) return; // no cases; return; effectively "empty"
byte[] argx = Eval_argx(ctx, src, caller, self);
boolean fall_thru_found = false;
byte[] match = null;
Arg_itm_tkn dflt_val_tkn = null; byte[] dflt_val_bry = null;
Arg_nde_tkn last_keyless_arg = null;
Bry_bfr tmp = ctx.Wiki().Utl__bfr_mkr().Get_b512();
Xol_kwd_mgr kwd_mgr = ctx.Lang().Kwd_mgr();
for (int i = 0; i < self_args_len; i++) {
Arg_nde_tkn arg = self.Args_get_by_idx(i);
if (arg.KeyTkn_exists()) { // = exists; EX: "|a=1|"
last_keyless_arg = null; // set last_keyless_arg to null
byte[] case_key = Get_or_eval(ctx, src, caller, self, bfr, arg.Key_tkn(), tmp);
if ( fall_thru_found // fall-thru found earlier; take cur value; EX: {{#switch:a|a|b=1|c=2}} -> 1
|| Pf_func_.Eq_(case_key, argx) // case_key matches argx; EX: {{#switch:a|a=1}}
) {
match = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
break; // stop iterating; explicit match found;
}
else if (kwd_mgr.Kwd_default_match(case_key)){ // case_key is #default; EX: {{#switch:a|#default=1}}; note that "#defaultabc" is also allowed;
dflt_val_tkn = arg.Val_tkn(); // set dflt_val_tkn; note that there is no "break" b/c multiple #defaults will use last one; EX: {{#switch:a|#default=1|#default=2}} -> 2
dflt_val_bry = null; // set dflt_val_bry to null; EX:{{#switch:a|#defaultabc|#default=2}} -> 2
}
else {} // case_key != argx; continue
}
else { // = missing; EX: "|a|", "|#default|"
last_keyless_arg = arg;
byte[] case_val = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
if (Pf_func_.Eq_(case_val, argx)) // argx matches case_val; EX: case_val="|a|" and argx="a"
fall_thru_found = true; // set as fall-thru; note that fall-thrus will have "val" in next keyed arg, so need to continue iterating; EX: {{#switch:a|a|b=1|c=2}} "a" is fall-thru, but "b" is next keyed arg with a val
else if (kwd_mgr.Kwd_default_match(case_val)) { // case_val starts with #default; EX: "|#default|" or "|#defaultabc|"
last_keyless_arg = null; // unflag last keyless arg else |#defaultabc| will be treated as last_keyless_arg and generate "#defaultabc"; DATE:2014-05-29
dflt_val_tkn = null; // unflag dflt_val_tkn; EX: {{#switch:a|b|#default=1|#default}} -> "" x> "1"
int case_val_len = case_val.length;
dflt_val_bry
= case_val_len == Dflt_keyword_len // PERF: check if case_val = "|#default|"
? null // PERF: set to null; don't create Bry_.Empty
: Bry_.Mid(case_val, Dflt_keyword_len, case_val_len) // chop off "#default"; EX: {{#switch:a|b|#defaultabc}} -> "abc"
;
}
}
}
if (match == null) { // no match; will either use last_keyless arg or #default
if (last_keyless_arg != null) // always prefer last_keyless_arg; EX: {{#switch:a|#default=1|2}} -> 2
match = Get_or_eval(ctx, src, caller, self, bfr, last_keyless_arg.Val_tkn(), tmp);
else if (dflt_val_bry != null) // "|#defaultabc|" found; use it
match = dflt_val_bry;
else if (dflt_val_tkn != null) // "|#default=val|" found; use it
match = Get_or_eval(ctx, src, caller, self, bfr, dflt_val_tkn, tmp);
else {} // nothing found; noop; match will remain null
}
if (match != null)
bfr.Add(match);
tmp.Mkr_rls();
}
private byte[] Get_or_eval(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb, Arg_itm_tkn itm, Bry_bfr tmp) {
if (itm.Itm_static() == Bool_.Y_byte)
return Bry_.Trim(src, itm.Dat_bgn(), itm.Dat_end());
else {
itm.Tmpl_evaluate(ctx, src, caller, tmp);
return tmp.Xto_bry_and_clear_and_trim();
}
}
public static final byte[] Dflt_keyword = Bry_.new_u8("#default"); // NOTE: technically should pull from messages, but would need to cache Dflt_keyword on wiki level; checked all Messages files, and no one overrides it; DATE:2014-05-29
private static int Dflt_keyword_len = Dflt_keyword.length;
}

View File

@@ -0,0 +1,91 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pfunc_switch_tst {
@Before public void init() {fxt.Reset();} private Xop_fxt fxt = new Xop_fxt();
@Test public void Basic_a() {fxt.Test_parse_tmpl_str_test("{{#switch:a|a=1|b=2|3}}" , "{{test}}" , "1");}
@Test public void Basic_b() {fxt.Test_parse_tmpl_str_test("{{#switch:b|a=1|b=2|3}}" , "{{test}}" , "2");}
@Test public void Basic_dflt() {fxt.Test_parse_tmpl_str_test("{{#switch:z|a=1|b=2|3}}" , "{{test}}" , "3");}
@Test public void FallThru_a() {fxt.Test_parse_tmpl_str_test("{{#switch:a|a|b|c=1|d=2|3}}" , "{{test}}" , "1");}
@Test public void FallThru_b() {fxt.Test_parse_tmpl_str_test("{{#switch:b|a|b|c=1|d=2|3}}" , "{{test}}" , "1");}
@Test public void FallThru_c() {fxt.Test_parse_tmpl_str_test("{{#switch:c|a|b|c=1|d=2|3}}" , "{{test}}" , "1");}
@Test public void FallThru_d() {fxt.Test_parse_tmpl_str_test("{{#switch:d|a|b|c=1|d=2|3}}" , "{{test}}" , "2");}
@Test public void FallThru_dflt() {fxt.Test_parse_tmpl_str_test("{{#switch:z|a|b|c=1|d=2|3}}" , "{{test}}" , "3");}
@Test public void Dflt_named() {fxt.Test_parse_tmpl_str_test("{{#switch:z|b=2|#default=3|a=1}}" , "{{test}}" , "3");}
@Test public void Dflt_last_idx_wins() // even if there is a named default, if last arg is un-keyd, then use it as default
{fxt.Test_parse_tmpl_str_test("{{#switch:z|#default=3|9}}" , "{{test}}" , "9");}
@Test public void Dflt_last_named_wins() // last named default wins
{fxt.Test_parse_tmpl_str_test("{{#switch:z|#default=3|#default=4}}" , "{{test}}" , "4");}
@Test public void Numeric() {fxt.Test_parse_tmpl_str_test("{{#switch:003|3.0=y|n}}" , "{{test}}" , "y");} //{{#switch:{{CURRENTMONTH}}|03=y|n}}
@Test public void NoKeys() {fxt.Test_parse_tmpl_str_test("{{#switch:a|a|b|c|d}}" , "{{test}}" , "d");}// d wins b/c it is default
@Test public void Prm_val() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a=1|b=2|3}}" , "{{test|b}}" , "2");}
@Test public void Prm_case1v() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a={{{1}}}|b=2|3}}" , "{{test|a}}" , "a");}
@Test public void Prm_case1k() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|{{{1}}}=1|b=2|3}}" , "{{test|a}}" , "1");}
@Test public void Null_x() {fxt.Test_parse_tmpl_str_test("{{#switch:|a=1|b=2|3}}" , "{{test|b}}" , "3");}
@Test public void Exc_no_cases() {fxt.Test_parse_tmpl_str_test("{{#switch:a}}" , "{{test}}" , "");}
@Test public void Exc_brace() {fxt.Test_parse_tmpl_str_test("{{#switch:a|{{{1}}}}=y|n}}" , "{{test|a}}" , "n");}// NOTE: deliberate 4th } brace
@Test public void Ex_1() {fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|off=none|def=off|{{{1|off}}}}}", "{{test|b}}" , "b");}
@Test public void Ex_2() {
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
( "{{#switch:{{{{{|safesubst:}}}NAMESPACE:Category:Foo}}"
, "|{{ns:0}}"
, "|{{ns:Category}}=yes"
, "|no"
, "}}"
)
, "{{test}}"
, "yes");
}
@Test public void Ws() {
fxt.Test_parse_tmpl_str_test(String_.Concat_lines_nl_skip_last
( "{{#switch: | {{ns:0}}"
, "|{{ns:2}} = yes"
, "|no"
, "}}"
)
, "{{test}}"
, "yes");
}
@Test public void Do_not_call_val_unless_needed() {
fxt.Init_defn_clear();
Xop_xowa_dbg.Argx_list.Clear();
fxt.Init_defn_add("fail", "{{#xowa_dbg:Fail}}");
fxt.Init_defn_add("pass", "{{#xowa_dbg:Pass}}");
fxt.Init_defn_add("dflt", "{{#xowa_dbg:Dflt}}");
fxt.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a={{fail}}|#default={{dflt}}|b={{pass}}}}", "{{test|b}}", "Pass");
Tfds.Eq(1, Xop_xowa_dbg.Argx_list.Count());
}
@Test public void Dflt_empty() { // PURPOSE: empty default should return "" not "#default"; PAGE:de.v:M<>nchen/Sehensw<73>rdigkeiten; DATE:2014-05-29
fxt.Test_parse_tmpl_str_test("{{#switch:z|b=1|#default}}" , "{{test}}" , "");
fxt.Test_parse_tmpl_str_test("{{#switch:z|b=1|#defaultabc}}" , "{{test}}" , "abc"); // chop off "#default"
fxt.Test_parse_tmpl_str_test("{{#switch:a|#default|#default=1}}" , "{{test}}" , "1"); // override "|#default|" with "|#default=2|"
fxt.Test_parse_tmpl_str_test("{{#switch:b|#default|1}}" , "{{test}}" , "1"); // override "|#default|" with "|2|"
fxt.Test_parse_tmpl_str_test("{{#switch:b|#defaultabc=1}}" , "{{test}}" , "1"); // this is also supported by MW
}
@Test public void Multiple() {
fxt.Wiki().Lang().Kwd_mgr().Kwd_default_match_reset();
Xol_kwd_grp kwd_grp = fxt.Wiki().Lang().Kwd_mgr().Get_or_new(Xol_kwd_grp_.Id_xtn_default);
kwd_grp.Srl_load(Bool_.Y, new byte[][] {Bry_.new_a7("#default1"), Bry_.new_a7("#default2")});
fxt.Test_parse_tmpl_str_test("{{#switch:|n=n|#default1=y}}" , "{{test}}" , "y");
fxt.Test_parse_tmpl_str_test("{{#switch:|n=n|#default2=y}}" , "{{test}}" , "y");
fxt.Test_parse_tmpl_str_test("{{#switch:a|n=n|#default=y}}" , "{{test}}" , ""); // #default is just a case
fxt.Test_parse_tmpl_str_test("{{#switch:|n=n|#default=y}}" , "{{test}}" , ""); // make sure empty String doesn't throw out of bounds
fxt.Wiki().Lang().Kwd_mgr().Kwd_default_match_reset();
}
}

View File

@@ -0,0 +1,28 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.ifs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
public class Xop_xowa_dbg extends Pf_func_base {
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
byte[] argx = Eval_argx(ctx, src, caller, self);
bfr.Add(argx);
Argx_list.Add(argx);
}
public static final List_adp Argx_list = List_adp_.new_();
@Override public int Id() {return Xol_kwd_grp_.Id_xowa_dbg;}
@Override public Pf_func New(int id, byte[] name) {return new Xop_xowa_dbg().Name_(name);}
}