1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2024-09-28 14:30:51 +00:00

XOMW: Add array_filter [#632]

This commit is contained in:
gnosygnu 2020-05-02 08:30:47 -04:00
parent a6b128422e
commit 3d74406a3e
11 changed files with 213 additions and 81 deletions

View File

@ -13,7 +13,9 @@ 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.*;
package gplx.xowa.mediawiki;
import gplx.*;
import gplx.core.strings.*;
public class XophpArray_ {
// REF.PHP:https://www.php.net/manual/en/function.array-merge.php
@ -172,12 +174,12 @@ public class XophpArray_ {
}
// REF.PHP:https://www.php.net/manual/en/function.array-map.php
public static XophpArray array_map(XophpCallableOwner callback_owner, String method, XophpArray array) {
public static XophpArray array_map(XophpCallbackOwner callback_owner, String method, XophpArray array) {
XophpArray rv = XophpArray.New();
int len = array.count();
for (int i = 0; i < len; i++) {
String itm = array.Get_at_str(i);
rv.Add((String)callback_owner.Callback(method, itm));
rv.Add((String)callback_owner.Call(method, itm));
}
return rv;
}
@ -272,4 +274,39 @@ public class XophpArray_ {
}
return itms[0].Val();
}
// REF.PHP: https://www.php.net/manual/en/function.array-filter.php
public static final int ARRAY_FILTER_USE_BOTH = 1, ARRAY_FILTER_USE_KEY = 2, ARRAY_FILTER_USE_VAL = 0; // XO:USE_VAL is not PHP
public static XophpArray array_filter(XophpArray array) {return array_filter(array, XophpArrayFilterNullCallback.Instance, 0);}
public static XophpArray array_filter(XophpArray array, XophpCallback callback) {return array_filter(array, callback, 0);}
public static XophpArray array_filter(XophpArray array, XophpCallback callback, int flag) {
XophpArray rv = new XophpArray();
int len = array.count();
for (int i = 0; i < len; i++) {
XophpArrayItm itm = array.Get_at_itm(i);
boolean filter = false;
switch (flag) {
case ARRAY_FILTER_USE_VAL:
filter = Bool_.Cast(callback.Call(itm.Val()));
break;
case ARRAY_FILTER_USE_KEY:
filter = Bool_.Cast(callback.Call(itm.Key()));
break;
case ARRAY_FILTER_USE_BOTH:
filter = Bool_.Cast(callback.Call(itm.Key(), itm.Val()));
break;
}
if (filter)
rv.Add(itm.Key(), itm.Val());
}
return rv;
}
}
class XophpArrayFilterNullCallback implements XophpCallbackOwner {
public Object Call(String method, Object... args) {
if (args.length != 1) throw new XophpRuntimeException("ArrayFilterNullCallback requires 1 arg");
Object arg = args[0];
return !XophpObject_.empty_obj(arg);
}
public static XophpCallback Instance = new XophpCallback(new XophpArrayFilterNullCallback(), "");
}

View File

@ -1,10 +0,0 @@
package gplx.xowa.mediawiki;
public class XophpCallable {
public XophpCallable(XophpCallableOwner owner, String methodName) {
this.owner = owner;
this.methodName = methodName;
}
public XophpCallableOwner Owner() {return owner;} private final XophpCallableOwner owner;
public String MethodName() {return methodName;} private final String methodName;
}

View File

@ -1,8 +0,0 @@
package gplx.xowa.mediawiki;
public class XophpCallable_ {
// REF.PHP: https://www.php.net/manual/en/function.call-user-func-array.phphttps://www.php.net/manual/en/function.call-user-func-array.php
public static Object call_user_func_array(XophpCallable callback, XophpArray param_arr) {
return callback.Owner().Callback(callback.MethodName(), param_arr);
}
}

View File

@ -0,0 +1,36 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2020 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;
public class XophpCallback {
public XophpCallback(XophpCallbackOwner owner, String methodName) {
this.owner = owner;
this.methodName = methodName;
}
public XophpCallbackOwner Owner() {return owner;} private final XophpCallbackOwner owner;
public String MethodName() {return methodName;} private final String methodName;
public Object Call(Object arg) {
return owner.Call(methodName, arg);
}
public Object Call(Object arg0, Object arg1) {
return owner.Call(methodName, arg0, arg1);
}
// REF.PHP: https://www.php.net/manual/en/function.call-user-func-array.php
public static Object call_user_func_array(XophpCallback callback, XophpArray param_arr) {
return callback.Owner().Call(callback.MethodName(), param_arr);
}
}

View File

@ -14,6 +14,6 @@ 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;
public interface XophpCallableOwner {
Object Callback(String method, Object... args);
public interface XophpCallbackOwner {
Object Call(String method, Object... args);
}

View File

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2020 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;
// REF.PHP: https://www.php.net/manual/en/class.closure.php
public class XophpClosure {
// public static bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] ) : Closure
// public bindTo ( object $newthis [, mixed $newscope = "static" ] ) : Closure
// public call ( object $newthis [, mixed $... ] ) : mixed
// public static fromCallable ( callable $callable ) : Closure
}

View File

@ -18,8 +18,8 @@ import gplx.xowa.mediawiki.includes.XomwTitleOld;
public class XophpObject_ {
public static final Object False = null; // handles code like "if ($var === false)" where var is an Object;
public static boolean is_true(Object val) {return val != null;}
public static boolean is_false(Object val) {return val == null;}
public static boolean is_true(Object val) {return !empty_obj(val);}
public static boolean is_false(Object val) {return empty_obj(val);}
public static boolean is_null(Object val) {return val == null;}
// REF.PHP:http://php.net/manual/en/function.empty.php

View File

@ -19,7 +19,7 @@ import gplx.core.intls.*;
import gplx.objects.strings.unicodes.*;
import gplx.core.primitives.*;
import gplx.objects.strings.bfrs.*;
public class XophpString_ implements XophpCallableOwner {
public class XophpString_ implements XophpCallbackOwner {
public static final String False = null;
public static boolean is_true (String s) {return s != null;} // handles code like "if ($var)" where var is an Object;
public static boolean is_false(String s) {return s == null;}
@ -564,7 +564,7 @@ public class XophpString_ implements XophpCallableOwner {
return String_.Eq(Char_as_str(s, idx), comp);
}
public Object Callback(String method, Object... args) {
public Object Call(String method, Object... args) {
if (String_.Eq(method, "strtoupper")) {
String val = (String)args[0];
return strtoupper(val);
@ -573,5 +573,5 @@ public class XophpString_ implements XophpCallableOwner {
throw Err_.new_unhandled_default(method);
}
}
public static final XophpCallableOwner Callback_owner = new XophpString_();
public static final XophpCallbackOwner Callback_owner = new XophpString_();
}

View File

@ -1,18 +1,18 @@
/*
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
*/
/*
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 XophpType_ {
public static int To_type_id(Object o) {
@ -51,4 +51,6 @@ public class XophpType_ {
public static boolean instance_of(Object o, Class<?> t) {
return Type_.Eq_by_obj(o, t) || Type_.Is_assignable_from_by_obj(o, t);
}
public static Class<?> get_class(Object o) {return o.getClass();}
}

View File

@ -14,15 +14,12 @@ 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;
// MW.SRC:1.33.1
import gplx.core.primitives.String_obj_ref;
import gplx.xowa.mediawiki.*;
/*
TODO:
* class XophpClosure: https://www.php.net/manual/en/class.closure.php
* array_filter: https://www.php.net/manual/en/function.array-filter.php
*/
import gplx.xowa.mediawiki.includes.exception.XomwMWException;
// MW.SRC:1.33.1
/**
* Hooks class.
*
@ -45,7 +42,7 @@ public class XomwHooks {
*
* @since 1.18
*/
public static void register(String name, XophpCallable callback) {
public static void register(String name, XophpCallback callback) {
handlers.Get_by_ary(name).Add(callback);
}
@ -112,7 +109,7 @@ public class XomwHooks {
private static String callHook(String event, Object hookObj, XophpArray args) {return callHook(event, hookObj, args, null, null);}
private static String callHook(String event, Object hookObj, XophpArray args, String deprecatedVersion) {return callHook(event, hookObj, args, deprecatedVersion, null);}
private static String callHook(String event, Object hookObj, XophpArray args, String deprecatedVersion,
String fname
String_obj_ref fname
) {
XophpArray hook;
// Turn non-array values into an array. (Can't use casting because of objects.)
@ -123,59 +120,59 @@ public class XomwHooks {
hook = (XophpArray)hookObj;
}
// if (!array_filter(hook)) {
// Either array is empty or it's an array filled with null/false/empty.
// return null;
// }
if (!XophpObject_.is_true(hook)) {
// Either array is empty or it's an array filled with null/false/empty.
return null;
}
// if (is_array(hook[0])) {
if (XophpArray_.is_array(hook.Get_at(0))) {
// First element is an array, meaning the developer intended
// the first element to be a callback. Merge it in so that
// processing can be uniform.
// hook = array_merge(hook[0], array_slice(hook, 1));
// }
hook = XophpArray_.array_merge(hook.Get_at_ary(0), XophpArray_.array_slice(hook, 1));
}
/**
* hook can be: a function, an object, an array of $function and
* $data, an array of just a function, an array of object and
* method, or an array of object, method, and data.
*/
if (XophpType_.instance_of(hook.Get_at(0), XophpCallable.class)) { // XophpClosure
// $fname = "hook-" + event + "-closure";
// $callback = array_shift(hook);
XophpCallback callback = null;
if (XophpType_.instance_of(hook.Get_at(0), XophpCallback.class)) { // XophpClosure
if (fname != null) fname.Val_("hook-" + event + "-closure");
callback = (XophpCallback) XophpArray_.array_shift(hook);
} else if (XophpObject_.is_object(hook.Get_at_str(0))) {
// Object object = XophpArray_.array_shift(hook);
// Object method = XophpArray_.array_shift(hook);
XophpCallbackOwner object = (XophpCallbackOwner)XophpArray_.array_shift(hook);
String method = (String)XophpArray_.array_shift(hook);
// If no method was specified, default to on$event.
// if ($method === null) {
// $method = "on" + event;
// }
if (XophpObject_.is_null(method)) {
method = "on" + event;
}
// $fname = get_class($object) . '::' . $method;
// $callback = [ $object, $method ];
// } else if (is_string(hook[0])) {
// $fname = $callback = array_shift(hook);
// } else {
// throw new MWException('Unknown datatype in hooks for ' . $event . "\n");
if (fname != null) fname.Val_(XophpType_.get_class(object).getName() + "::" + method);
callback = new XophpCallback(object, method);
} else if (XophpString_.is_string(hook.Get_at(0))) {
throw new XomwMWException("XOMW does not support string callbacks! Should not have been passed here!; event=" + event + "; fname=" + XophpArray_.array_shift(hook) + "\n");
} else {
throw new XomwMWException("Unknown datatype in hooks for " + event + "\n");
}
// XOMW:skip as callback already strongly-typed above
// Run autoloader (workaround for call_user_func_array bug)
// and throw error if not callable.
// if (!is_callable($callback)) {
// throw new MWException('Invalid callback ' . $fname . ' in hooks for ' . $event . "\n");
// }
// if (!is_callable($callback)) {
// throw new MWException('Invalid callback ' . $fname . ' in hooks for ' . $event . "\n");
// }
// mark hook as deprecated, if deprecation version is specified
if (deprecatedVersion != null) {
// wfDeprecated("$event hook (used in $fname)", deprecatedVersion);
}
XophpCallable callback = null;
// Call the hook.
XophpArray hook_args = XophpArray_.array_merge(hook, args);
return (String)XophpCallable_.call_user_func_array(callback, hook_args);
return (String) XophpCallback.call_user_func_array(callback, hook_args);
}
/**
* Call hook functions defined in Hooks::register and $wgHooks.
@ -205,7 +202,7 @@ public class XomwHooks {
public static boolean run(String event, XophpArray args, String deprecatedVersion) {
XophpArray handlers = getHandlers(event);
for (int i = 0; i < handlers.count(); i++) {
XophpCallable hook = (XophpCallable)handlers.Get_at(i);
XophpCallback hook = (XophpCallback)handlers.Get_at(i);
Object retval = callHook(event, hook, args, deprecatedVersion);
if (retval == null) {
continue;

View File

@ -16,6 +16,9 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
package gplx.xowa.mediawiki;
import gplx.Bool_;
import gplx.Err_;
import gplx.Int_;
import gplx.String_;
import gplx.core.tests.Gftest;
import org.junit.Test;
@ -263,7 +266,7 @@ public class XophpArray__tst {
);
}
@Test public void in_array() {
// PHP samples
// PHP examples
XophpArray array;
// Example #1
array = XophpArray.New("Mac", "NT", "Irix", "Linux");
@ -322,7 +325,7 @@ public class XophpArray__tst {
Gftest.Eq__bool_y(shifted == null);
Gftest.Eq__bool_y(array == null);
// PHP samples
// PHP examples
// Example #1
array = XophpArray.New("orange", "banana", "apple", "strawberry");
shifted = (String)XophpArray_.array_shift(array);
@ -333,6 +336,41 @@ public class XophpArray__tst {
, array
);
}
@Test public void array_filter() {
// PHP examples
// Example #1 array_filter() example
XophpArrayTestCallbackOwner callbackOwner = new XophpArrayTestCallbackOwner();
XophpArray array;
array = XophpArray.New().Add("a", 1).Add("b", 2).Add("c", 3).Add("d", 4).Add("e", 5);
fxt.Test__eq
( XophpArray.New().Add("a", 1).Add("c", 3).Add("e", 5)
, XophpArray_.array_filter(array, callbackOwner.NewCallback("array_filter_odd"))
);
array = XophpArray.New(6, 7, 8, 9, 10, 11, 12);
fxt.Test__eq
( XophpArray.New().Add(0, 6).Add(2, 8).Add(4, 10).Add(6, 12)
, XophpArray_.array_filter(array, callbackOwner.NewCallback( "array_filter_even"))
);
// Example #2 array_filter() without callback
array = XophpArray.New().Add(0, "foo").Add(1, false).Add(2, -1).Add(3, null).Add(4, "").Add(5, "0").Add(6, 0);
fxt.Test__eq
( XophpArray.New().Add(0, "foo").Add(2, -1)
, XophpArray_.array_filter(array)
);
// Example #3 array_filter() with flag
array = XophpArray.New().Add("a", 1).Add("b", 2).Add("c", 3).Add("d", 4);
fxt.Test__eq
( XophpArray.New().Add("b", 2)
, XophpArray_.array_filter(array, callbackOwner.NewCallback("array_filter_key"), XophpArray_.ARRAY_FILTER_USE_KEY)
);
fxt.Test__eq
( XophpArray.New().Add("b", 2).Add("d", 4)
, XophpArray_.array_filter(array, callbackOwner.NewCallback("array_filter_both"), XophpArray_.ARRAY_FILTER_USE_BOTH)
);
}
}
class XophpArray__fxt {
public XophpArray Make() {return new XophpArray();}
@ -340,3 +378,20 @@ class XophpArray__fxt {
Gftest.Eq__str(expd.To_str(), actl.To_str());
}
}
class XophpArrayTestCallbackOwner implements XophpCallbackOwner {
public XophpCallback NewCallback(String method) {return new XophpCallback(this, method);}
public Object Call(String method, Object... args) {
switch (method) {
case "array_filter_even":
return Int_.Cast(args[0]) % 2 == 0;
case "array_filter_odd":
return Int_.Cast(args[0]) % 2 == 1;
case "array_filter_key":
return String_.cast(args[0]).equals("b");
case "array_filter_both":
return String_.cast(args[0]).equals("b") || Int_.Cast(args[1]) == 4;
default:
throw Err_.new_unhandled_default(method);
}
}
}