XOMW: Start XomwServiceContainer [#632]

staging
gnosygnu 4 years ago
parent b0e02979ac
commit 2dab6a90be

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
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.
@ -13,22 +13,39 @@ 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.*;
package gplx.xowa.mediawiki;
import gplx.Bool_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Char_;
import gplx.Int_;
import gplx.Object_;
import gplx.Ordered_hash;
import gplx.Ordered_hash_;
import gplx.Type_;
import gplx.core.brys.*;
// NOTE: Object-representation of PHP Array; REF.PHP: https://www.php.net/manual/en/language.types.array.php
import java.util.Iterator;
import java.util.function.Consumer;
// REF.PHP: https://www.php.net/manual/en/language.types.array.php
// Will also will have static functions but "array_" will be stripped; REF.PHP: https://www.php.net/manual/en/ref.array.php
public class XophpArray implements Bry_bfr_able {
public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
private final Ordered_hash hash = Ordered_hash_.New();
private int nxt_idx;
private int newMemberIdx;
public void Clear() {
hash.Clear();
newMemberIdx = 0;
internalPointerIndex = 0;
}
public int Len() {return hash.Len();}
public int count() {return hash.Len();}
public boolean count_bool() {return hash.Len() > 0;}
public boolean isset(String key) {return hash.Has(key);}
public boolean isset(int idx) {return idx >= 0 && idx < hash.Count();}
public boolean in_array(String v) {return Has(v);}
public static boolean is_array(Object val) {
return Type_.Eq_by_obj(val, XophpArray.class);
}
public Object end() {
int len = hash.Len();
return len == 0 ? null : ((XophpArrayItm)hash.Get_at(len - 1)).Val();
@ -54,30 +71,25 @@ public class XophpArray implements Bry_bfr_able {
}
return rv;
}
public void Clear() {
hash.Clear();
nxt_idx = 0;
}
public XophpArray Add(Object val) {
int key = nxt_idx++;
int key = newMemberIdx++;
Set(XophpArrayItm.New_int(key, val));
return this;
}
public XophpArray Add(int key, Object val) {
nxt_idx = key + 1;
newMemberIdx = key + 1;
Set(XophpArrayItm.New_int(key, val));
return this;
}
public XophpArray Add(double key, Object val) {
int key_as_int = (int)key;
nxt_idx = key_as_int + 1;
newMemberIdx = key_as_int + 1;
Set(XophpArrayItm.New_int(key_as_int, val));
return this;
}
public XophpArray Add(boolean key, Object val) {
int key_as_int = key ? 1 : 0;
nxt_idx = key_as_int + 1;
newMemberIdx = key_as_int + 1;
Set(XophpArrayItm.New_int(key_as_int, val));
return this;
}
@ -88,7 +100,7 @@ public class XophpArray implements Bry_bfr_able {
}
else {
Set(XophpArrayItm.New_int(key_as_int, val));
nxt_idx = key_as_int + 1;
newMemberIdx = key_as_int + 1;
}
return this;
}
@ -235,11 +247,32 @@ public class XophpArray implements Bry_bfr_able {
return rv;
}
public static XophpArray New(Object... vals) {
XophpArray rv = new XophpArray();
for (Object val : vals)
rv.Add(val);
return rv;
@Override
public Iterator iterator() {
return new XophpArrayIterator(hash);
}
class XophpArrayIterator implements Iterator<T> {
private final Ordered_hash hash;
private int curIdx;
private int len;
public XophpArrayIterator(Ordered_hash hash) {
this.hash = hash;
this.len = hash.Len();
}
@Override
public boolean hasNext() {
return curIdx < len;
}
@Override
public T next() {
return (T) hash.Get_at(curIdx++);
}
@Override
public void remove() {
throw new XophpRuntimeException("remove not supported");
}
}
// REF.PHP:https://www.php.net/manual/en/function.reset.php
@ -259,5 +292,14 @@ public class XophpArray implements Bry_bfr_able {
return array.internalPointerAdd(1);
}
public static boolean is_array(Object val) {
return Type_.Eq_by_obj(val, XophpArray.class);
}
public static final XophpArray False = null; // handles code like "if ($var === false)" where var is an Object;
public static XophpArray New(Object... vals) {
XophpArray rv = new XophpArray();
for (Object val : vals)
rv.Add(val);
return rv;
}
}

@ -119,7 +119,7 @@ public class XophpArray_ {
return rv;
}
public static XophpArray array_keys(XophpArray array) {
public static XophpArray<String> array_keys(XophpArray array) {
XophpArray rv = XophpArray.New();
int len = array.count();
for (int i = 0; i < len; i++) {

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
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.
@ -13,7 +13,14 @@ 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 XophpError extends Err { public XophpError(String msg) {super(true, "", "", msg);
package gplx.xowa.mediawiki;
import gplx.Err;
// REF.PHP:https://www.php.net/manual/en/class.exception.php
public class XophpException extends Err {
public XophpException(String message) {this(message, 0, null);}
public XophpException(String message, int code, XophpException previous) {
super(true, "", "", message);
}
}

@ -15,8 +15,8 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.xowa.mediawiki;
public class XophpFatalError extends XophpError {
public XophpFatalError(String msg) {
public class XophpFatalException extends XophpException {
public XophpFatalException(String msg) {
super(msg);
}
}

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
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.
@ -13,7 +13,10 @@ 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 XophpRuntimeException extends XophpError { public XophpRuntimeException(String msg) {super(msg);
package gplx.xowa.mediawiki;
public class XophpRuntimeException extends XophpException {
public XophpRuntimeException(String message) {super(message);}
public XophpRuntimeException(String message, int code, XophpException previous) {
super(message, code, previous);
}
}

@ -268,6 +268,9 @@ public class XophpString_ implements XophpCallbackOwner {
public static byte[] strtr(byte[] src, byte find, byte repl) {
return Bry_.Replace(src, 0, src.length, find, repl);
}
public static String strtr(String src, String find, String repl) {
return String_.Replace(src, find, repl);
}
public static byte[] str_replace(byte find, byte repl, byte[] src) {
return Bry_.Replace(src, 0, src.length, find, repl);
}
@ -322,10 +325,10 @@ public class XophpString_ implements XophpCallbackOwner {
byte nxt_byte = pad_bry[i + 1];
if (nxt_byte == Byte_ascii.Dot) {
if (i == 0) {
throw new XophpError(".. found but at start of String; src=" + pad_str);
throw new XophpException(".. found but at start of String; src=" + pad_str);
}
else if (i == pad_len - 2) {
throw new XophpError(".. found but at end of String; src=" + pad_str);
throw new XophpException(".. found but at end of String; src=" + pad_str);
}
else {
nxt_byte = pad_bry[i + 2];
@ -339,7 +342,7 @@ public class XophpString_ implements XophpCallbackOwner {
continue;
}
else {
throw new XophpError(".. found but next byte must be greater than previous byte; src=" + pad_str);
throw new XophpException(".. found but next byte must be greater than previous byte; src=" + pad_str);
}
}
}

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
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.
@ -13,8 +13,13 @@ 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.Wikibase.lib.includes.Store; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.extensions.*; import gplx.xowa.mediawiki.extensions.Wikibase.*; import gplx.xowa.mediawiki.extensions.Wikibase.lib.*; import gplx.xowa.mediawiki.extensions.Wikibase.lib.includes.*;
package gplx.xowa.mediawiki.extensions.Wikibase.lib.includes.Store;
import gplx.xowa.mediawiki.XophpRuntimeException;
// REF.WBASE:2020-01-19
class XomwPropertyOrderProviderException extends XophpRuntimeException { public XomwPropertyOrderProviderException(String msg) {super(msg);
class XomwPropertyOrderProviderException extends XophpRuntimeException {
public XomwPropertyOrderProviderException(String message) {
super(message);
}
}

@ -22,7 +22,7 @@ import gplx.xowa.mediawiki.XophpArray;
import gplx.xowa.mediawiki.XophpArray_;
import gplx.xowa.mediawiki.XophpCallback;
import gplx.xowa.mediawiki.XophpCallbackOwner;
import gplx.xowa.mediawiki.XophpFatalError;
import gplx.xowa.mediawiki.XophpFatalException;
import gplx.xowa.mediawiki.XophpObject_;
import gplx.xowa.mediawiki.XophpString_;
import gplx.xowa.mediawiki.XophpType_;
@ -221,7 +221,7 @@ public class XomwHooks {
// Process the return value.
if (XophpString_.is_string(retval)) {
// String returned means error.
throw new XophpFatalError((String)retval);
throw new XophpFatalException((String)retval);
} else if (XophpObject_.is_false(retval)) {
// False was returned. Stop processing, but no error.
return false;

@ -14,13 +14,13 @@ 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.xowa.mediawiki.XomwEnv;
import gplx.xowa.mediawiki.includes.interwiki.XomwInterwikiLookup;
import gplx.xowa.mediawiki.includes.title.XomwMediaWikiTitleCodec;
import gplx.xowa.mediawiki.languages.XomwLanguage;
// MW.SRC:1.33.1
/**
* MediaWikiServices is the service locator for the application scope of MediaWiki.
* Its implemented as a simple configurable DI container.

@ -16,6 +16,12 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
package gplx.xowa.mediawiki.includes;
// MW.SRC:1.33.1
import gplx.xowa.mediawiki.XophpArray;
import gplx.xowa.mediawiki.XophpArray_;
import gplx.xowa.mediawiki.XophpObject_;
import gplx.xowa.mediawiki.XophpString_;
/**
* The WebRequest class encapsulates getting at data passed in the
* URL or via a POSTed form stripping illegal input characters and
@ -24,65 +30,67 @@ package gplx.xowa.mediawiki.includes;
* @ingroup HTTP
*/
public class XomwWebRequest {
// protected $data, $headers = [];
//
// /**
// * Flag to make WebRequest::getHeader return an array of values.
// * @since 1.26
// */
// const GETHEADER_LIST = 1;
//
// /**
// * The unique request ID.
// * @var string
// */
// private static $reqId;
//
// /**
// * Lazy-init response object
// * @var WebResponse
// */
// private $response;
//
// /**
// * Cached client IP address
// * @var string
// */
// private $ip;
//
// /**
// * The timestamp of the start of the request, with microsecond precision.
// * @var float
// */
// protected $requestTime;
//
// /**
// * Cached URL protocol
// * @var string
// */
// protected $protocol;
//
protected XophpArray data, headers = XophpArray.New();
/**
* Flag to make WebRequest::getHeader return an array of values.
* @since 1.26
*/
public static final int GETHEADER_LIST = 1;
/**
* The unique request ID.
* @var string
*/
private static String reqId;
/**
* Lazy-init response object
* @var WebResponse
*/
// private XomwWebResponse response;
/**
* Cached client IP address
* @var string
*/
private String ip;
/**
* The timestamp of the start of the request, with microsecond precision.
* @var float
*/
protected float requestTime;
/**
* Cached URL protocol
* @var string
*/
protected String protocol;
// /**
// * @var SessionId|null Session ID to use for this
// * request. We can't save the session directly due to reference cycles not
// * working too well (slow GC in Zend and never collected in HHVM).
// */
// protected $sessionId = null;
//
// /** @var bool Whether this HTTP request is "safe" (even if it is an HTTP post) */
// protected $markedAsSafe = false;
//
// /**
// * @codeCoverageIgnore
// */
// public function __construct() {
// $this->requestTime = $_SERVER['REQUEST_TIME_FLOAT'];
//
// // POST overrides GET data
// // We don't use $_REQUEST here to avoid interference from cookies...
// $this->data = $_POST + $_GET;
// }
//
/** @var bool Whether this HTTP request is "safe" (even if it is an HTTP post) */
protected boolean markedAsSafe = false;
private XophpArray _POST = XophpArray.New(); // XOMW:PHP_GLOBAL
private XophpArray _GET = XophpArray.New(); // XOMW:PHP_GLOBAL
/**
* @codeCoverageIgnore
*/
public XomwWebRequest() {
// this.requestTime = $_SERVER['REQUEST_TIME_FLOAT'];
// POST overrides GET data
// We don't use $_REQUEST here to avoid interference from cookies...
this.data = XophpArray_.array_merge(_POST, _GET);
}
// /**
// * Extract relevant query arguments from the http request uri's path
// * to be merged with the normal php provided query arguments.
@ -126,7 +134,7 @@ public class XomwWebRequest {
// $router = new PathRouter;
//
// // Raw PATH_INFO style
// $router->add( "$wgScript/$1" );
// $router.add("$wgScript/$1");
//
// if (isset($_SERVER['SCRIPT_NAME'])
// && preg_match('/\.php/', $_SERVER['SCRIPT_NAME'])
@ -134,31 +142,31 @@ public class XomwWebRequest {
// # Check for SCRIPT_NAME, we handle index.php explicitly
// # But we do have some other .php files such as img_auth.php
// # Don't let root article paths clober the parsing for them
// $router->add( $_SERVER['SCRIPT_NAME'] . "/$1" );
// $router.add($_SERVER['SCRIPT_NAME'] . "/$1");
// }
//
// global $wgArticlePath;
// if ($wgArticlePath) {
// $router->add( $wgArticlePath );
// $router.add($wgArticlePath);
// }
//
// global $wgActionPaths;
// if ($wgActionPaths) {
// $router->add( $wgActionPaths, [ 'action' => '$key' ] );
// $router.add($wgActionPaths, [ 'action' => '$key' ]);
// }
//
// global $wgVariantArticlePath;
// if ($wgVariantArticlePath) {
// $router->add( $wgVariantArticlePath,
// $router.add($wgVariantArticlePath,
// [ 'variant' => '$2' ],
// [ '$2' => MediaWikiServices::getInstance()->getContentLanguage()->
// [ '$2' => MediaWikiServices::getInstance().getContentLanguage().
// getVariants() ]
// );
// }
//
// Hooks::run('WebRequestPathInfoRouter', [ $router ]);
//
// $matches = $router->parse( $path );
// $matches = $router.parse($path);
// }
// } elseif ($wgUsePathInfo) {
// if (isset($_SERVER['ORIG_PATH_INFO']) && $_SERVER['ORIG_PATH_INFO'] != '') {
@ -246,7 +254,7 @@ public class XomwWebRequest {
// * @since 1.25
// */
// public function getElapsedTime() {
// return microtime( true ) - $this->requestTime;
// return microtime(true) - this.requestTime;
// }
//
// /**
@ -283,10 +291,10 @@ public class XomwWebRequest {
// * @return string
// */
// public function getProtocol() {
// if ( $this->protocol === null ) {
// $this->protocol = self::detectProtocol();
// if (this.protocol === null) {
// this.protocol = self::detectProtocol();
// }
// return $this->protocol;
// return this.protocol;
// }
//
// /**
@ -304,7 +312,7 @@ public class XomwWebRequest {
//
// $matches = self::getPathInfo('title');
// foreach ($matches as $key => $val) {
// $this->data[$key] = $_GET[$key] = $_REQUEST[$key] = $val;
// this.data[$key] = $_GET[$key] = $_REQUEST[$key] = $val;
// }
// }
//
@ -347,42 +355,42 @@ public class XomwWebRequest {
// public function normalizeUnicode($data) {
// if (is_array($data)) {
// foreach ($data as $key => $val) {
// $data[$key] = $this->normalizeUnicode( $val );
// $data[$key] = this.normalizeUnicode($val);
// }
// } else {
// $contLang = MediaWikiServices::getInstance()->getContentLanguage();
// $data = $contLang ? $contLang->normalize( $data ) :
// $contLang = MediaWikiServices::getInstance().getContentLanguage();
// $data = $contLang ? $contLang.normalize($data) :
// UtfNormal\Validator::cleanUp($data);
// }
// return $data;
// }
//
// /**
// * Fetch a value from the given array or return $default if it's not set.
// *
// * @param array $arr
// * @param string $name
// * @param mixed $default
// * @return mixed
// */
// private function getGPCVal( $arr, $name, $default ) {
// # PHP is so nice to not touch input data, except sometimes:
// # https://secure.php.net/variables.external#language.variables.external.dot-in-names
// # Work around PHP *feature* to avoid *bugs* elsewhere.
// $name = strtr( $name, '.', '_' );
// if ( isset( $arr[$name] ) ) {
// $data = $arr[$name];
// if ( isset( $_GET[$name] ) && is_string( $data ) ) {
// # Check for alternate/legacy character encoding.
// $contLang = MediaWikiServices::getInstance()->getContentLanguage();
// $data = $contLang->checkTitleEncoding( $data );
// }
// $data = $this->normalizeUnicode( $data );
// return $data;
// } else {
// return $default;
// }
// }
/**
* Fetch a value from the given array or return $default if it's not set.
*
* @param array $arr
* @param string $name
* @param mixed $default
* @return mixed
*/
private Object getGPCVal(XophpArray arr, String name, Object defaultVal) {
// PHP is so nice to not touch input data, except sometimes:
// https://secure.php.net/variables.external#language.variables.external.dot-in-names
// Work around PHP *feature* to avoid *bugs* elsewhere.
name = XophpString_.strtr(name, ".", "_");
if (XophpArray_.isset(arr, name)) {
Object data = arr.Get_by(name);
if (XophpArray_.isset(_GET, name) && XophpString_.is_string(data)) {
// Check for alternate/legacy character encoding.
// $contLang = MediaWikiServices::getInstance().getContentLanguage();
// $data = $contLang.checkTitleEncoding($data);
}
// $data = this.normalizeUnicode($data);
return data;
} else {
return defaultVal;
}
}
//
// /**
// * Fetch a scalar from the input without normalization, or return $default
@ -398,8 +406,8 @@ public class XomwWebRequest {
// */
// public function getRawVal($name, $default = null) {
// $name = strtr($name, '.', '_'); // See comment in self::getGPCVal()
// if ( isset( $this->data[$name] ) && !is_array( $this->data[$name] ) ) {
// $val = $this->data[$name];
// if (isset(this.data[$name]) && !is_array(this.data[$name])) {
// $val = this.data[$name];
// } else {
// $val = $default;
// }
@ -409,29 +417,30 @@ public class XomwWebRequest {
// return (string)$val;
// }
// }
//
// /**
// * Fetch a scalar from the input or return $default if it's not set.
// * Returns a string. Arrays are discarded. Useful for
// * non-freeform text inputs (e.g. predefined internal text keys
// * selected by a drop-down menu). For freeform input, see getText().
// *
// * @param string $name
// * @param string|null $default Optional default (or null)
// * @return string|null
// */
// public function getVal( $name, $default = null ) {
// $val = $this->getGPCVal( $this->data, $name, $default );
// if ( is_array( $val ) ) {
// $val = $default;
// }
// if ( is_null( $val ) ) {
// return $val;
// } else {
// return (string)$val;
// }
// }
//
/**
* Fetch a scalar from the input or return $default if it's not set.
* Returns a string. Arrays are discarded. Useful for
* non-freeform text inputs (e.g. predefined internal text keys
* selected by a drop-down menu). For freeform input, see getText().
*
* @param string $name
* @param string|null $default Optional default (or null)
* @return string|null
*/
public String getVal(String name) {return getVal(name, null);}
public String getVal(String name, String defaultVal) {
Object val = this.getGPCVal(this.data, name, defaultVal);
if (XophpArray.is_array(val)) {
val = defaultVal;
}
if (XophpObject_.is_null(val)) {
return null;
} else {
return (String)val;
}
}
// /**
// * Set an arbitrary value into our get/post data.
// *
@ -440,8 +449,8 @@ public class XomwWebRequest {
// * @return mixed Old value if one was present, null otherwise
// */
// public function setVal($key, $value) {
// $ret = $this->data[$key] ?? null;
// $this->data[$key] = $value;
// $ret = this.data[$key] ?? null;
// this.data[$key] = $value;
// return $ret;
// }
//
@ -452,11 +461,11 @@ public class XomwWebRequest {
// * @return mixed Old value if one was present, null otherwise
// */
// public function unsetVal($key) {
// if ( !isset( $this->data[$key] ) ) {
// if (!isset(this.data[$key])) {
// $ret = null;
// } else {
// $ret = $this->data[$key];
// unset( $this->data[$key] );
// $ret = this.data[$key];
// unset(this.data[$key]);
// }
// return $ret;
// }
@ -471,7 +480,7 @@ public class XomwWebRequest {
// * @return array|null
// */
// public function getArray($name, $default = null) {
// $val = $this->getGPCVal( $this->data, $name, $default );
// $val = this.getGPCVal(this.data, $name, $default);
// if (is_null($val)) {
// return null;
// } else {
@ -490,7 +499,7 @@ public class XomwWebRequest {
// * @return array Array of ints
// */
// public function getIntArray($name, $default = null) {
// $val = $this->getArray( $name, $default );
// $val = this.getArray($name, $default);
// if (is_array($val)) {
// $val = array_map('intval', $val);
// }
@ -507,7 +516,7 @@ public class XomwWebRequest {
// * @return int
// */
// public function getInt($name, $default = 0) {
// return intval( $this->getRawVal( $name, $default ) );
// return intval(this.getRawVal($name, $default));
// }
//
// /**
@ -519,7 +528,7 @@ public class XomwWebRequest {
// * @return int|null
// */
// public function getIntOrNull($name) {
// $val = $this->getRawVal( $name );
// $val = this.getRawVal($name);
// return is_numeric($val)
// ? intval($val)
// : null;
@ -536,7 +545,7 @@ public class XomwWebRequest {
// * @return float
// */
// public function getFloat($name, $default = 0.0) {
// return floatval( $this->getRawVal( $name, $default ) );
// return floatval(this.getRawVal($name, $default));
// }
//
// /**
@ -549,7 +558,7 @@ public class XomwWebRequest {
// * @return bool
// */
// public function getBool($name, $default = false) {
// return (bool)$this->getRawVal( $name, $default );
// return (bool)this.getRawVal($name, $default);
// }
//
// /**
@ -562,8 +571,8 @@ public class XomwWebRequest {
// * @return bool
// */
// public function getFuzzyBool($name, $default = false) {
// return $this->getBool( $name, $default )
// && strcasecmp( $this->getRawVal( $name ), 'false' ) !== 0;
// return this.getBool($name, $default)
// && strcasecmp(this.getRawVal($name), 'false') !== 0;
// }
//
// /**
@ -577,7 +586,7 @@ public class XomwWebRequest {
// public function getCheck($name) {
// # Checkboxes and buttons are only present when clicked
// # Presence connotes truth, absence false
// return $this->getRawVal( $name, null ) !== null;
// return this.getRawVal($name, null) !== null;
// }
//
// /**
@ -591,7 +600,7 @@ public class XomwWebRequest {
// * @return string
// */
// public function getText($name, $default = '') {
// $val = $this->getVal( $name, $default );
// $val = this.getVal($name, $default);
// return str_replace("\r\n", "\n", $val);
// }
//
@ -605,12 +614,12 @@ public class XomwWebRequest {
// public function getValues() {
// $names = func_get_args();
// if (count($names) == 0) {
// $names = array_keys( $this->data );
// $names = array_keys(this.data);
// }
//
// $retVal = [];
// foreach ($names as $name) {
// $value = $this->getGPCVal( $this->data, $name, null );
// $value = this.getGPCVal(this.data, $name, null);
// if (!is_null($value)) {
// $retVal[$name] = $value;
// }
@ -625,7 +634,7 @@ public class XomwWebRequest {
// * @return array
// */
// public function getValueNames($exclude = []) {
// return array_diff( array_keys( $this->getValues() ), $exclude );
// return array_diff(array_keys(this.getValues()), $exclude);
// }
//
// /**
@ -669,10 +678,10 @@ public class XomwWebRequest {
// * @return string
// */
// public function getRawPostString() {
// if ( !$this->wasPosted() ) {
// if (!this.wasPosted()) {
// return '';
// }
// return $this->getRawInput();
// return this.getRawInput();
// }
//
// /**
@ -709,7 +718,7 @@ public class XomwWebRequest {
// * @return bool
// */
// public function wasPosted() {
// return $this->getMethod() == 'POST';
// return this.getMethod() == 'POST';
// }
//
// /**
@ -723,15 +732,15 @@ public class XomwWebRequest {
// * @return Session
// */
// public function getSession() {
// if ( $this->sessionId !== null ) {
// $session = SessionManager::singleton()->getSessionById( (string)$this->sessionId, true, $this );
// if (this.sessionId !== null) {
// $session = SessionManager::singleton().getSessionById((string)this.sessionId, true, this);
// if ($session) {
// return $session;
// }
// }
//
// $session = SessionManager::singleton()->getSessionForRequest( $this );
// $this->sessionId = $session->getSessionId();
// $session = SessionManager::singleton().getSessionForRequest(this);
// this.sessionId = $session.getSessionId();
// return $session;
// }
//
@ -742,7 +751,7 @@ public class XomwWebRequest {
// * @param SessionId $sessionId
// */
// public function setSessionId(SessionId $sessionId) {
// $this->sessionId = $sessionId;
// this.sessionId = $sessionId;
// }
//
// /**
@ -752,7 +761,7 @@ public class XomwWebRequest {
// * @return SessionId|null
// */
// public function getSessionId() {
// return $this->sessionId;
// return this.sessionId;
// }
//
// /**
@ -768,7 +777,7 @@ public class XomwWebRequest {
// global $wgCookiePrefix;
// $prefix = $wgCookiePrefix;
// }
// return $this->getGPCVal( $_COOKIE, $prefix . $key, $default );
// return this.getGPCVal($_COOKIE, $prefix . $key, $default);
// }
//
// /**
@ -839,7 +848,7 @@ public class XomwWebRequest {
// * @return string
// */
// public function getFullRequestURL() {
// return wfGetServerUrl( PROTO_CURRENT ) . $this->getRequestURL();
// return wfGetServerUrl(PROTO_CURRENT) . this.getRequestURL();
// }
//
// /**
@ -848,7 +857,7 @@ public class XomwWebRequest {
// * @return string
// */
// public function appendQueryValue($key, $value) {
// return $this->appendQueryArray( [ $key => $value ] );
// return this.appendQueryArray([ $key => $value ]);
// }
//
// /**
@ -858,7 +867,7 @@ public class XomwWebRequest {
// * @return string
// */
// public function appendQueryArray($array) {
// $newquery = $this->getQueryValues();
// $newquery = this.getQueryValues();
// unset($newquery['title']);
// $newquery = array_merge($newquery, $array);
//
@ -877,12 +886,12 @@ public class XomwWebRequest {
// public function getLimitOffset($deflimit = 50, $optionname = 'rclimit') {
// global $wgUser;
//
// $limit = $this->getInt( 'limit', 0 );
// $limit = this.getInt('limit', 0);
// if ($limit < 0) {
// $limit = 0;
// }
// if (($limit == 0) && ($optionname != '')) {
// $limit = $wgUser->getIntOption( $optionname );
// $limit = $wgUser.getIntOption($optionname);
// }
// if ($limit <= 0) {
// $limit = $deflimit;
@ -891,7 +900,7 @@ public class XomwWebRequest {
// $limit = 5000; # We have *some* limits...
// }
//
// $offset = $this->getInt( 'offset', 0 );
// $offset = this.getInt('offset', 0);
// if ($offset < 0) {
// $offset = 0;
// }
@ -906,8 +915,8 @@ public class XomwWebRequest {
// * @return string|null String or null if no such file.
// */
// public function getFileTempname($key) {
// $file = new WebRequestUpload( $this, $key );
// return $file->getTempName();
// $file = new WebRequestUpload(this, $key);
// return $file.getTempName();
// }
//
// /**
@ -917,8 +926,8 @@ public class XomwWebRequest {
// * @return int
// */
// public function getUploadError($key) {
// $file = new WebRequestUpload( $this, $key );
// return $file->getError();
// $file = new WebRequestUpload(this, $key);
// return $file.getError();
// }
//
// /**
@ -933,8 +942,8 @@ public class XomwWebRequest {
// * @return string|null String or null if no such file.
// */
// public function getFileName($key) {
// $file = new WebRequestUpload( $this, $key );
// return $file->getName();
// $file = new WebRequestUpload(this, $key);
// return $file.getName();
// }
//
// /**
@ -944,7 +953,7 @@ public class XomwWebRequest {
// * @return WebRequestUpload
// */
// public function getUpload($key) {
// return new WebRequestUpload( $this, $key );
// return new WebRequestUpload(this, $key);
// }
//
// /**
@ -955,33 +964,33 @@ public class XomwWebRequest {
// */
// public function response() {
// /* Lazy initialization of response object for this request */
// if ( !is_object( $this->response ) ) {
// $class = ( $this instanceof FauxRequest ) ? FauxResponse::class : WebResponse::class;
// $this->response = new $class();
// if (!is_object(this.response)) {
// $class = (this instanceof FauxRequest) ? FauxResponse::class : WebResponse::class;
// this.response = new $class();
// }
// return $this->response;
// return this.response;
// }
//
// /**
// * Initialise the header list
// */
// protected function initHeaders() {
// if ( count( $this->headers ) ) {
// if (count(this.headers)) {
// return;
// }
//
// $apacheHeaders = function_exists('apache_request_headers') ? apache_request_headers() : false;
// if ($apacheHeaders) {
// foreach ($apacheHeaders as $tempName => $tempValue) {
// $this->headers[strtoupper( $tempName )] = $tempValue;
// this.headers[strtoupper($tempName)] = $tempValue;
// }
// } else {
// foreach ($_SERVER as $name => $value) {
// if (substr($name, 0, 5) === 'HTTP_') {
// $name = str_replace('_', '-', substr($name, 5));
// $this->headers[$name] = $value;
// this.headers[$name] = $value;
// } elseif ($name === 'CONTENT_LENGTH') {
// $this->headers['CONTENT-LENGTH'] = $value;
// this.headers['CONTENT-LENGTH'] = $value;
// }
// }
// }
@ -993,8 +1002,8 @@ public class XomwWebRequest {
// * @return array Mapping header name to its value
// */
// public function getAllHeaders() {
// $this->initHeaders();
// return $this->headers;
// this.initHeaders();
// return this.headers;
// }
//
// /**
@ -1010,12 +1019,12 @@ public class XomwWebRequest {
// * WebRequest::GETHEADER_LIST flag was set.
// */
// public function getHeader($name, $flags = 0) {
// $this->initHeaders();
// this.initHeaders();
// $name = strtoupper($name);
// if ( !isset( $this->headers[$name] ) ) {
// if (!isset(this.headers[$name])) {
// return false;
// }
// $value = $this->headers[$name];
// $value = this.headers[$name];
// if ($flags & self::GETHEADER_LIST) {
// $value = array_map('trim', explode(',', $value));
// }
@ -1025,23 +1034,23 @@ public class XomwWebRequest {
// /**
// * Get data from the session
// *
// * @note Prefer $this->getSession() instead if making multiple calls.
// * @note Prefer this.getSession() instead if making multiple calls.
// * @param string $key Name of key in the session
// * @return mixed
// */
// public function getSessionData($key) {
// return $this->getSession()->get( $key );
// return this.getSession().get($key);
// }
//
// /**
// * Set session data
// *
// * @note Prefer $this->getSession() instead if making multiple calls.
// * @note Prefer this.getSession() instead if making multiple calls.
// * @param string $key Name of key in the session
// * @param mixed $data
// */
// public function setSessionData($key, $data) {
// $this->getSession()->set( $key, $data );
// this.getSession().set($key, $data);
// }
//
// /**
@ -1057,11 +1066,11 @@ public class XomwWebRequest {
// public function checkUrlExtension($extWhitelist = []) {
// $extWhitelist[] = 'php';
// if (IEUrlExtension::areServerVarsBad($_SERVER, $extWhitelist)) {
// if ( !$this->wasPosted() ) {
// if (!this.wasPosted()) {
// $newUrl = IEUrlExtension::fixUrlForIE6(
// $this->getFullRequestURL(), $extWhitelist );
// this.getFullRequestURL(), $extWhitelist);
// if ($newUrl !== false) {
// $this->doSecurityRedirect( $newUrl );
// this.doSecurityRedirect($newUrl);
// return false;
// }
// }
@ -1117,7 +1126,7 @@ public class XomwWebRequest {
// public function getAcceptLang() {
// // Modified version of code found at
// // http://www.thefutureoftheweb.com/blog/use-accept-language-header
// $acceptLang = $this->getHeader( 'Accept-Language' );
// $acceptLang = this.getHeader('Accept-Language');
// if (!$acceptLang) {
// return [];
// }
@ -1195,21 +1204,21 @@ public class XomwWebRequest {
// global $wgUsePrivateIPs;
//
// # Return cached result
// if ( $this->ip !== null ) {
// return $this->ip;
// if (this.ip !== null) {
// return this.ip;
// }
//
// # collect the originating ips
// $ip = $this->getRawIP();
// $ip = this.getRawIP();
// if (!$ip) {
// throw new MWException('Unable to determine IP.');
// }
//
// # Append XFF
// $forwardedFor = $this->getHeader( 'X-Forwarded-For' );
// $forwardedFor = this.getHeader('X-Forwarded-For');
// if ($forwardedFor !== false) {
// $proxyLookup = MediaWikiServices::getInstance()->getProxyLookup();
// $isConfigured = $proxyLookup->isConfiguredProxy( $ip );
// $proxyLookup = MediaWikiServices::getInstance().getProxyLookup();
// $isConfigured = $proxyLookup.isConfiguredProxy($ip);
// $ipchain = array_map('trim', explode(',', $forwardedFor));
// $ipchain = array_reverse($ipchain);
// array_unshift($ipchain, $ip);
@ -1222,14 +1231,14 @@ public class XomwWebRequest {
// foreach ($ipchain as $i => $curIP) {
// $curIP = IP::sanitizeIP(IP::canonicalize($curIP));
// if (!$curIP || !isset($ipchain[$i + 1]) || $ipchain[$i + 1] === 'unknown'
// || !$proxyLookup->isTrustedProxy( $curIP )
// || !$proxyLookup.isTrustedProxy($curIP)
// ) {
// break; // IP is not valid/trusted or does not point to anything
// }
// if (
// IP::isPublic($ipchain[$i + 1]) ||
// $wgUsePrivateIPs ||
// $proxyLookup->isConfiguredProxy( $curIP ) // T50919; treat IP as sane
// $proxyLookup.isConfiguredProxy($curIP) // T50919; treat IP as sane
// ) {
// // Follow the next IP according to the proxy
// $nextIP = IP::canonicalize($ipchain[$i + 1]);
@ -1254,7 +1263,7 @@ public class XomwWebRequest {
// }
//
// wfDebug("IP: $ip\n");
// $this->ip = $ip;
// this.ip = $ip;
// return $ip;
// }
//
@ -1264,7 +1273,7 @@ public class XomwWebRequest {
// * @since 1.21
// */
// public function setIP($ip) {
// $this->ip = $ip;
// this.ip = $ip;
// }
//
// /**
@ -1306,11 +1315,11 @@ public class XomwWebRequest {
// * @since 1.28
// */
// public function isSafeRequest() {
// if ( $this->markedAsSafe && $this->wasPosted() ) {
// if (this.markedAsSafe && this.wasPosted()) {
// return true; // marked as a "safe" POST
// }
//
// return $this->hasSafeMethod();
// return this.hasSafeMethod();
// }
//
// /**
@ -1324,6 +1333,6 @@ public class XomwWebRequest {
// * @since 1.28
// */
// public function markAsSafeRequest() {
// $this->markedAsSafe = true;
// this.markedAsSafe = true;
// }
}

@ -16,6 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
package gplx.xowa.mediawiki.includes.context;
import gplx.xowa.mediawiki.XophpObject_;
import gplx.xowa.mediawiki.XophpString_;
import gplx.xowa.mediawiki.includes.XomwOutputPage;
import gplx.xowa.mediawiki.includes.XomwTitle;
import gplx.xowa.mediawiki.includes.XomwWebRequest;
@ -105,22 +106,23 @@ public class XomwRequestContext { // implements IContextSource, MutableContext
// this.request = $request;
// }
// /**
// * @return WebRequest
// */
// public XomwWebRequest getRequest() {
// if (this.request === null) {
/**
* @return WebRequest
*/
public XomwWebRequest getRequest() {
if (XophpObject_.is_null(this.request)) {
// XOMW:skip
// global $wgCommandLineMode;
// // create the WebRequest object on the fly
// if ($wgCommandLineMode) {
// this.request = new FauxRequest([]);
// } else {
// this.request = new WebRequest();
// }
// }
//
// return this.request;
this.request = new XomwWebRequest();
// }
}
return this.request;
}
// /**
// * @deprecated since 1.27 use a StatsdDataFactory from MediaWikiServices (preferably injected)
@ -264,7 +266,7 @@ public class XomwRequestContext { // implements IContextSource, MutableContext
*/
public XomwUser getUser() {
if (XophpObject_.is_null(this.user)) {
// this.user = XomwUser.newFromSession(this.getRequest());
this.user = XomwUser.newFromSession(this.getRequest());
}
return this.user;
@ -327,18 +329,18 @@ public class XomwRequestContext { // implements IContextSource, MutableContext
this.recursion = true;
try {
// $request = this.getRequest();
// $user = this.getUser();
//
// $code = $request.getVal('uselang', 'user');
// if ($code === 'user') {
// $code = $user.getOption('language');
// }
request = this.getRequest();
user = this.getUser();
String code = request.getVal("uselang", "user");
if (XophpString_.eq(code, "user")) {
// code = user.getOption("language");
}
// $code = self::sanitizeLangCode($code);
//
// XomwHooks.run("UserGetLanguageObject", XophpArray.New(user, &$code, this));
//
// if ($code === this.getConfig().get('LanguageCode')) {
// if ($code === this.getConfig().get("LanguageCode")) {
// this.lang = MediaWikiServices::getInstance().getContentLanguage();
// } else {
// $obj = Language::factory($code);

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
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.
@ -13,7 +13,8 @@ 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.dao; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
package gplx.xowa.mediawiki.includes.dao;
/**
* Interface for database access objects.
*
@ -46,4 +47,22 @@ package gplx.xowa.mediawiki.includes.dao; import gplx.*; import gplx.xowa.*; imp
* @since 1.20
*/
public interface XomwIDBAccessObject {
/** Constants for object loading bitfield flags (higher => higher QoS) */
/** @var int Read from a replica DB/non-quorum */
public static int READ_NORMAL = 0;
/** @var int Read from the master/quorum */
public static int READ_LATEST = 1;
/* @var int Read from the master/quorum and lock out other writers */
public static int READ_LOCKING = READ_LATEST | 2; // READ_LATEST (1) and "LOCK IN SHARE MODE" (2)
/** @var int Read from the master/quorum and lock out other writers and locking readers */
public static int READ_EXCLUSIVE = READ_LOCKING | 4; // READ_LOCKING (3) and "FOR UPDATE" (4)
/** @var int Read from a replica DB or without a quorum, using the master/quorum on miss */
public static int READ_LATEST_IMMUTABLE = 8;
// Convenience constant for tracking how data was loaded (higher => higher QoS)
public static int READ_NONE = -1; // not loaded yet (or the object was cleared)
}

@ -0,0 +1,38 @@
/*
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.includes.libs.services;
// MW.SRC:1.33.1
/**
* DestructibleService defines a standard interface for shutting down a service instance.
* The intended use is for a service container to be able to shut down services that should
* no longer be used, and allow such services to release any system resources.
*
* @note There is no expectation that services will be destroyed when the process (or web request)
* terminates.
*/
public interface XomwDestructibleService {
/**
* Notifies the service object that it should expect to no longer be used, and should release
* any system resources it may own. The behavior of all service methods becomes undefined after
* destroy() has been called. It is recommended that implementing classes should throw an
* exception when service methods are accessed after destroy() has been called.
*/
public void destroy();
}

@ -0,0 +1,21 @@
package gplx.xowa.mediawiki.includes.libs.services;
import gplx.String_;
import gplx.xowa.mediawiki.XophpException;
import gplx.xowa.mediawiki.XophpRuntimeException;
/**
* Exception thrown when the requested service is not known.
*/
class XomwNoSuchServiceException extends XophpRuntimeException {
/**
* @param string $serviceName
* @param Exception|null $previous
*/
public XomwNoSuchServiceException(String serviceName) {this(serviceName, null);}
public XomwNoSuchServiceException(String serviceName, XophpException previous) {
super(String_.Format("No such service: {0}", serviceName), 0, previous);
}
}

@ -0,0 +1,464 @@
/*
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.includes.libs.services;
// MW.SRC:1.33.1
import gplx.xowa.mediawiki.XophpArray;
import gplx.xowa.mediawiki.XophpArray_;
import gplx.xowa.mediawiki.XophpCallbackOwner;
import gplx.xowa.mediawiki.XophpObject_;
import gplx.xowa.mediawiki.XophpType_;
/**
* ServiceContainer provides a generic service to manage named services using
* lazy instantiation based on instantiator callback functions.
*
* Services managed by an instance of ServiceContainer may or may not implement
* a common interface.
*
* @note When using ServiceContainer to manage a set of services, consider
* creating a wrapper or a subclass that provides access to the services via
* getter methods with more meaningful names and more specific return type
* declarations.
*
* @see docs/injection.txt for an overview of using dependency injection in the
* MediaWiki code base.
*/
public class XomwServiceContainer implements XomwDestructibleService {
/**
* @var object[]
*/
private XophpArray<Object> services = new XophpArray();
/**
* @var callable[]
*/
private XophpArray<XophpCallbackOwner> serviceInstantiators = new XophpArray();
/**
* @var callable[][]
*/
private XophpArray<XophpCallbackOwner[]> serviceManipulators = new XophpArray();
/**
* @var bool[] disabled status, per service name
*/
private XophpArray<Boolean> disabled = new XophpArray();
/**
* @var array
*/
private XophpArray extraInstantiationParams;
/**
* @var bool
*/
private boolean destroyed = false;
/**
* @param array $extraInstantiationParams Any additional parameters to be passed to the
* instantiator function when creating a service. This is typically used to provide
* access to additional ServiceContainers or Config objects.
*/
public XomwServiceContainer() {this(new XophpArray());}
public XomwServiceContainer(XophpArray extraInstantiationParams) {
this.extraInstantiationParams = extraInstantiationParams;
}
/**
* Destroys all contained service instances that implement the DestructibleService
* interface. This will render all services obtained from this ServiceContainer
* instance unusable. In particular, this will disable access to the storage backend
* via any of these services. Any future call to getService() will throw an exception.
*
* @see resetGlobalInstance()
*/
public void destroy() {
for (String name : this.getServiceNames()) {
Object service = this.peekService(name);
if (service != null && XophpType_.instance_of(service, XomwDestructibleService.class)) {
((XomwDestructibleService)service).destroy();
}
}
// Break circular references due to the this reference in closures, by
// erasing the instantiator array. This allows the ServiceContainer to
// be deleted when it goes out of scope.
this.serviceInstantiators = new XophpArray();
// Also remove the services themselves, to avoid confusion.
this.services = new XophpArray();
this.destroyed = true;
}
// /**
// * @param array $wiringFiles A list of PHP files to load wiring information from.
// * Each file is loaded using PHP's include mechanism. Each file is expected to
// * return an associative array that maps service names to instantiator functions.
// */
// public function loadWiringFiles(array $wiringFiles) {
// foreach ($wiringFiles as $file) {
// // the wiring file is required to return an array of instantiators.
// $wiring = require $file;
//
// Assert::postcondition(
// is_array($wiring),
// "Wiring file $file is expected to return an array!"
// );
//
// this.applyWiring($wiring);
// }
// }
// /**
// * Registers multiple services (aka a "wiring").
// *
// * @param array $serviceInstantiators An associative array mapping service names to
// * instantiator functions.
// */
// public function applyWiring(array $serviceInstantiators) {
// Assert::parameterElementType('callable', $serviceInstantiators, '$serviceInstantiators');
//
// foreach ($serviceInstantiators as $name => $instantiator) {
// this.defineService($name, $instantiator);
// }
// }
// /**
// * Imports all wiring defined in $container. Wiring defined in $container
// * will override any wiring already defined locally. However, already
// * existing service instances will be preserved.
// *
// * @since 1.28
// *
// * @param ServiceContainer $container
// * @param string[] $skip A list of service names to skip during import
// */
// public function importWiring(ServiceContainer $container, $skip = []) {
// $newInstantiators = array_diff_key(
// $container.serviceInstantiators,
// array_flip($skip)
// );
//
// this.serviceInstantiators = array_merge(
// this.serviceInstantiators,
// $newInstantiators
// );
//
// $newManipulators = array_diff(
// array_keys($container.serviceManipulators),
// $skip
// );
//
// foreach ($newManipulators as $name) {
// if (isset(this.serviceManipulators[$name])) {
// this.serviceManipulators[$name] = array_merge(
// this.serviceManipulators[$name],
// $container.serviceManipulators[$name]
// );
// } else {
// this.serviceManipulators[$name] = $container.serviceManipulators[$name];
// }
// }
// }
/**
* Returns true if a service is defined for $name, that is, if a call to getService($name)
* would return a service instance.
*
* @param string $name
*
* @return bool
*/
public boolean hasService(String name) {
return XophpArray_.isset(this.serviceInstantiators, name);
}
/**
* Returns the service instance for $name only if that service has already been instantiated.
* This is intended for situations where services get destroyed/cleaned up, so we can
* avoid creating a service just to destroy it again.
*
* @note This is intended for internal use and for test fixtures.
* Application logic should use getService() instead.
*
* @see getService().
*
* @param string $name
*
* @return object|null The service instance, or null if the service has not yet been instantiated.
* @throws RuntimeException if $name does not refer to a known service.
*/
public Object peekService(String name) {
if (!this.hasService(name)) {
throw new XomwNoSuchServiceException(name);
}
return XophpObject_.Coalesce(this.services.Get_by(name), null);
}
/**
* @return string[]
*/
public XophpArray<String> getServiceNames() {
return XophpArray_.array_keys(this.serviceInstantiators);
}
// /**
// * Define a new service. The service must not be known already.
// *
// * @see getService().
// * @see redefineService().
// *
// * @param string $name The name of the service to register, for use with getService().
// * @param callable $instantiator Callback that returns a service instance.
// * Will be called with this ServiceContainer instance as the only parameter.
// * Any extra instantiation parameters provided to the constructor will be
// * passed as subsequent parameters when invoking the instantiator.
// *
// * @throws RuntimeException if there is already a service registered as $name.
// */
// public function defineService($name, callable $instantiator) {
// Assert::parameterType('string', $name, '$name');
//
// if (this.hasService($name)) {
// throw new ServiceAlreadyDefinedException($name);
// }
//
// this.serviceInstantiators[$name] = $instantiator;
// }
// /**
// * Replace an already defined service.
// *
// * @see defineService().
// *
// * @note This will fail if the service was already instantiated. If the service was previously
// * disabled, it will be re-enabled by this call. Any manipulators registered for the service
// * will remain in place.
// *
// * @param string $name The name of the service to register.
// * @param callable $instantiator Callback function that returns a service instance.
// * Will be called with this ServiceContainer instance as the only parameter.
// * The instantiator must return a service compatible with the originally defined service.
// * Any extra instantiation parameters provided to the constructor will be
// * passed as subsequent parameters when invoking the instantiator.
// *
// * @throws NoSuchServiceException if $name is not a known service.
// * @throws CannotReplaceActiveServiceException if the service was already instantiated.
// */
// public function redefineService($name, callable $instantiator) {
// Assert::parameterType('string', $name, '$name');
//
// if (!this.hasService($name)) {
// throw new NoSuchServiceException($name);
// }
//
// if (isset(this.services[$name])) {
// throw new CannotReplaceActiveServiceException($name);
// }
//
// this.serviceInstantiators[$name] = $instantiator;
// unset(this.disabled[$name]);
// }
//
// /**
// * Add a service manipulator callback for the given service.
// * This method may be used by extensions that need to wrap, replace, or re-configure a
// * service. It would typically be called from a MediaWikiServices hook handler.
// *
// * The manipulator callback is called just after the service is instantiated.
// * It can call methods on the service to change configuration, or wrap or otherwise
// * replace it.
// *
// * @see defineService().
// * @see redefineService().
// *
// * @note This will fail if the service was already instantiated.
// *
// * @since 1.32
// *
// * @param string $name The name of the service to manipulate.
// * @param callable $manipulator Callback function that manipulates, wraps or replaces a
// * service instance. The callback receives the new service instance and this
// * ServiceContainer as parameters, as well as any extra instantiation parameters specified
// * when constructing this ServiceContainer. If the callback returns a value, that
// * value replaces the original service instance.
// *
// * @throws NoSuchServiceException if $name is not a known service.
// * @throws CannotReplaceActiveServiceException if the service was already instantiated.
// */
// public function addServiceManipulator($name, callable $manipulator) {
// Assert::parameterType('string', $name, '$name');
//
// if (!this.hasService($name)) {
// throw new NoSuchServiceException($name);
// }
//
// if (isset(this.services[$name])) {
// throw new CannotReplaceActiveServiceException($name);
// }
//
// this.serviceManipulators[$name][] = $manipulator;
// }
/**
* Disables a service.
*
* @note Attempts to call getService() for a disabled service will result
* in a DisabledServiceException. Calling peekService for a disabled service will
* return null. Disabled services are listed by getServiceNames(). A disabled service
* can be enabled again using redefineService().
*
* @note If the service was already active (that is, instantiated) when getting disabled,
* and the service instance implements DestructibleService, destroy() is called on the
* service instance.
*
* @see redefineService()
* @see resetService()
*
* @param string $name The name of the service to disable.
*
* @throws RuntimeException if $name is not a known service.
*/
public void disableService(String name) {
this.resetService(name);
this.disabled.Set(name, true);
}
/**
* Resets a service by dropping the service instance.
* If the service instances implements DestructibleService, destroy()
* is called on the service instance.
*
* @warning This is generally unsafe! Other services may still retain references
* to the stale service instance, leading to failures and inconsistencies. Subclasses
* may use this method to reset specific services under specific instances, but
* it should not be exposed to application logic.
*
* @note This is declared final so subclasses can not interfere with the expectations
* disableService() has when calling resetService().
*
* @see redefineService()
* @see disableService().
*
* @param string $name The name of the service to reset.
* @param bool $destroy Whether the service instance should be destroyed if it exists.
* When set to false, any existing service instance will effectively be detached
* from the container.
*
* @throws RuntimeException if $name is not a known service.
*/
protected void resetService(String name) {this.resetService(name, true);}
protected void resetService(String name, boolean destroy) {
// Assert::parameterType('string', $name, '$name');
Object instance = this.peekService(name);
if (destroy && XophpType_.instance_of(instance, XomwDestructibleService.class)) {
((XomwDestructibleService)instance).destroy();
}
XophpArray_.unset(this.services, name);
XophpArray_.unset(this.disabled, name);
}
/**
* Returns a service object of the kind associated with $name.
* Services instances are instantiated lazily, on demand.
* This method may or may not return the same service instance
* when called multiple times with the same $name.
*
* @note Rather than calling this method directly, it is recommended to provide
* getters with more meaningful names and more specific return types, using
* a subclass or wrapper.
*
* @see redefineService().
*
* @param string $name The service name
*
* @throws NoSuchServiceException if $name is not a known service.
* @throws ContainerDisabledException if this container has already been destroyed.
* @throws ServiceDisabledException if the requested service has been disabled.
*
* @return object The service instance
*/
public Object getService(String name) {
if (this.destroyed) {
// throw new XomwContainerDisabledException();
}
if (XophpArray_.isset(this.disabled, name)) {
// throw new XomwServiceDisabledException($name);
}
if (!XophpArray_.isset(this.services, name)) {
this.services.Set(name, this.createService(name));
}
return this.services.Get_by(name);
}
/**
* @param string $name
*
* @throws InvalidArgumentException if $name is not a known service.
* @return object
*/
private Object createService(String name) {
// if (isset(this.serviceInstantiators[$name])) {
// $service = (this.serviceInstantiators[$name])(
// this,
// ...this.extraInstantiationParams
// );
//
// if (isset(this.serviceManipulators[$name])) {
// foreach (this.serviceManipulators[$name] as $callback) {
// $ret = call_user_func_array(
// $callback,
// array_merge([ $service, this ], this.extraInstantiationParams)
// );
//
// // If the manipulator callback returns an object, that object replaces
// // the original service instance. This allows the manipulator to wrap
// // or fully replace the service.
// if ($ret !== null) {
// $service = $ret;
// }
// }
// }
//
// // NOTE: when adding more wiring logic here, make sure importWiring() is kept in sync!
// } else {
// throw new NoSuchServiceException($name);
// }
//
// return $service;
return null;
}
/**
* @param string $name
* @return bool Whether the service is disabled
* @since 1.28
*/
public boolean isServiceDisabled(String name) {
return XophpArray_.isset(this.disabled, name);
}
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save