diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java b/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java index b40d86f69..ff4a5f419 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java @@ -59,6 +59,7 @@ public class XophpArray implements Bry_bfr_able { } public XophpArray Get_at_ary(int i) {return (XophpArray)Get_at(i);} public String Get_at_str(int i) {return (String)Get_at(i);} + public int Get_at_int(int i) {return Int_.Cast(Get_at(i));} public Object Get_at(int i) { if (i < 0 || i >= hash.Len()) return null; XophpArrayItm itm = (XophpArrayItm)hash.Get_at(i); @@ -78,6 +79,8 @@ public class XophpArray implements Bry_bfr_able { } public Object Get_by_obj(Object key) {return Get_by(Object_.Xto_str_strict_or_null(key));} public Object Get_by(int key) {return Get_by(Int_.To_str(key));} + public int Get_by_int(String key) {return Int_.Cast(this.Get_by(key));} + public Object Get_by_str(String key) {return (String)this.Get_by(key);} public Object Get_by(String key) { XophpArrayItm itm = (XophpArrayItm)hash.Get_by(key); return itm.Val(); @@ -93,6 +96,7 @@ public class XophpArray implements Bry_bfr_able { public boolean Has(String key) { return hash.Has(key); } + public boolean is_set(String key) {return hash.Has(key);} public XophpArrayItm[] To_ary() { return (XophpArrayItm[])hash.To_ary(XophpArrayItm.class); } @@ -117,10 +121,25 @@ public class XophpArray implements Bry_bfr_able { cur.Val_(itm.Val()); } } + public Object Pop() { + int pos = this.Count() - 1; + XophpArrayItm itm = (XophpArrayItm)hash.Get_at(pos); + this.Del_at(pos); + return itm.Val(); + } + public void Itm_str_concat_end(int idx, String v) { + String itm = (String)this.Get_at(idx); + itm += v; + this.Set(idx, itm); + } public static XophpArray New(Object... vals) { XophpArray rv = new XophpArray(); for (Object val : vals) rv.Add(val); return rv; } + 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; } diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpArray_tst.java b/400_xowa/src/gplx/xowa/mediawiki/XophpArray_tst.java index c53a4fb64..bb66466b9 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/XophpArray_tst.java +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpArray_tst.java @@ -120,8 +120,30 @@ public class XophpArray_tst { // REF: http://php.net/manual/en/language.types.ar ary.Add("c"); fxt.Test__array(ary, XophpArrayItm.New_int(2, "c")); } + @Test public void Pop() { + XophpArray ary = XophpArray.New(); + ary.Add(0, "a").Add(1, "b").Add(2, "c"); + + // pop all + fxt.Test__Pop(ary, "c"); + fxt.Test__Pop(ary, "b"); + fxt.Test__Pop(ary, "a"); + fxt.Test__Count(ary, 0); + } + @Test public void Itm_str_concat_end() { + XophpArray ary = XophpArray.New(); + ary.Add(0, "a").Add(1, "b").Add(2, "c"); + + // pop all + fxt.Test__Itm_str_concat_end(ary, "a0", 0, "0"); + fxt.Test__Itm_str_concat_end(ary, "b1", 1, "1"); + fxt.Test__Itm_str_concat_end(ary, "c2", 2, "2"); + } } class XophpArray_fxt { + public void Test__Count(XophpArray ary, int expd) { + Gftest.Eq__int(expd, ary.Count()); + } public void Test__array(XophpArray ary, XophpArrayItm... expd) { XophpArrayItm[] actl = ary.To_ary(); Gftest.Eq__ary(expd, actl); @@ -130,4 +152,13 @@ class XophpArray_fxt { XophpArrayItm[] actl = ary.To_ary(); Gftest.Eq__ary(expd, actl); } + public void Test__Pop(XophpArray ary, String expd) { + String actl = (String)ary.Pop(); + Gftest.Eq__str(expd, actl); + } + public void Test__Itm_str_concat_end(XophpArray ary, String expd, int idx, String v) { + ary.Itm_str_concat_end(idx, v); + String actl = ary.Get_at_str(idx); + Gftest.Eq__str(expd, actl); + } } diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpBry_.java b/400_xowa/src/gplx/xowa/mediawiki/XophpBry_.java new file mode 100644 index 000000000..b724aae26 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpBry_.java @@ -0,0 +1,19 @@ +/* +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 XophpBry_ { + public static final byte[] False = null; // handles code like "if ($var === false)" where var is an Object; +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpObject.java b/400_xowa/src/gplx/xowa/mediawiki/XophpObject.java new file mode 100644 index 000000000..2bc93c60d --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpObject.java @@ -0,0 +1,20 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*; +public 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;} +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpString.java b/400_xowa/src/gplx/xowa/mediawiki/XophpString.java index 4a7c961e7..6e3001bca 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/XophpString.java +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpString.java @@ -20,6 +20,8 @@ public class XophpString { public static int strpos(byte[] src, byte find, int bgn, int end) { return Bry_find_.Find_fwd(src, find, bgn, end); } + public static String substr(String src, int bgn, int len) {return String_.new_u8(substr(Bry_.new_u8(src), bgn, len));} + public static String substr(String src, int bgn) {return String_.new_u8(substr(Bry_.new_u8(src), bgn, String_.Len(src)));} public static byte[] substr(byte[] src, int bgn) {return substr(src, bgn, src.length);} public static byte[] substr(byte[] src, int bgn, int len) { int src_len = src.length; @@ -169,4 +171,7 @@ public class XophpString { } return String_.new_charAry_(chry, 0, chry_len); } + public static boolean is_string(Object o) { + return String_.as_(o) != null; + } } diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpString_.java b/400_xowa/src/gplx/xowa/mediawiki/XophpString_.java new file mode 100644 index 000000000..508993e6d --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpString_.java @@ -0,0 +1,19 @@ +/* +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 XophpString_ { + public static final String False = null; // handles code like "if ($var === false)" where var is an Object; +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/XomwTitle.java b/400_xowa/src/gplx/xowa/mediawiki/includes/XomwTitle.java index 2914af350..012462711 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/XomwTitle.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/XomwTitle.java @@ -1438,6 +1438,7 @@ public class XomwTitle { s = XophpString.strtr(s, Byte_ascii.Space, Byte_ascii.Underline); return s; } + public String getPrefixedDBkeyStr() {return String_.new_u8(getPrefixedDBkey());} /** * Get the prefixed title with spaces. diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java index 1999dcd8e..fe996f8f8 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java @@ -68,102 +68,102 @@ import gplx.xowa.mediawiki.includes.parsers.preprocessors.*; * @ingroup Parser */ public class XomwParser implements XomwParserIface { -// /** -// * Update this version number when the ParserOutput format -// * changes in an incompatible way, so the parser cache -// * can automatically discard old data. -// */ -// static final VERSION = '1.6.4'; -// -// /** -// * Update this version number when the output of serialiseHalfParsedText() -// * changes in an incompatible way -// */ -// static final HALF_PARSED_VERSION = 2; -// -// # Flags for Parser::setFunctionHook -// static final SFH_NO_HASH = 1; -// static final SFH_OBJECT_ARGS = 2; -// -// # Constants needed for external link processing -// # Everything except bracket, space, or control characters -// # \p{Zs} is unicode 'separator, space' category. It covers the space 0x20 -// # as well as U+3000 is IDEOGRAPHIC SPACE for T21052 + /** + * Update this version number when the ParserOutput format + * changes in an incompatible way, so the parser cache + * can automatically discard old data. + */ +// private static final String VERSION = "1.6.4"; + + /** + * Update this version number when the output of serialiseHalfParsedText() + * changes in an incompatible way + */ +// private static final int HALF_PARSED_VERSION = 2; + + // Flags for Parser::setFunctionHook +// private static final int SFH_NO_HASH = 1; +// private static final int SFH_OBJECT_ARGS = 2; + +// // Constants needed for external link processing +// // Everything except bracket, space, or control characters +// // \p{Zs} is unicode 'separator, space' category. It covers the space 0x20 +// // as well as U+3000 is IDEOGRAPHIC SPACE for T21052 // static final EXT_LINK_URL_CLASS = '[^][<>"\\x00-\\x20\\x7F\p{Zs}]'; -// # Simplified expression to match an IPv4 or IPv6 address, or -// # at least one character of a host name (embeds EXT_LINK_URL_CLASS) +// // Simplified expression to match an IPv4 or IPv6 address, or +// // at least one character of a host name (embeds EXT_LINK_URL_CLASS) // static final EXT_LINK_ADDR = '(?:[0-9.]+|\\[(?i:[0-9a-f:.]+)\\]|[^][<>"\\x00-\\x20\\x7F\p{Zs}])'; -// # RegExp to make image URLs (embeds IPv6 part of EXT_LINK_ADDR) +// // RegExp to make image URLs (embeds IPv6 part of EXT_LINK_ADDR) // // @codingStandardsIgnoreStart Generic.Files.LineLength // static final EXT_IMAGE_REGEX = '/^(http:\/\/|https:\/\/)((?:\\[(?i:[0-9a-f:.]+)\\])?[^][<>"\\x00-\\x20\\x7F\p{Zs}]+) // \\/([A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]+)\\.((?i)gif|png|jpg|jpeg)$/Sxu'; // // @codingStandardsIgnoreEnd // -// # Regular expression for a non-newline space +// // Regular expression for a non-newline space // static final SPACE_NOT_NL = '(?:\t| |&\#0*160;|&\#[Xx]0*[Aa]0;|\p{Zs})'; // Flags for preprocessToDom public static final int PTD_FOR_INCLUSION = 1; -// # Allowed values for this.mOutputType -// # Parameter to startExternalParse(). -// static final OT_HTML = 1; # like parse() -// static final OT_WIKI = 2; # like preSaveTransform() -// static final OT_PREPROCESS = 3; # like preprocess() -// static final OT_MSG = 3; -// static final OT_PLAIN = 4; # like extractSections() - portions of the original are returned unchanged. + // Allowed values for this.mOutputType + // Parameter to startExternalParse(). + private static final int OT_HTML = 1; // like parse() + private static final int OT_WIKI = 2; // like preSaveTransform() + private static final int OT_PREPROCESS = 3; // like preprocess() +// private static final int OT_MSG = 3; + private static final int OT_PLAIN = 4; // like extractSections() - portions of the original are returned unchanged. + + /** + * @var String Prefix and suffix for temporary replacement strings + * for the multipass parser. + * + * \x7f should never appear in input as it's disallowed in XML. + * Using it at the front also gives us a little extra robustness + * since it shouldn't match when butted up against identifier-like + * String constructs. + * + * Must not consist of all title characters, or else it will change + * the behavior of in a link. + * + * Must have a character that needs escaping in attributes, otherwise + * someone could put a strip marker in an attribute, to get around + * escaping quote marks, and break out of the attribute. Thus we add + * `'". + */ +// private static final String MARKER_SUFFIX = "-QINU`\"'\x7f"; +// private static final String MARKER_PREFIX = "\x7f'\"`UNIQ-"; + + // Markers used for wrapping the table of contents +// private static final String TOC_START = ""; +// private static final String TOC_END = ""; + +// // Persistent: +// public mTagHooks = []; +// public mTransparentTagHooks = []; +// public mFunctionHooks = []; +// public mFunctionSynonyms = [ 0 => [], 1 => [] ]; +// public mFunctionTagHooks = []; +// public mStripList = []; +// public mDefaultStripList = []; +// public mVarCache = []; +// public mImageParams = []; +// public mImageParamsMagicArray = []; +// public mMarkerIndex = 0; +// public mFirstCall = true; // -// /** -// * @var String Prefix and suffix for temporary replacement strings -// * for the multipass parser. -// * -// * \x7f should never appear in input as it's disallowed in XML. -// * Using it at the front also gives us a little extra robustness -// * since it shouldn't match when butted up against identifier-like -// * String constructs. -// * -// * Must not consist of all title characters, or else it will change -// * the behavior of in a link. -// * -// * Must have a character that needs escaping in attributes, otherwise -// * someone could put a strip marker in an attribute, to get around -// * escaping quote marks, and break out of the attribute. Thus we add -// * `'". -// */ -// static final MARKER_SUFFIX = "-QINU`\"'\x7f"; -// static final MARKER_PREFIX = "\x7f'\"`UNIQ-"; -// -// # Markers used for wrapping the table of contents -// static final TOC_START = ''; -// static final TOC_END = ''; -// -// # Persistent: -// public $mTagHooks = []; -// public $mTransparentTagHooks = []; -// public $mFunctionHooks = []; -// public $mFunctionSynonyms = [ 0 => [], 1 => [] ]; -// public $mFunctionTagHooks = []; -// public $mStripList = []; -// public $mDefaultStripList = []; -// public $mVarCache = []; -// public $mImageParams = []; -// public $mImageParamsMagicArray = []; -// public $mMarkerIndex = 0; -// public $mFirstCall = true; -// -// # Initialised by initialiseVariables() +// // Initialised by initialiseVariables() // // /** // * @var MagicWordArray // */ -// public $mVariables; +// public mVariables; // // /** // * @var MagicWordArray // */ -// public $mSubstWords; -// # Initialised in constructor -// public $mConf, $mExtLinkBracketedRegex, $mUrlProtocols; +// public mSubstWords; +// // Initialised in constructor +// public mConf, mExtLinkBracketedRegex, mUrlProtocols; // Initialized in getPreprocessor() /** @var Preprocessor */ @@ -171,70 +171,70 @@ public class XomwParser implements XomwParserIface { private XomwPreprocessor mPreprocessorClass; -// # Cleared with clearState(): +// // Cleared with clearState(): // /** // * @var ParserOutput // */ -// public $mOutput; -// public $mAutonumber; +// public mOutput; +// public mAutonumber; /** * @var StripState */ public XomwStripState mStripState = new XomwStripState(); -// public $mIncludeCount; +// public mIncludeCount; /** * @var LinkHolderArray */ public XomwLinkHolderArray mLinkHolders; private int mLinkID; -// public $mIncludeSizes, $mPPNodeCount, $mGeneratedPPNodeCount, $mHighestExpansionDepth; -// public $mDefaultSort; -// public $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores; -// public $mExpensiveFunctionCount; # number of expensive parser function calls -// public $mShowToc, $mForceTocPosition; + public int mIncludeSizes, mPPNodeCount, mGeneratedPPNodeCount, mHighestExpansionDepth; +// public mDefaultSort; +// public mTplRedirCache, mTplDomCache, mHeadings, mDoubleUnderscores; +// public mExpensiveFunctionCount; // number of expensive parser function calls +// public mShowToc, mForceTocPosition; // // /** // * @var User // */ -// public $mUser; # User Object; only used when doing pre-save transform +// public mUser; // User Object; only used when doing pre-save transform // -// # Temporary -// # These are variables reset at least once per parse regardless of $clearState +// // Temporary +// // These are variables reset at least once per parse regardless of $clearState /** * @var ParserOptions */ public XomwParserOptions mOptions = new XomwParserOptions(); -// /** -// * @var Title -// */ -// public $mTitle; # Title context, used for self-link rendering and similar things -// public $mOutputType; # Output type, one of the OT_xxx constants -// public $ot; # Shortcut alias, see setOutputType() -// public $mRevisionObject; # The revision Object of the specified revision ID -// public $mRevisionId; # ID to display in {{REVISIONID}} tags -// public $mRevisionTimestamp; # The timestamp of the specified revision ID -// public $mRevisionUser; # User to display in {{REVISIONUSER}} tag -// public $mRevisionSize; # Size to display in {{REVISIONSIZE}} variable -// public $mRevIdForTs; # The revision ID which was used to fetch the timestamp -// public $mInputSize = false; # For {{PAGESIZE}} on current page. + /** + * @var Title + */ + public XomwTitle mTitle; // Title context, used for self-link rendering and similar things + public int mOutputType; // Output type, one of the OT_xxx constants + public XophpArray ot; // Shortcut alias, see setOutputType() +// public mRevisionObject; // The revision Object of the specified revision ID +// public mRevisionId; // ID to display in {{REVISIONID}} tags +// public mRevisionTimestamp; // The timestamp of the specified revision ID +// public mRevisionUser; // User to display in {{REVISIONUSER}} tag +// public mRevisionSize; // Size to display in {{REVISIONSIZE}} variable +// public mRevIdForTs; // The revision ID which was used to fetch the timestamp +// public mInputSize = false; // For {{PAGESIZE}} on current page. // // /** // * @var String Deprecated accessor for the strip marker prefix. // * @deprecated since 1.26; use Parser::MARKER_PREFIX instead. // */ -// public $mUniqPrefix = Parser::MARKER_PREFIX; +// public mUniqPrefix = Parser::MARKER_PREFIX; // // /** // * @var array Array with the language name of each language link (i.e. the // * interwiki prefix) in the key, value arbitrary. Used to avoid sending // * duplicate language links to the ParserOutput. // */ -// public $mLangLinkLanguages; +// public mLangLinkLanguages; // // /** // * @var MapCacheLRU|null @@ -248,10 +248,10 @@ public class XomwParser implements XomwParserIface { // * @var boolean Recursive call protection. // * This variable should be treated as if it were private. // */ -// public $mInParse = false; +// public mInParse = false; // // /** @var SectionProfiler */ -// protected $mProfiler; +// protected mProfiler; /** * @var LinkRenderer @@ -292,17 +292,17 @@ public class XomwParser implements XomwParserIface { // this.mConf = $conf; // this.mUrlProtocols = wfUrlProtocols(); // this.mExtLinkBracketedRegex = '/\[(((?i)' . this.mUrlProtocols . ')' . -// self::EXT_LINK_ADDR . -// self::EXT_LINK_URL_CLASS . '*)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F]*?)\]/Su'; +// XomwParser.EXT_LINK_ADDR . +// XomwParser.EXT_LINK_URL_CLASS . '*)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F]*?)\]/Su'; this.mPreprocessorClass = XomwPreprocessor_DOM.Instance; // if (isset($conf['preprocessorClass'])) { // this.mPreprocessorClass = $conf['preprocessorClass']; // } elseif (defined('HPHP_VERSION')) { - // # Preprocessor_Hash is much faster than Preprocessor_DOM under HipHop + // // Preprocessor_Hash is much faster than Preprocessor_DOM under HipHop // this.mPreprocessorClass = 'Preprocessor_Hash'; // } elseif (extension_loaded('domxml')) { - // # PECL extension that conflicts with the core DOM extension (T15770) + // // PECL extension that conflicts with the core DOM extension (T15770) // wfDebug("Warning: you have the obsolete domxml extension for PHP. Please remove it!\n"); // this.mPreprocessorClass = 'Preprocessor_Hash'; // } elseif (extension_loaded('dom')) { @@ -428,7 +428,7 @@ public class XomwParser implements XomwParserIface { this.mStripState = new XomwStripState(); -// # Clear these on every parse, T6549 +// // Clear these on every parse, T6549 // this.mTplRedirCache = this.mTplDomCache = []; // // this.mShowToc = true; @@ -445,7 +445,7 @@ public class XomwParser implements XomwParserIface { // this.mDoubleUnderscores = []; // this.mExpensiveFunctionCount = 0; // -// # Fix cloning +// // Fix cloning // if (isset(this.mPreprocessor) && this.mPreprocessor->parser !== $this) { // this.mPreprocessor = null; // } @@ -487,10 +487,10 @@ public class XomwParser implements XomwParserIface { // // We use U+007F DELETE to construct strip markers, so we have to make // // sure that this character does not occur in the input text. // $text = strtr($text, "\x7f", "?"); -// $magicScopeVariable = this.synchronized(); +// magicScopeVariable = this.synchronized(); // } // -// this.startParse($title, $options, self::OT_HTML, $clearState); +// this.startParse($title, $options, XomwParser.OT_HTML, $clearState); // // this.currentRevisionCache = null; // this.mInputSize = strlen($text); @@ -512,7 +512,7 @@ public class XomwParser implements XomwParserIface { // } // // Hooks::run('ParserBeforeStrip', [ &$this, &$text, &this.mStripState ]); -// # No more strip! +// // No more strip! // Hooks::run('ParserAfterStrip', [ &$this, &$text, &this.mStripState ]); this.internalParse(pbfr, pctx, text); // Hooks::run('ParserAfterParse', [ &$this, &$text, &this.mStripState ]); @@ -540,10 +540,10 @@ public class XomwParser implements XomwParserIface { // } // } // -// # Done parsing! Compute runtime adaptive expiry if set +// // Done parsing! Compute runtime adaptive expiry if set // this.mOutput->finalizeAdaptiveCacheExpiry(); // -// # Warn if too many heavyweight parser functions were used +// // Warn if too many heavyweight parser functions were used // if (this.mExpensiveFunctionCount > this.mOptions->getExpensiveParserFunctionLimit()) { // this.limitationWarn('expensive-parserfunction', // this.mExpensiveFunctionCount, @@ -551,9 +551,9 @@ public class XomwParser implements XomwParserIface { // ); // } // -// # Information on include size limits, for the benefit of users who try to skirt them +// // Information on include size limits, for the benefit of users who try to skirt them // if (this.mOptions->getEnableLimitReport()) { -// $max = this.mOptions->getMaxIncludeSize(); +// max = this.mOptions->getMaxIncludeSize(); // // $cpuTime = this.mOutput->getTimeSinceStart('cpu'); // if ($cpuTime !== null) { @@ -574,10 +574,10 @@ public class XomwParser implements XomwParserIface { // [ this.mGeneratedPPNodeCount, this.mOptions->getMaxGeneratedPPNodeCount() ] // ); // this.mOutput->setLimitReportData('limitreport-postexpandincludesize', -// [ this.mIncludeSizes['post-expand'], $max ] +// [ this.mIncludeSizes['post-expand'], max ] // ); // this.mOutput->setLimitReportData('limitreport-templateargumentsize', -// [ this.mIncludeSizes['arg'], $max ] +// [ this.mIncludeSizes['arg'], max ] // ); // this.mOutput->setLimitReportData('limitreport-expansiondepth', // [ this.mHighestExpansionDepth, this.mOptions->getMaxPPExpandDepth() ] @@ -734,8 +734,8 @@ public class XomwParser implements XomwParserIface { // public function preprocess($text, Title $title = null, // ParserOptions $options, $revid = null, $frame = false // ) { -// $magicScopeVariable = this.synchronized(); -// this.startParse($title, $options, self::OT_PREPROCESS, true); +// magicScopeVariable = this.synchronized(); +// this.startParse($title, $options, XomwParser.OT_PREPROCESS, true); // if ($revid !== null) { // this.mRevisionId = $revid; // } @@ -775,15 +775,15 @@ public class XomwParser implements XomwParserIface { // * @return String // */ // public function getPreloadText($text, Title $title, ParserOptions $options, $params = []) { -// $msg = new RawMessage($text); -// $text = $msg->params($params)->plain(); +// msg = new RawMessage($text); +// $text = msg->params($params)->plain(); // -// # Parser (re)initialisation -// $magicScopeVariable = this.synchronized(); -// this.startParse($title, $options, self::OT_PLAIN, true); +// // Parser (re)initialisation +// magicScopeVariable = this.synchronized(); +// this.startParse($title, $options, XomwParser.OT_PLAIN, true); // // $flags = PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES; -// $dom = this.preprocessToDom($text, self::PTD_FOR_INCLUSION); +// $dom = this.preprocessToDom($text, XomwParser.PTD_FOR_INCLUSION); // $text = this.getPreprocessor()->newFrame()->expand($dom, $flags); // $text = this.mStripState->unstripBoth($text); // return $text; @@ -818,7 +818,7 @@ public class XomwParser implements XomwParserIface { // */ // public function uniqPrefix() { // wfDeprecated(__METHOD__, '1.26'); -// return self::MARKER_PREFIX; +// return XomwParser.MARKER_PREFIX; // } // // /** @@ -832,7 +832,7 @@ public class XomwParser implements XomwParserIface { // } // // if ($t->hasFragment()) { -// # Strip the fragment to avoid various odd effects +// // Strip the fragment to avoid various odd effects // this.mTitle = $t->createFragmentTarget(''); // } else { // this.mTitle = $t; @@ -857,23 +857,23 @@ public class XomwParser implements XomwParserIface { // public function Title($x = null) { // return wfSetVar(this.mTitle, $x); // } -// -// /** -// * Set the output type -// * -// * @param int $ot New value -// */ -// public function setOutputType($ot) { -// this.mOutputType = $ot; -// # Shortcut alias -// this.ot = [ -// 'html' => $ot == self::OT_HTML, -// 'wiki' => $ot == self::OT_WIKI, -// 'pre' => $ot == self::OT_PREPROCESS, -// 'plain' => $ot == self::OT_PLAIN, -// ]; -// } -// + + /** + * Set the output type + * + * @param int ot New value + */ + public void setOutputType(int otVal) { + this.mOutputType = otVal; + // Shortcut alias + this.ot = XophpArray.New() + .Add("html", otVal == XomwParser.OT_HTML) + .Add("wiki", otVal == XomwParser.OT_WIKI) + .Add("pre", otVal == XomwParser.OT_PREPROCESS) + .Add("plain", otVal == XomwParser.OT_PLAIN) + ; + } + // /** // * Accessor/mutator for the output type // * @@ -1014,7 +1014,7 @@ public class XomwParser implements XomwParserIface { // /** // * Replaces all occurrences of HTML-style comments and the given tags // * in the text with a random marker and returns the next text. The output -// * parameter $matches will be an associative array filled with data in +// * parameter matches will be an associative array filled with data in // * the form: // * // * @code @@ -1027,18 +1027,18 @@ public class XomwParser implements XomwParserIface { // * // * @param array $elements List of element names. Comments are always extracted. // * @param String $text Source text String. -// * @param array $matches Out parameter, Array: extracted tags +// * @param array matches Out parameter, Array: extracted tags // * @param String|null $uniq_prefix // * @return String Stripped text // * @since 1.26 The uniq_prefix argument is deprecated. // */ -// public static function extractTagsAndParams($elements, $text, &$matches, $uniq_prefix = null) { +// public static function extractTagsAndParams($elements, $text, &matches, $uniq_prefix = null) { // if ($uniq_prefix !== null) { // wfDeprecated(__METHOD__ . ' called with $prefix argument', '1.26'); // } // static $n = 1; // $stripped = ''; -// $matches = []; +// matches = []; // // $taglist = implode('|', $elements); // $start = "/<($taglist)(\\s+[^>]*?|\\s*?)(\/?" . ">)|<(!--)/i"; @@ -1050,24 +1050,24 @@ public class XomwParser implements XomwParserIface { // break; // } // if (count($p) > 5) { -// # comment +// // comment // $element = $p[4]; // $attributes = ''; // $close = ''; // $inside = $p[5]; // } else { -// # tag +// // tag // $element = $p[1]; // $attributes = $p[2]; // $close = $p[3]; // $inside = $p[4]; // } // -// $marker = self::MARKER_PREFIX . "-$element-" . sprintf('%08X', $n++) . self::MARKER_SUFFIX; -// $stripped .= $marker; +// marker = XomwParser.MARKER_PREFIX . "-$element-" . sprintf('%08X', $n++) . XomwParser.MARKER_SUFFIX; +// $stripped .= marker; // // if ($close === '/>') { -// # Empty element tag, +// // Empty element tag, // $content = null; // $text = $inside; // $tail = null; @@ -1080,7 +1080,7 @@ public class XomwParser implements XomwParserIface { // $q = preg_split($end, $inside, 2, PREG_SPLIT_DELIM_CAPTURE); // $content = $q[0]; // if (count($q) < 3) { -// # No end tag -- let it run out to the end of the text. +// // No end tag -- let it run out to the end of the text. // $tail = ''; // $text = ''; // } else { @@ -1089,7 +1089,7 @@ public class XomwParser implements XomwParserIface { // } // } // -// $matches[$marker] = [ $element, +// matches[marker] = [ $element, // $content, // Sanitizer::decodeTagAttributes($attributes), // "<$element$attributes$close$content$tail" ]; @@ -1115,12 +1115,14 @@ public class XomwParser implements XomwParserIface { * * @return String */ - public byte[] Insert_strip_item(byte[] text) { + public byte[] insertStripItem(byte[] text) { byte[] marker = tmp.Add_bry_many(MARKER_PREFIX, STRIP_ITEM).Add_int_variable(this.mMarkerIndex).Add(MARKER_SUFFIX).To_bry_and_clear(); this.mMarkerIndex++; this.mStripState.addGeneral(marker, text); return marker; } + public String insertStripItem(String text) {return String_.new_u8(insertStripItem(Bry_.new_u8(text)));} + /** * parse the wiki syntax used to render tables @@ -1134,7 +1136,7 @@ public class XomwParser implements XomwParserIface { /** * Helper function for parse() that transforms wiki markup into half-parsed - * HTML. Only called for $mOutputType == self::OT_HTML. + * HTML. Only called for mOutputType == XomwParser.OT_HTML. * * @private * @@ -1198,7 +1200,7 @@ public class XomwParser implements XomwParserIface { // replaceInternalLinks may sometimes leave behind // absolute URLs, which have to be masked to hide them from replaceExternalLinks - XomwParserBfr_.Replace(pbfr, Bry__marker__noparse, Bry_.Empty); // $text = str_replace(self::MARKER_PREFIX . 'NOPARSE', '', $text); + XomwParserBfr_.Replace(pbfr, Bry__marker__noparse, Bry_.Empty); // $text = str_replace(XomwParser.MARKER_PREFIX . 'NOPARSE', '', $text); magiclinksWkr.doMagicLinks(pctx, pbfr); // $text = $this->formatHeadings($text, $origText, $isMain); @@ -1220,12 +1222,12 @@ public class XomwParser implements XomwParserIface { // Clean up special characters, only run once, next-to-last before doBlockLevels // $fixtags = [ - // # French spaces, last one Guillemet-left - // # only if there is something before the space + // // French spaces, last one Guillemet-left + // // only if there is something before the space // '/(.) (?=\\?|:|;|!|%|\\302\\273)/' => '\\1 ', - // # french spaces, Guillemet-right + // // french spaces, Guillemet-right // '/(\\302\\253) /' => '\\1 ', - // '/ (!\s*important)/' => ' \\1', # Beware of CSS magic word !important, T13874. + // '/ (!\s*important)/' => ' \\1', // Beware of CSS magic word !important, T13874. // ]; // $text = preg_replace( array_keys( $fixtags ), array_values( $fixtags ), $text ); nbspWkr.doNbsp(pctx, pbfr); @@ -1300,7 +1302,7 @@ public class XomwParser implements XomwParserIface { // public function doMagicLinks($text) {} // XO.MW:MOVED - // public function magicLinkCallback($m) {} + // public function magicLinkCallback(m) {} // /** // * Make a free external link, given a user-supplied URL @@ -1314,39 +1316,39 @@ public class XomwParser implements XomwParserIface { // public function makeFreeExternalLink($url, $numPostProto) { // $trail = ''; // -// # The characters '<' and '>' (which were escaped by -// # removeHTMLtags()) should not be included in -// # URLs, per RFC 2396. -// # Make   terminate a URL as well (bug T84937) -// $m2 = []; +// // The characters '<' and '>' (which were escaped by +// // removeHTMLtags()) should not be included in +// // URLs, per RFC 2396. +// // Make   terminate a URL as well (bug T84937) +// m2 = []; // if (preg_match( // '/&(lt|gt|nbsp|#x0*(3[CcEe]|[Aa]0)|#0*(60|62|160));/', // $url, -// $m2, +// m2, // PREG_OFFSET_CAPTURE // )) { -// $trail = substr($url, $m2[0][1]) . $trail; -// $url = substr($url, 0, $m2[0][1]); +// $trail = substr($url, m2[0][1]) . $trail; +// $url = substr($url, 0, m2[0][1]); // } // -// # Move trailing punctuation to $trail +// // Move trailing punctuation to $trail // $sep = ',;\.:!?'; -// # If there is no left bracket, then consider right brackets fair game too +// // If there is no left bracket, then consider right brackets fair game too // if (strpos($url, '(') === false) { // $sep .= ')'; // } // // $urlRev = strrev($url); // $numSepChars = strspn($urlRev, $sep); -// # Don't break a trailing HTML entity by moving the ; into $trail -// # This is in hot code, so use substr_compare to avoid having to -// # create a new String Object for the comparison +// // Don't break a trailing HTML entity by moving the ; into $trail +// // This is in hot code, so use substr_compare to avoid having to +// // create a new String Object for the comparison // if ($numSepChars && substr_compare($url, ";", -$numSepChars, 1) === 0) { -// # more optimization: instead of running preg_match with a $ -// # anchor, which can be slow, do the match on the reversed -// # String starting at the desired offset. -// # un-reversed regexp is: /&([a-z]+|#x[\da-f]+|#\d+)$/i -// if (preg_match('/\G([a-z]+|[\da-f]+x#|\d+#)&/i', $urlRev, $m2, 0, $numSepChars)) { +// // more optimization: instead of running preg_match with a $ +// // anchor, which can be slow, do the match on the reversed +// // String starting at the desired offset. +// // un-reversed regexp is: /&([a-z]+|#x[\da-f]+|#\d+)$/i +// if (preg_match('/\G([a-z]+|[\da-f]+x#|\d+#)&/i', $urlRev, m2, 0, $numSepChars)) { // $numSepChars--; // } // } @@ -1355,25 +1357,25 @@ public class XomwParser implements XomwParserIface { // $url = substr($url, 0, -$numSepChars); // } // -// # Verify that we still have a real URL after trail removal, and -// # not just lone protocol +// // Verify that we still have a real URL after trail removal, and +// // not just lone protocol // if (strlen($trail) >= $numPostProto) { // return $url . $trail; // } // // $url = Sanitizer::cleanUrl($url); // -// # Is this an external image? +// // Is this an external image? // $text = this.maybeMakeExternalImage($url); // if ($text === false) { -// # Not an image, make a link +// // Not an image, make a link // $text = Linker::makeExternalLink($url, // this.getConverterLanguage()->markNoConversion($url, true), // true, 'free', // this.getExternalLinkAttribs($url), this.mTitle); -// # Register it in the output Object... -// # Replace unnecessary URL escape codes with their equivalent characters -// $pasteurized = self::normalizeLinkUrl($url); +// // Register it in the output Object... +// // Replace unnecessary URL escape codes with their equivalent characters +// $pasteurized = XomwParser.normalizeLinkUrl($url); // this.mOutput->addExternalLink($pasteurized); // } // return $text . $trail; @@ -1416,17 +1418,17 @@ public class XomwParser implements XomwParserIface { // $text = $bits[$i++]; // $trail = $bits[$i++]; // -// # The characters '<' and '>' (which were escaped by -// # removeHTMLtags()) should not be included in -// # URLs, per RFC 2396. -// $m2 = []; -// if (preg_match('/&(lt|gt);/', $url, $m2, PREG_OFFSET_CAPTURE)) { -// $text = substr($url, $m2[0][1]) . ' ' . $text; -// $url = substr($url, 0, $m2[0][1]); +// // The characters '<' and '>' (which were escaped by +// // removeHTMLtags()) should not be included in +// // URLs, per RFC 2396. +// m2 = []; +// if (preg_match('/&(lt|gt);/', $url, m2, PREG_OFFSET_CAPTURE)) { +// $text = substr($url, m2[0][1]) . ' ' . $text; +// $url = substr($url, 0, m2[0][1]); // } // -// # If the link text is an image URL, replace it with an tag -// # This happened by accident in the original parser, but some people used it extensively +// // If the link text is an image URL, replace it with an tag +// // This happened by accident in the original parser, but some people used it extensively // $img = this.maybeMakeExternalImage($text); // if ($img !== false) { // $text = $img; @@ -1434,18 +1436,18 @@ public class XomwParser implements XomwParserIface { // // $dtrail = ''; // -// # Set linktype for CSS - if URL==text, link is essentially free +// // Set linktype for CSS - if URL==text, link is essentially free // $linktype = ($text === $url) ? 'free' : 'text'; // -// # No link text, e.g. [http://domain.tld/some.link] +// // No link text, e.g. [http://domain.tld/some.link] // if ($text == '') { -// # Autonumber +// // Autonumber // $langObj = this.getTargetLanguage(); // $text = '[' . $langObj->formatNum(++this.mAutonumber) . ']'; // $linktype = 'autonumber'; // } else { -// # Have link text, e.g. [http://domain.tld/some.link text]s -// # Check for trail +// // Have link text, e.g. [http://domain.tld/some.link text]s +// // Check for trail // list($dtrail, $trail) = Linker::splitTrail($trail); // } // @@ -1453,17 +1455,17 @@ public class XomwParser implements XomwParserIface { // // $url = Sanitizer::cleanUrl($url); // -// # Use the encoded URL -// # This means that users can paste URLs directly into the text -// # Funny characters like � aren't valid in URLs anyway -// # This was changed in August 2004 +// // Use the encoded URL +// // This means that users can paste URLs directly into the text +// // Funny characters like � aren't valid in URLs anyway +// // This was changed in August 2004 // $s .= Linker::makeExternalLink($url, $text, false, $linktype, // this.getExternalLinkAttribs($url), this.mTitle) . $dtrail . $trail; // -// # Register link in the output Object. -// # Replace unnecessary URL escape codes with the referenced character -// # This prevents spammers from hiding links from the filters -// $pasteurized = self::normalizeLinkUrl($url); +// // Register link in the output Object. +// // Replace unnecessary URL escape codes with the referenced character +// // This prevents spammers from hiding links from the filters +// $pasteurized = XomwParser.normalizeLinkUrl($url); // this.mOutput->addExternalLink($pasteurized); // } // @@ -1520,10 +1522,10 @@ public class XomwParser implements XomwParserIface { // * @return String // */ // public static function normalizeLinkUrl($url) { -// # First, make sure unsafe characters are encoded +// // First, make sure unsafe characters are encoded // $url = preg_replace_callback('/[\x00-\x20"<>\[\\\\\]^`{|}\x7F-\xFF]/', -// function ($m) { -// return rawurlencode($m[0]); +// function (m) { +// return rawurlencode(m[0]); // }, // $url // ); @@ -1531,40 +1533,40 @@ public class XomwParser implements XomwParserIface { // $ret = ''; // $end = strlen($url); // -// # Fragment part - 'fragment' +// // Fragment part - 'fragment' // $start = strpos($url, '#'); // if ($start !== false && $start < $end) { -// $ret = self::normalizeUrlComponent( +// $ret = XomwParser.normalizeUrlComponent( // substr($url, $start, $end - $start), '"#%<>[\]^`{|}') . $ret; // $end = $start; // } // -// # Query part - 'query' minus &=+; +// // Query part - 'query' minus &=+; // $start = strpos($url, '?'); // if ($start !== false && $start < $end) { -// $ret = self::normalizeUrlComponent( +// $ret = XomwParser.normalizeUrlComponent( // substr($url, $start, $end - $start), '"#%<>[\]^`{|}&=+;') . $ret; // $end = $start; // } // -// # Scheme and path part - 'pchar' -// # (we assume no userinfo or encoded colons in the host) -// $ret = self::normalizeUrlComponent( +// // Scheme and path part - 'pchar' +// // (we assume no userinfo or encoded colons in the host) +// $ret = XomwParser.normalizeUrlComponent( // substr($url, 0, $end), '"#%<>[\]^`{|}/?') . $ret; // // return $ret; // } // // private static function normalizeUrlComponent($component, $unsafe) { -// $callback = function ($matches) use ($unsafe) { -// $char = urldecode($matches[0]); +// $callback = function (matches) use ($unsafe) { +// $char = urldecode(matches[0]); // $ord = ord($char); // if ($ord > 32 && $ord < 127 && strpos($unsafe, $char) === false) { -// # Unescape it +// // Unescape it // return $char; // } else { -// # Leave it escaped, but use uppercase for a-f -// return strtoupper($matches[0]); +// // Leave it escaped, but use uppercase for a-f +// return strtoupper(matches[0]); // } // }; // return preg_replace_callback('/%[0-9A-Fa-f]{2}/', $callback, $component); @@ -1582,11 +1584,11 @@ public class XomwParser implements XomwParserIface { // $imagesfrom = this.mOptions->getAllowExternalImagesFrom(); // $imagesexception = !empty($imagesfrom); // $text = false; -// # $imagesfrom could be either a single String or an array of strings, parse out the latter +// // $imagesfrom could be either a single String or an array of strings, parse out the latter // if ($imagesexception && is_array($imagesfrom)) { // $imagematch = false; -// foreach ($imagesfrom as $match) { -// if (strpos($url, $match) === 0) { +// foreach ($imagesfrom as match) { +// if (strpos($url, match) === 0) { // $imagematch = true; // break; // } @@ -1600,13 +1602,13 @@ public class XomwParser implements XomwParserIface { // if (this.mOptions->getAllowExternalImages() // || ($imagesexception && $imagematch) // ) { -// if (preg_match(self::EXT_IMAGE_REGEX, $url)) { -// # Image found +// if (preg_match(XomwParser.EXT_IMAGE_REGEX, $url)) { +// // Image found // $text = Linker::makeExternalImage($url); // } // } // if (!$text && this.mOptions->getEnableImageWhitelist() -// && preg_match(self::EXT_IMAGE_REGEX, $url) +// && preg_match(XomwParser.EXT_IMAGE_REGEX, $url) // ) { // $whitelist = explode( // "\n", @@ -1614,12 +1616,12 @@ public class XomwParser implements XomwParserIface { // ); // // foreach ($whitelist as $entry) { -// # Sanitize the regex fragment, make it case-insensitive, ignore blank entries/comments +// // Sanitize the regex fragment, make it case-insensitive, ignore blank entries/comments // if (strpos($entry, '#') === 0 || $entry === '') { // continue; // } // if (preg_match('/' . str_replace('/', '\\/', $entry) . '/i', $url)) { -// # Image matches a whitelist entry +// // Image matches a whitelist entry // $text = Linker::makeExternalImage($url); // break; // } @@ -1674,7 +1676,7 @@ public class XomwParser implements XomwParserIface { public byte[] armorLinks(Bry_bfr trg, byte[] src, int src_bgn, int src_end) { // XO.MW.PORTED // return preg_replace('/\b((?i)' . this.mUrlProtocols . ')/', - // self::MARKER_PREFIX . "NOPARSE$1", $text); + // XomwParser.MARKER_PREFIX . "NOPARSE$1", $text); int cur = src_bgn; int prv = cur; boolean dirty = false; @@ -1729,7 +1731,7 @@ public class XomwParser implements XomwParserIface { // * @return boolean // */ // public function areSubpagesAllowed() { -// # Some namespaces don't allow subpages +// // Some namespaces don't allow subpages // return MWNamespace::hasSubpages(this.mTitle->getNamespace()); // } // @@ -1907,18 +1909,18 @@ public class XomwParser implements XomwParserIface { // case 'pageid': // requested in T25427 // $pageid = this.getTitle()->getArticleID(); // if ($pageid == 0) { -// # 0 means the page doesn't exist in the database, -// # which means the user is previewing a new page. -// # The vary-revision flag must be set, because the magic word -// # will have a different value once the page is saved. +// // 0 means the page doesn't exist in the database, +// // which means the user is previewing a new page. +// // The vary-revision flag must be set, because the magic word +// // will have a different value once the page is saved. // this.mOutput->setFlag('vary-revision'); // wfDebug(__METHOD__ . ": {{PAGEID}} used in a new page, setting vary-revision...\n"); // } // $value = $pageid ? $pageid : null; // break; // case 'revisionid': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned. // this.mOutput->setFlag('vary-revision-id'); // wfDebug(__METHOD__ . ": {{REVISIONID}} used, setting vary-revision-id...\n"); // $value = this.mRevisionId; @@ -1928,50 +1930,50 @@ public class XomwParser implements XomwParserIface { // } // break; // case 'revisionday': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned. This is for null edits. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned. This is for null edits. // this.mOutput->setFlag('vary-revision'); // wfDebug(__METHOD__ . ": {{REVISIONDAY}} used, setting vary-revision...\n"); // $value = intval(substr(this.getRevisionTimestamp(), 6, 2)); // break; // case 'revisionday2': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned. This is for null edits. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned. This is for null edits. // this.mOutput->setFlag('vary-revision'); // wfDebug(__METHOD__ . ": {{REVISIONDAY2}} used, setting vary-revision...\n"); // $value = substr(this.getRevisionTimestamp(), 6, 2); // break; // case 'revisionmonth': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned. This is for null edits. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned. This is for null edits. // this.mOutput->setFlag('vary-revision'); // wfDebug(__METHOD__ . ": {{REVISIONMONTH}} used, setting vary-revision...\n"); // $value = substr(this.getRevisionTimestamp(), 4, 2); // break; // case 'revisionmonth1': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned. This is for null edits. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned. This is for null edits. // this.mOutput->setFlag('vary-revision'); // wfDebug(__METHOD__ . ": {{REVISIONMONTH1}} used, setting vary-revision...\n"); // $value = intval(substr(this.getRevisionTimestamp(), 4, 2)); // break; // case 'revisionyear': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned. This is for null edits. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned. This is for null edits. // this.mOutput->setFlag('vary-revision'); // wfDebug(__METHOD__ . ": {{REVISIONYEAR}} used, setting vary-revision...\n"); // $value = substr(this.getRevisionTimestamp(), 0, 4); // break; // case 'revisiontimestamp': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned. This is for null edits. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned. This is for null edits. // this.mOutput->setFlag('vary-revision'); // wfDebug(__METHOD__ . ": {{REVISIONTIMESTAMP}} used, setting vary-revision...\n"); // $value = this.getRevisionTimestamp(); // break; // case 'revisionuser': -// # Let the edit saving system know we should parse the page -// # *after* a revision ID has been assigned for null edits. +// // Let the edit saving system know we should parse the page +// // *after* a revision ID has been assigned for null edits. // this.mOutput->setFlag('vary-user'); // wfDebug(__METHOD__ . ": {{REVISIONUSER}} used, setting vary-user...\n"); // $value = this.getRevisionUser(); @@ -2015,8 +2017,8 @@ public class XomwParser implements XomwParserIface { // $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('H'), true); // break; // case 'currentweek': -// # @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to -// # int to remove the padding +// // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to +// // int to remove the padding // $value = $pageLang->formatNum((int)MWTimestamp::getInstance($ts)->format('W')); // break; // case 'currentdow': @@ -2041,8 +2043,8 @@ public class XomwParser implements XomwParserIface { // $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('H'), true); // break; // case 'localweek': -// # @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to -// # int to remove the padding +// // @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to +// // int to remove the padding // $value = $pageLang->formatNum((int)MWTimestamp::getLocalInstance($ts)->format('W')); // break; // case 'localdow': @@ -2137,7 +2139,7 @@ public class XomwParser implements XomwParserIface { * * @param String $text The text to parse * @param int $flags Bitwise combination of: - * - self::PTD_FOR_INCLUSION: Handle "" and "" as if the text is being + * - XomwParser.PTD_FOR_INCLUSION: Handle "" and "" as if the text is being * included. Default is to assume a direct page view. * * The generated DOM tree must depend only on the input text and the flags. @@ -2183,10 +2185,10 @@ public class XomwParser implements XomwParserIface { * with the appropriate text. Templates are substituted recursively, * taking care to avoid infinite loops. * - * Note that the substitution depends on value of $mOutputType: - * self::OT_WIKI: only {{subst:}} templates - * self::OT_PREPROCESS: templates but not extension tags - * self::OT_HTML: all templates and extension tags + * Note that the substitution depends on value of mOutputType: + * XomwParser.OT_WIKI: only {{subst:}} templates + * XomwParser.OT_PREPROCESS: templates but not extension tags + * XomwParser.OT_HTML: all templates and extension tags * * @param String $text The text to transform * @param boolean|PPFrame $frame Object describing the arguments passed to the @@ -2271,14 +2273,14 @@ public class XomwParser implements XomwParserIface { // * 'expansion-depth-exceeded-warning', // * 'expansion-depth-exceeded-category') // * @param String|int|null $current Current value -// * @param String|int|null $max Maximum allowed, when an explicit limit has been +// * @param String|int|null max Maximum allowed, when an explicit limit has been // * exceeded, provide the values (optional) // */ -// public function limitationWarn($limitationType, $current = '', $max = '') { -// # does no harm if $current and $max are present but are unnecessary for the message -// # Not doing ->inLanguage(this.mOptions->getUserLangObj()), since this is shown -// # only during preview, and that would split the parser cache unnecessarily. -// $warning = wfMessage("$limitationType-warning")->numParams($current, $max) +// public function limitationWarn($limitationType, $current = '', max = '') { +// // does no harm if $current and max are present but are unnecessary for the message +// // Not doing ->inLanguage(this.mOptions->getUserLangObj()), since this is shown +// // only during preview, and that would split the parser cache unnecessarily. +// $warning = wfMessage("$limitationType-warning")->numParams($current, max) // ->text(); // this.mOutput->addWarning($warning); // this.addTrackingCategory("$limitationType-category"); @@ -2296,7 +2298,7 @@ public class XomwParser implements XomwParserIface { // * @throws Exception // * @return String The text of the template // */ -// public function braceSubstitution($piece, $frame) { + public XophpArray braceSubstitution(XophpArray piece, XomwPPFrame frame) { // // // Flags // @@ -2313,42 +2315,42 @@ public class XomwParser implements XomwParserIface { // // $text is a DOM node needing expansion in the current frame // $isLocalObj = false; // -// # Title Object, where $text came from +// // Title Object, where $text came from // $title = false; // -// # $part1 is the bit before the first |, and must contain only title characters. -// # Various prefixes will be stripped from it later. +// // $part1 is the bit before the first |, and must contain only title characters. +// // Various prefixes will be stripped from it later. // $titleWithSpaces = $frame->expand($piece['title']); // $part1 = trim($titleWithSpaces); // $titleText = false; // -// # Original title text preserved for various purposes +// // Original title text preserved for various purposes // $originalTitle = $part1; // -// # $args is a list of argument nodes, starting from index 0, not including $part1 -// # @todo FIXME: If piece['parts'] is null then the call to getLength() -// # below won't work b/c this $args isn't an Object +// // $args is a list of argument nodes, starting from index 0, not including $part1 +// // @todo FIXME: If piece['parts'] is null then the call to getLength() +// // below won't work b/c this $args isn't an Object // $args = (null == $piece['parts']) ? [] : $piece['parts']; // // $profileSection = null; // profile templates // -// # SUBST +// // SUBST // if (!$found) { // $substMatch = this.mSubstWords->matchStartAndRemove($part1); // -// # Possibilities for substMatch: "subst", "safesubst" or FALSE -// # Decide whether to expand template or keep wikitext as-is. +// // Possibilities for substMatch: "subst", "safesubst" or FALSE +// // Decide whether to expand template or keep wikitext as-is. // if (this.ot['wiki']) { // if ($substMatch === false) { -// $literal = true; # literal when in PST with no prefix +// $literal = true; // literal when in PST with no prefix // } else { -// $literal = false; # expand when in PST with subst: or safesubst: +// $literal = false; // expand when in PST with subst: or safesubst: // } // } else { // if ($substMatch == 'subst') { -// $literal = true; # literal when not in PST with plain subst: +// $literal = true; // literal when not in PST with plain subst: // } else { -// $literal = false; # expand when not in PST with safesubst: or no prefix +// $literal = false; // expand when not in PST with safesubst: or no prefix // } // } // if ($literal) { @@ -2358,7 +2360,7 @@ public class XomwParser implements XomwParserIface { // } // } // -// # Variables +// // Variables // if (!$found && $args->getLength() == 0) { // $id = this.mVariables->matchStartToEnd($part1); // if ($id !== false) { @@ -2370,26 +2372,26 @@ public class XomwParser implements XomwParserIface { // } // } // -// # MSG, MSGNW and RAW +// // MSG, MSGNW and RAW // if (!$found) { -// # Check for MSGNW: -// $mwMsgnw = MagicWord::get('msgnw'); -// if ($mwMsgnw->matchStartAndRemove($part1)) { +// // Check for MSGNW: +// mwMsgnw = MagicWord::get('msgnw'); +// if (mwMsgnw->matchStartAndRemove($part1)) { // $nowiki = true; // } else { -// # Remove obsolete MSG: -// $mwMsg = MagicWord::get('msg'); -// $mwMsg->matchStartAndRemove($part1); +// // Remove obsolete MSG: +// mwMsg = MagicWord::get('msg'); +// mwMsg->matchStartAndRemove($part1); // } // -// # Check for RAW: -// $mwRaw = MagicWord::get('raw'); -// if ($mwRaw->matchStartAndRemove($part1)) { +// // Check for RAW: +// mwRaw = MagicWord::get('raw'); +// if (mwRaw->matchStartAndRemove($part1)) { // $forceRawInterwiki = true; // } // } // -// # Parser functions +// // Parser functions // if (!$found) { // $colonPos = strpos($part1, ':'); // if ($colonPos !== false) { @@ -2405,18 +2407,18 @@ public class XomwParser implements XomwParserIface { // throw $ex; // } // -// # The interface for parser functions allows for extracting -// # flags into the local scope. Extract any forwarded flags -// # here. +// // The interface for parser functions allows for extracting +// // flags into the local scope. Extract any forwarded flags +// // here. // extract($result); // } // } // -// # Finish mangling title and then check for loops. -// # Set $title to a Title Object and $titleText to the PDBK +// // Finish mangling title and then check for loops. +// // Set $title to a Title Object and $titleText to the PDBK // if (!$found) { // $ns = NS_TEMPLATE; -// # Split the title into page and subpage +// // Split the title into page and subpage // $subpage = ''; // $relative = this.maybeDoSubpageLink($part1, $subpage); // if ($part1 !== $relative) { @@ -2426,11 +2428,11 @@ public class XomwParser implements XomwParserIface { // $title = Title::newFromText($part1, $ns); // if ($title) { // $titleText = $title->getPrefixedText(); -// # Check for language variants if the template is not found +// // Check for language variants if the template is not found // if (this.getConverterLanguage()->hasVariants() && $title->getArticleID() == 0) { // this.getConverterLanguage()->findVariantLink($part1, $title, true); // } -// # Do recursion depth check +// // Do recursion depth check // $limit = this.mOptions->getMaxTemplateDepth(); // if ($frame->depth >= $limit) { // $found = true; @@ -2442,7 +2444,7 @@ public class XomwParser implements XomwParserIface { // } // } // -// # Load from database +// // Load from database // if (!$found && $title) { // $profileSection = this.mProfiler->scopedProfileIn($title->getPrefixedDBkey()); // if (!$title->isExternal()) { @@ -2490,7 +2492,7 @@ public class XomwParser implements XomwParserIface { // } // } // } elseif (MWNamespace::isNonincludable($title->getNamespace())) { -// $found = false; # access denied +// $found = false; // access denied // wfDebug(__METHOD__ . ": template inclusion denied for " . // $title->getPrefixedDBkey() . "\n"); // } else { @@ -2501,27 +2503,27 @@ public class XomwParser implements XomwParserIface { // } // } // -// # If the title is valid but undisplayable, make a link to it +// // If the title is valid but undisplayable, make a link to it // if (!$found && (this.ot['html'] || this.ot['pre'])) { // $text = "[[:$titleText]]"; // $found = true; // } // } elseif ($title->isTrans()) { -// # Interwiki transclusion +// // Interwiki transclusion // if (this.ot['html'] && !$forceRawInterwiki) { // $text = this.interwikiTransclude($title, 'render'); // $isHTML = true; // } else { // $text = this.interwikiTransclude($title, 'raw'); -// # Preprocess it like a template -// $text = this.preprocessToDom($text, self::PTD_FOR_INCLUSION); +// // Preprocess it like a template +// $text = this.preprocessToDom($text, XomwParser.PTD_FOR_INCLUSION); // $isChildObj = true; // } // $found = true; // } // -// # Do infinite loop check -// # This has to be done after redirect resolution to avoid infinite loops via redirects +// // Do infinite loop check +// // This has to be done after redirect resolution to avoid infinite loops via redirects // if (!$frame->loopCheck($title)) { // $found = true; // $text = '' @@ -2531,8 +2533,8 @@ public class XomwParser implements XomwParserIface { // } // } // -// # If we haven't found text to substitute by now, we're done -// # Recover the source wikitext and return it +// // If we haven't found text to substitute by now, we're done +// // Recover the source wikitext and return it // if (!$found) { // $text = $frame->virtualBracketedImplode('{{', '|', '}}', $titleWithSpaces, $args); // if ($profileSection) { @@ -2541,18 +2543,18 @@ public class XomwParser implements XomwParserIface { // return [ 'Object' => $text ]; // } // -// # Expand DOM-style return values in a child frame +// // Expand DOM-style return values in a child frame // if ($isChildObj) { -// # Clean up argument array +// // Clean up argument array // $newFrame = $frame->newChild($args, $title); // // if ($nowiki) { // $text = $newFrame->expand($text, PPFrame::RECOVER_ORIG); // } elseif ($titleText !== false && $newFrame->isEmpty()) { -// # Expansion is eligible for the empty-frame cache +// // Expansion is eligible for the empty-frame cache // $text = $newFrame->cachedExpand($titleText, $text); // } else { -// # Uncached expansion +// // Uncached expansion // $text = $newFrame->expand($text); // } // } @@ -2565,30 +2567,30 @@ public class XomwParser implements XomwParserIface { // this.mProfiler->scopedProfileOut($profileSection); // } // -// # Replace raw HTML by a placeholder +// // Replace raw HTML by a placeholder // if ($isHTML) { // $text = this.insertStripItem($text); // } elseif ($nowiki && (this.ot['html'] || this.ot['pre'])) { -// # Escape nowiki-style return values +// // Escape nowiki-style return values // $text = wfEscapeWikiText($text); // } elseif (is_string($text) // && !$piece['lineStart'] // && preg_match('/^(?:{\\||:|;|#|\*)/', $text) // ) { -// # T2529: if the template begins with a table or block-level -// # element, it should be treated as beginning a new line. -// # This behavior is somewhat controversial. +// // T2529: if the template begins with a table or block-level +// // element, it should be treated as beginning a new line. +// // This behavior is somewhat controversial. // $text = "\n" . $text; // } // // if (is_string($text) && !this.incrementIncludeSize('post-expand', strlen($text))) { -// # Error, oversize inclusion +// // Error, oversize inclusion // if ($titleText !== false) { -// # Make a working, properly escaped link if possible (T25588) +// // Make a working, properly escaped link if possible (T25588) // $text = "[[:$titleText]]"; // } else { -// # This will probably not be a working link, but at least it may -// # provide some hint of where the problem is +// // This will probably not be a working link, but at least it may +// // provide some hint of where the problem is // preg_replace('/^:/', '', $originalTitle); // $text = "[[:$originalTitle]]"; // } @@ -2604,7 +2606,8 @@ public class XomwParser implements XomwParserIface { // } // // return $ret; -// } + return null; + } // // /** // * Call a parser function and return an array with text and flags. @@ -2628,11 +2631,11 @@ public class XomwParser implements XomwParserIface { // public function callParserFunction($frame, $function, array $args = []) { // global $wgContLang; // -// # Case sensitive functions +// // Case sensitive functions // if (isset(this.mFunctionSynonyms[1][$function])) { // $function = this.mFunctionSynonyms[1][$function]; // } else { -// # Case insensitive functions +// // Case insensitive functions // $function = $wgContLang->lc($function); // if (isset(this.mFunctionSynonyms[0][$function])) { // $function = this.mFunctionSynonyms[0][$function]; @@ -2643,14 +2646,14 @@ public class XomwParser implements XomwParserIface { // // list($callback, $flags) = this.mFunctionHooks[$function]; // -// # Workaround for PHP bug 35229 and similar +// // Workaround for PHP bug 35229 and similar // if (!is_callable($callback)) { // throw new MWException("Tag hook for $function is not callable\n"); // } // // $allArgs = [ &$this ]; -// if ($flags & self::SFH_OBJECT_ARGS) { -// # Convert arguments to PPNodes and collect for appending to $allArgs +// if ($flags & XomwParser.SFH_OBJECT_ARGS) { +// // Convert arguments to PPNodes and collect for appending to $allArgs // $funcArgs = []; // foreach ($args as $k => $v) { // if ($v instanceof PPNode || $k === 0) { @@ -2660,11 +2663,11 @@ public class XomwParser implements XomwParserIface { // } // } // -// # Add a frame parameter, and pass the arguments as an array +// // Add a frame parameter, and pass the arguments as an array // $allArgs[] = $frame; // $allArgs[] = $funcArgs; // } else { -// # Convert arguments to plain text and append to $allArgs +// // Convert arguments to plain text and append to $allArgs // foreach ($args as $k => $v) { // if ($v instanceof PPNode) { // $allArgs[] = trim($frame->expand($v)); @@ -2678,9 +2681,9 @@ public class XomwParser implements XomwParserIface { // // $result = call_user_func_array($callback, $allArgs); // -// # The interface for function hooks allows them to return a wikitext -// # String or an array containing the String and any flags. This mungs -// # things around to match what this method should return. +// // The interface for function hooks allows them to return a wikitext +// // String or an array containing the String and any flags. This mungs +// // things around to match what this method should return. // if (!is_array($result)) { // $result =[ // 'found' => true, @@ -2734,7 +2737,7 @@ public class XomwParser implements XomwParserIface { // return [ this.mTplDomCache[$titleText], $title ]; // } // -// # Cache miss, go to the database +// // Cache miss, go to the database // list($text, $title) = this.fetchTemplateAndTitle($title); // // if ($text === false) { @@ -2742,7 +2745,7 @@ public class XomwParser implements XomwParserIface { // return [ false, $title ]; // } // -// $dom = this.preprocessToDom($text, self::PTD_FOR_INCLUSION); +// $dom = this.preprocessToDom($text, XomwParser.PTD_FOR_INCLUSION); // this.mTplDomCache[$titleText] = $dom; // // if (!$title->equals($cacheTitle)) { @@ -2850,12 +2853,12 @@ public class XomwParser implements XomwParserIface { // $finalTitle = $title; // $deps = []; // -// # Loop to fetch the article, with up to 1 redirect +// // Loop to fetch the article, with up to 1 redirect // // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed // for ($i = 0; $i < 2 && is_object($title); $i++) { // // @codingStandardsIgnoreEnd -// # Give extensions a chance to select the revision instead -// $id = false; # Assume current +// // Give extensions a chance to select the revision instead +// $id = false; // Assume current // Hooks::run('BeforeParserFetchTemplateAndtitle', // [ $parser, $title, &$skip, &$id ]); // @@ -2868,7 +2871,7 @@ public class XomwParser implements XomwParserIface { // ]; // break; // } -// # Get the revision +// // Get the revision // if ($id) { // $rev = Revision::newFromId($id); // } elseif ($parser) { @@ -2877,7 +2880,7 @@ public class XomwParser implements XomwParserIface { // $rev = Revision::newFromTitle($title); // } // $rev_id = $rev ? $rev->getId() : 0; -// # If there is no current revision, there is no page +// // If there is no current revision, there is no page // if ($id === false && !$rev) { // $linkCache = LinkCache::singleton(); // $linkCache->addBadLinkObj($title); @@ -2888,7 +2891,7 @@ public class XomwParser implements XomwParserIface { // 'page_id' => $title->getArticleID(), // 'rev_id' => $rev_id ]; // if ($rev && !$title->equals($rev->getTitle())) { -// # We fetched a rev from a different title; register it too... +// // We fetched a rev from a different title; register it too... // $deps[] = [ // 'title' => $rev->getTitle(), // 'page_id' => $rev->getPage(), @@ -2908,20 +2911,20 @@ public class XomwParser implements XomwParserIface { // } // } elseif ($title->getNamespace() == NS_MEDIAWIKI) { // global $wgContLang; -// $message = wfMessage($wgContLang->lcfirst($title->getText()))->inContentLanguage(); -// if (!$message->exists()) { +// message = wfMessage($wgContLang->lcfirst($title->getText()))->inContentLanguage(); +// if (!message->exists()) { // $text = false; // break; // } -// $content = $message->content(); -// $text = $message->plain(); +// $content = message->content(); +// $text = message->plain(); // } else { // break; // } // if (!$content) { // break; // } -// # Redirect? +// // Redirect? // $finalTitle = $title; // $title = $content->getRedirectTarget(); // } @@ -2954,10 +2957,10 @@ public class XomwParser implements XomwParserIface { // // $time = $file ? $file->getTimestamp() : false; // $sha1 = $file ? $file->getSha1() : false; -// # Register the file as a dependency... +// // Register the file as a dependency... // this.mOutput->addImage($title->getDBkey(), $time, $sha1); // if ($file && !$title->equals($file->getTitle())) { -// # Update fetched file title +// // Update fetched file title // $title = $file->getTitle(); // this.mOutput->addImage($title->getDBkey(), $time, $sha1); // } @@ -3042,17 +3045,17 @@ public class XomwParser implements XomwParserIface { // ]); // return $text; // } -// -// /** -// * Triple brace replacement -- used for template arguments -// * @private -// * -// * @param array $piece -// * @param PPFrame $frame -// * -// * @return array -// */ -// public function argSubstitution($piece, $frame) { + + /** + * Triple brace replacement -- used for template arguments + * @private + * + * @param array $piece + * @param PPFrame $frame + * + * @return array + */ + public XophpArray argSubstitution(XophpArray piece, XomwPPFrame frame) { // // $error = false; // $parts = $piece['parts']; @@ -3066,7 +3069,7 @@ public class XomwParser implements XomwParserIface { // || (this.ot['wiki'] && $frame->isTemplate()) // ) // ) { -// # No match in frame, use the supplied default +// // No match in frame, use the supplied default // $Object = $parts->item(0)->getChildren(); // } // if (!this.incrementIncludeSize('arg', strlen($text))) { @@ -3075,7 +3078,7 @@ public class XomwParser implements XomwParserIface { // } // // if ($text === false && $Object === false) { -// # No match anywhere +// // No match anywhere // $Object = $frame->virtualBracketedImplode('{{{', '|', '}}}', $nameWithSpaces, $parts); // } // if ($error !== false) { @@ -3088,24 +3091,25 @@ public class XomwParser implements XomwParserIface { // } // // return $ret; -// } -// -// /** -// * Return the text to be used for a given extension tag. -// * This is the ghost of strip(). -// * -// * @param array $params Associative array of parameters: -// * name PPNode for the tag name -// * attr PPNode for unparsed text where tag attributes are thought to be -// * attributes Optional associative array of parsed attributes -// * inner Contents of extension element -// * noClose Original text did not have a close tag -// * @param PPFrame $frame -// * -// * @throws MWException -// * @return String -// */ -// public function extensionSubstitution($params, $frame) { + return null; + } + + /** + * Return the text to be used for a given extension tag. + * This is the ghost of strip(). + * + * @param array $Associative array of parameters: + * name PPNode for the tag name + * attr PPNode for unparsed text where tag attributes are thought to be + * attributes Optional associative array of parsed attributes + * inner Contents of extension element + * noClose Original text did not have a close tag + * @param PPFrame $frame + * + * @throws MWException + * @return String + */ + public String extensionSubstitution(XophpArray paramsAry, XomwPPFrame frame) { // static $errorStr = ''; // static $errorLen = 20; // @@ -3127,15 +3131,15 @@ public class XomwParser implements XomwParserIface { // // (T149622). // $content = !isset($params['inner']) ? null : $frame->expand($params['inner']); // -// $marker = self::MARKER_PREFIX . "-$name-" -// . sprintf('%08X', this.mMarkerIndex++) . self::MARKER_SUFFIX; +// marker = XomwParser.MARKER_PREFIX . "-$name-" +// . sprintf('%08X', this.mMarkerIndex++) . XomwParser.MARKER_SUFFIX; // // $isFunctionTag = isset(this.mFunctionTagHooks[strtolower($name)]) && // (this.ot['html'] || this.ot['pre']); // if ($isFunctionTag) { -// $markerType = 'none'; +// markerType = 'none'; // } else { -// $markerType = 'general'; +// markerType = 'general'; // } // if (this.ot['html'] || $isFunctionTag) { // $name = strtolower($name); @@ -3145,7 +3149,7 @@ public class XomwParser implements XomwParserIface { // } // // if (isset(this.mTagHooks[$name])) { -// # Workaround for PHP bug 35229 and similar +// // Workaround for PHP bug 35229 and similar // if (!is_callable(this.mTagHooks[$name])) { // throw new MWException("Tag hook for $name is not callable\n"); // } @@ -3164,7 +3168,7 @@ public class XomwParser implements XomwParserIface { // } // // if (is_array($output)) { -// # Extract flags to local scope (to override $markerType) +// // Extract flags to local scope (to override markerType) // $flags = $output; // $output = $flags[0]; // unset($flags[0]); @@ -3192,17 +3196,18 @@ public class XomwParser implements XomwParserIface { // } // } // -// if ($markerType === 'none') { +// if (markerType === 'none') { // return $output; -// } elseif ($markerType === 'nowiki') { -// this.mStripState->addNoWiki($marker, $output); -// } elseif ($markerType === 'general') { -// this.mStripState->addGeneral($marker, $output); +// } elseif (markerType === 'nowiki') { +// this.mStripState->addNoWiki(marker, $output); +// } elseif (markerType === 'general') { +// this.mStripState->addGeneral(marker, $output); // } else { // throw new MWException(__METHOD__ . ': invalid marker type'); // } -// return $marker; -// } +// return marker; + return null; + } // // /** // * Increment an include size counter @@ -3235,11 +3240,11 @@ public class XomwParser implements XomwParserIface { // /** // * @see ParserOutput::addTrackingCategory() -// * @param String $msg Message key +// * @param String msg Message key // * @return boolean Whether the addition was successful // */ -// public function addTrackingCategory($msg) { -// return this.mOutput->addTrackingCategory($msg, this.mTitle); +// public function addTrackingCategory(msg) { +// return this.mOutput->addTrackingCategory(msg, this.mTitle); // } // // /** @@ -3261,56 +3266,56 @@ public class XomwParser implements XomwParserIface { // public function formatHeadings($text, $origText, $isMain = true) { // global $wgMaxTocLevel, $wgExperimentalHtmlIds; // -// # Inhibit editsection links if requested in the page +// // Inhibit editsection links if requested in the page // if (isset(this.mDoubleUnderscores['noeditsection'])) { -// $maybeShowEditLink = $showEditLink = false; +// maybeShowEditLink = $showEditLink = false; // } else { -// $maybeShowEditLink = true; /* Actual presence will depend on ParserOptions option */ +// maybeShowEditLink = true; /* Actual presence will depend on ParserOptions option */ // $showEditLink = this.mOptions->getEditSection(); // } // if ($showEditLink) { // this.mOutput->setEditSectionTokens(true); // } // -// # Get all headlines for numbering them and adding funky stuff like [edit] -// # links - this is for later, but we need the number of headlines right now -// $matches = []; +// // Get all headlines for numbering them and adding funky stuff like [edit] +// // links - this is for later, but we need the number of headlines right now +// matches = ...; // $numMatches = preg_match_all( // '/[1-6])(?P.*?>)\s*(?P
[\s\S]*?)\s*<\/H[1-6] *>/i', // $text, -// $matches +// matches // ); // -// # if there are fewer than 4 headlines in the article, do not show TOC -// # unless it's been explicitly enabled. +// // if there are fewer than 4 headlines in the article, do not show TOC +// // unless it's been explicitly enabled. // $enoughToc = this.mShowToc && // (($numMatches >= 4) || this.mForceTocPosition); // -// # Allow user to stipulate that a page should have a "new section" -// # link added via __NEWSECTIONLINK__ +// // Allow user to stipulate that a page should have a "new section" +// // link added via __NEWSECTIONLINK__ // if (isset(this.mDoubleUnderscores['newsectionlink'])) { // this.mOutput->setNewSection(true); // } // -// # Allow user to remove the "new section" -// # link via __NONEWSECTIONLINK__ +// // Allow user to remove the "new section" +// // link via __NONEWSECTIONLINK__ // if (isset(this.mDoubleUnderscores['nonewsectionlink'])) { // this.mOutput->hideNewSection(true); // } // -// # if the String __FORCETOC__ (not case-sensitive) occurs in the HTML, -// # override above conditions and always show TOC above first header +// // if the String __FORCETOC__ (not case-sensitive) occurs in the HTML, +// // override above conditions and always show TOC above first header // if (isset(this.mDoubleUnderscores['forcetoc'])) { // this.mShowToc = true; // $enoughToc = true; // } // -// # headline counter +// // headline counter // $headlineCount = 0; // $numVisible = 0; // -// # Ugh .. the TOC should have neat indentation levels which can be -// # passed to the skin functions. These are determined here +// // Ugh .. the TOC should have neat indentation levels which can be +// // passed to the skin functions. These are determined here // $toc = ''; // $full = ''; // $head = []; @@ -3320,10 +3325,10 @@ public class XomwParser implements XomwParserIface { // $prevlevel = 0; // $toclevel = 0; // $prevtoclevel = 0; -// $markerRegex = self::MARKER_PREFIX . "-h-(\d+)-" . self::MARKER_SUFFIX; +// markerRegex = XomwParser.MARKER_PREFIX . "-h-(\d+)-" . XomwParser.MARKER_SUFFIX; // $baseTitleText = this.mTitle->getPrefixedDBkey(); // $oldType = this.mOutputType; -// this.setOutputType(self::OT_WIKI); +// this.setOutputType(XomwParser.OT_WIKI); // $frame = this.getPreprocessor()->newFrame(); // $root = this.preprocessToDom($origText); // $node = $root->getFirstChild(); @@ -3331,28 +3336,28 @@ public class XomwParser implements XomwParserIface { // $tocraw = []; // $refers = []; // -// $headlines = $numMatches !== false ? $matches[3] : []; +// $headlines = $numMatches !== false ? matches[3] : []; // // foreach ($headlines as $headline) { // $isTemplate = false; // $titleText = false; // $sectionIndex = false; // $numbering = ''; -// $markerMatches = []; -// if (preg_match("/^$markerRegex/", $headline, $markerMatches)) { -// $serial = $markerMatches[1]; +// markerMatches = []; +// if (preg_match("/^markerRegex/", $headline, markerMatches)) { +// $serial = markerMatches[1]; // list($titleText, $sectionIndex) = this.mHeadings[$serial]; // $isTemplate = ($titleText != $baseTitleText); -// $headline = preg_replace("/^$markerRegex\\s*/", "", $headline); +// $headline = preg_replace("/^markerRegex\\s*/", "", $headline); // } // // if ($toclevel) { // $prevlevel = $level; // } -// $level = $matches[1][$headlineCount]; +// $level = matches[1][$headlineCount]; // // if ($level > $prevlevel) { -// # Increase TOC level +// // Increase TOC level // $toclevel++; // $sublevelCount[$toclevel] = 0; // if ($toclevel < $wgMaxTocLevel) { @@ -3361,15 +3366,15 @@ public class XomwParser implements XomwParserIface { // $numVisible++; // } // } elseif ($level < $prevlevel && $toclevel > 1) { -// # Decrease TOC level, find level to jump to +// // Decrease TOC level, find level to jump to // // for ($i = $toclevel; $i > 0; $i--) { // if ($levelCount[$i] == $level) { -// # Found last matching level +// // Found last matching level // $toclevel = $i; // break; // } elseif ($levelCount[$i] < $level) { -// # Found first matching level below current level +// // Found first matching level below current level // $toclevel = $i + 1; // break; // } @@ -3379,7 +3384,7 @@ public class XomwParser implements XomwParserIface { // } // if ($toclevel < $wgMaxTocLevel) { // if ($prevtoclevel < $wgMaxTocLevel) { -// # Unindent only if the previous toc level was shown :p +// // Unindent only if the previous toc level was shown :p // $toc .= Linker::tocUnindent($prevtoclevel - $toclevel); // $prevtoclevel = $toclevel; // } else { @@ -3387,7 +3392,7 @@ public class XomwParser implements XomwParserIface { // } // } // } else { -// # No change in level, end TOC line +// // No change in level, end TOC line // if ($toclevel < $wgMaxTocLevel) { // $toc .= Linker::tocLineEnd(); // } @@ -3395,7 +3400,7 @@ public class XomwParser implements XomwParserIface { // // $levelCount[$toclevel] = $level; // -// # count number of headlines for each level +// // count number of headlines for each level // $sublevelCount[$toclevel]++; // $dot = 0; // for ($i = 1; $i <= $toclevel; $i++) { @@ -3408,28 +3413,28 @@ public class XomwParser implements XomwParserIface { // } // } // -// # The safe header is a version of the header text safe to use for links +// // The safe header is a version of the header text safe to use for links // -// # Remove link placeholders by the link text. -// # -// # turns into -// # link text with suffix -// # Do this before unstrip since link text can contain strip markers +// // Remove link placeholders by the link text. +// // +// // turns into +// // link text with suffix +// // Do this before unstrip since link text can contain strip markers // $safeHeadline = this.replaceLinkHoldersText($headline); // -// # Avoid insertion of weird stuff like by expanding the relevant sections +// // Avoid insertion of weird stuff like by expanding the relevant sections // $safeHeadline = this.mStripState->unstripBoth($safeHeadline); // -// # Strip out HTML (first regex removes any tag not allowed) -// # Allowed tags are: -// # * and (T10393) -// # * (T28375) -// # * (r105284) -// # * (T74884) -// # * and (T37167) -// # * and (T35715) -// # We strip any parameter from accepted tags (second regex), except dir="rtl|ltr" from , -// # to allow setting directionality in toc items. +// // Strip out HTML (first regex removes any tag not allowed) +// // Allowed tags are: +// // * and (T10393) +// // * (T28375) +// // * (r105284) +// // * (T74884) +// // * and (T37167) +// // * and (T35715) +// // We strip any parameter from accepted tags (second regex), except dir="rtl|ltr" from , +// // to allow setting directionality in toc items. // $tocline = preg_replace( // [ // '#<(?!/?(span|sup|sub|bdi|i|b|s|strike)(?: [^>]*)?>).*?>#', @@ -3439,36 +3444,36 @@ public class XomwParser implements XomwParserIface { // $safeHeadline // ); // -// # Strip '', which is the result from the above if -// # is used to produce an additional anchor -// # for a section. +// // Strip '', which is the result from the above if +// // is used to produce an additional anchor +// // for a section. // $tocline = str_replace('', '', $tocline); // // $tocline = trim($tocline); // -// # For the anchor, strip out HTML-y stuff period +// // For the anchor, strip out HTML-y stuff period // $safeHeadline = preg_replace('/<.*?>/', '', $safeHeadline); // $safeHeadline = Sanitizer::normalizeSectionNameWhitespace($safeHeadline); // -// # Save headline for section edit hint before it's escaped +// // Save headline for section edit hint before it's escaped // $headlineHint = $safeHeadline; // // if ($wgExperimentalHtmlIds) { -// # For reverse compatibility, provide an id that's -// # HTML4-compatible, like we used to. -// # It may be worth noting, academically, that it's possible for -// # the legacy anchor to conflict with a non-legacy headline -// # anchor on the page. In this case likely the "correct" thing -// # would be to either drop the legacy anchors or make sure -// # they're numbered first. However, this would require people -// # to type in section names like "abc_.D7.93.D7.90.D7.A4" -// # manually, so let's not bother worrying about it. +// // For reverse compatibility, provide an id that's +// // HTML4-compatible, like we used to. +// // It may be worth noting, academically, that it's possible for +// // the legacy anchor to conflict with a non-legacy headline +// // anchor on the page. In this case likely the "correct" thing +// // would be to either drop the legacy anchors or make sure +// // they're numbered first. However, this would require people +// // to type in section names like "abc_.D7.93.D7.90.D7.A4" +// // manually, so let's not bother worrying about it. // $legacyHeadline = Sanitizer::escapeId($safeHeadline, // [ 'noninitial', 'legacy' ]); // $safeHeadline = Sanitizer::escapeId($safeHeadline); // // if ($legacyHeadline == $safeHeadline) { -// # No reason to have both (in fact, we can't) +// // No reason to have both (in fact, we can't) // $legacyHeadline = false; // } // } else { @@ -3477,10 +3482,10 @@ public class XomwParser implements XomwParserIface { // 'noninitial'); // } // -// # HTML names must be case-insensitively unique (T12721). -// # This does not apply to Unicode characters per -// # https://www.w3.org/TR/html5/infrastructure.html#case-sensitivity-and-String-comparison -// # @todo FIXME: We may be changing them depending on the current locale. +// // HTML names must be case-insensitively unique (T12721). +// // This does not apply to Unicode characters per +// // https://www.w3.org/TR/html5/infrastructure.html#case-sensitivity-and-String-comparison +// // @todo FIXME: We may be changing them depending on the current locale. // $arrayKey = strtolower($safeHeadline); // if ($legacyHeadline === false) { // $legacyArrayKey = false; @@ -3488,7 +3493,7 @@ public class XomwParser implements XomwParserIface { // $legacyArrayKey = strtolower($legacyHeadline); // } // -// # Create the anchor for linking from the TOC to the section +// // Create the anchor for linking from the TOC to the section // $anchor = $safeHeadline; // $legacyAnchor = $legacyHeadline; // if (isset($refers[$arrayKey])) { @@ -3510,9 +3515,9 @@ public class XomwParser implements XomwParserIface { // $refers[$legacyArrayKey] = true; // } // -// # Don't number the heading if it is the only one (looks silly) -// if (count($matches[3]) > 1 && this.mOptions->getNumberHeadings()) { -// # the two are different if the line contains a link +// // Don't number the heading if it is the only one (looks silly) +// if (count(matches[3]) > 1 && this.mOptions->getNumberHeadings()) { +// // the two are different if the line contains a link // $headline = Html::element( // 'span', // [ 'class' => 'mw-headline-number' ], @@ -3525,8 +3530,8 @@ public class XomwParser implements XomwParserIface { // $numbering, $toclevel, ($isTemplate ? false : $sectionIndex)); // } // -// # Add the section to the section tree -// # Find the DOM node for this header +// // Add the section to the section tree +// // Find the DOM node for this header // $noOffset = ($isTemplate || $sectionIndex === false); // while ($node && !$noOffset) { // if ($node->getName() === 'h') { @@ -3550,12 +3555,12 @@ public class XomwParser implements XomwParserIface { // 'anchor' => $anchor, // ]; // -// # give headline the correct tag -// if ($maybeShowEditLink && $sectionIndex !== false) { +// // give headline the correct tag +// if (maybeShowEditLink && $sectionIndex !== false) { // // Output edit section links as markers with styles that can be customized by skins // if ($isTemplate) { -// # Put a T flag in the section identifier, to indicate to extractSections() -// # that sections inside should be counted. +// // Put a T flag in the section identifier, to indicate to extractSections() +// // that sections inside should be counted. // $editsectionPage = $titleText; // $editsectionSection = "T-$sectionIndex"; // $editsectionContent = null; @@ -3587,7 +3592,7 @@ public class XomwParser implements XomwParserIface { // $editlink = ''; // } // $head[$headlineCount] = Linker::makeHeadline($level, -// $matches['attrib'][$headlineCount], $anchor, $headline, +// matches['attrib'][$headlineCount], $anchor, $headline, // $editlink, $legacyAnchor); // // $headlineCount++; @@ -3595,7 +3600,7 @@ public class XomwParser implements XomwParserIface { // // this.setOutputType($oldType); // -// # Never ever show TOC if no headers +// // Never ever show TOC if no headers // if ($numVisible < 1) { // $enoughToc = false; // } @@ -3606,7 +3611,7 @@ public class XomwParser implements XomwParserIface { // } // $toc = Linker::tocList($toc, this.mOptions->getUserLangObj()); // this.mOutput->setTOCHTML($toc); -// $toc = self::TOC_START . $toc . self::TOC_END; +// $toc = XomwParser.TOC_START . $toc . XomwParser.TOC_END; // this.mOutput->addModules('mediawiki.toc'); // } // @@ -3614,7 +3619,7 @@ public class XomwParser implements XomwParserIface { // this.mOutput->setSections($tocraw); // } // -// # split up and insert constructed headlines +// // split up and insert constructed headlines // $blocks = preg_split('/[\s\S]*?<\/H[1-6]>/i', $text); // $i = 0; // @@ -3673,9 +3678,9 @@ public class XomwParser implements XomwParserIface { // ParserOptions $options, $clearState = true // ) { // if ($clearState) { -// $magicScopeVariable = this.synchronized(); +// magicScopeVariable = this.synchronized(); // } -// this.startParse($title, $options, self::OT_WIKI, $clearState); +// this.startParse($title, $options, XomwParser.OT_WIKI, $clearState); // this.setUser($user); // // // We still normalize line endings for backwards-compatibility @@ -3688,7 +3693,7 @@ public class XomwParser implements XomwParserIface { // } // $text = this.mStripState->unstripBoth($text); // -// this.setUser(null); # Reset +// this.setUser(null); // Reset // // return $text; // } @@ -3704,11 +3709,11 @@ public class XomwParser implements XomwParserIface { // private function pstPass2($text, $user) { // global $wgContLang; // -// # Note: This is the timestamp saved as hardcoded wikitext to -// # the database, we use $wgContLang here in order to give -// # everyone the same signature and use the default one rather -// # than the one selected in each user's preferences. -// # (see also T14815) +// // Note: This is the timestamp saved as hardcoded wikitext to +// // the database, we use $wgContLang here in order to give +// // everyone the same signature and use the default one rather +// // than the one selected in each user's preferences. +// // (see also T14815) // $ts = this.mOptions->getTimestamp(); // $timestamp = MWTimestamp::getLocalInstance($ts); // $ts = $timestamp->format('YmdHis'); @@ -3716,14 +3721,14 @@ public class XomwParser implements XomwParserIface { // // $d = $wgContLang->timeanddate($ts, false, false) . " ($tzMsg)"; // -// # Variable replacement -// # Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags +// // Variable replacement +// // Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags // $text = this.replaceVariables($text); // -// # This works almost by chance, as the replaceVariables are done before the getUserSig(), -// # which may corrupt this parser instance via its wfMessage()->text() call- +// // This works almost by chance, as the replaceVariables are done before the getUserSig(), +// // which may corrupt this parser instance via its wfMessage()->text() call- // -// # Signatures +// // Signatures // $sigText = this.getUserSig($user); // $text = strtr($text, [ // '~~~~~' => $d, @@ -3731,9 +3736,9 @@ public class XomwParser implements XomwParserIface { // '~~~' => $sigText // ]); // -// # Context links ("pipe tricks"): [[|name]] and [[name (context)|]] +// // Context links ("pipe tricks"): [[|name]] and [[name (context)|]] // $tc = '[' . Title::legalChars() . ']'; -// $nc = '[ _0-9A-Za-z\x80-\xff-]'; # Namespaces can use non-ascii! +// $nc = '[ _0-9A-Za-z\x80-\xff-]'; // Namespaces can use non-ascii! // // // [[ns:page (context)|]] // $p1 = "/\[\[(:?$nc+:|:|)($tc+?)(?\\($tc+\\))\\|]]/"; @@ -3744,19 +3749,19 @@ public class XomwParser implements XomwParserIface { // // [[|page]] (reverse pipe trick: add context from page title) // $p2 = "/\[\[\\|($tc+)]]/"; // -// # try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]" +// // try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]" // $text = preg_replace($p1, '[[\\1\\2\\3|\\2]]', $text); // $text = preg_replace($p4, '[[\\1\\2\\3|\\2]]', $text); // $text = preg_replace($p3, '[[\\1\\2\\3\\4|\\2]]', $text); // // $t = this.mTitle->getText(); -// $m = []; -// if (preg_match("/^($nc+:|)$tc+?(\\($tc+\\))$/", $t, $m)) { -// $text = preg_replace($p2, "[[$m[1]\\1$m[2]|\\1]]", $text); -// } elseif (preg_match("/^($nc+:|)$tc+?(, $tc+|)$/", $t, $m) && "$m[1]$m[2]" != '') { -// $text = preg_replace($p2, "[[$m[1]\\1$m[2]|\\1]]", $text); +// m = []; +// if (preg_match("/^($nc+:|)$tc+?(\\($tc+\\))$/", $t, m)) { +// $text = preg_replace($p2, "[[m[1]\\1m[2]|\\1]]", $text); +// } elseif (preg_match("/^($nc+:|)$tc+?(, $tc+|)$/", $t, m) && "m[1]m[2]" != '') { +// $text = preg_replace($p2, "[[m[1]\\1m[2]|\\1]]", $text); // } else { -// # if there's no context, don't bother duplicating the title +// // if there's no context, don't bother duplicating the title // $text = preg_replace($p2, '[[\\1]]', $text); // } // @@ -3782,7 +3787,7 @@ public class XomwParser implements XomwParserIface { // // $username = $user->getName(); // -// # If not given, retrieve from the user Object. +// // If not given, retrieve from the user Object. // if ($nickname === false) { // $nickname = $user->getOption('nickname'); // } @@ -3797,26 +3802,26 @@ public class XomwParser implements XomwParserIface { // $nickname = $username; // wfDebug(__METHOD__ . ": $username has overlong signature.\n"); // } elseif ($fancySig !== false) { -// # Sig. might contain markup; validate this +// // Sig. might contain markup; validate this // if (this.validateSig($nickname) !== false) { -// # Validated; clean up (if needed) and return it +// // Validated; clean up (if needed) and return it // return this.cleanSig($nickname, true); // } else { -// # Failed to validate; fall back to the default +// // Failed to validate; fall back to the default // $nickname = $username; // wfDebug(__METHOD__ . ": $username has bad XML tags in signature.\n"); // } // } // -// # Make sure nickname doesnt get a sig in a sig -// $nickname = self::cleanSigInSig($nickname); +// // Make sure nickname doesnt get a sig in a sig +// $nickname = XomwParser.cleanSigInSig($nickname); // -// # If we're still here, make it a link to the user page +// // If we're still here, make it a link to the user page // $userText = wfEscapeWikiText($username); // $nickText = wfEscapeWikiText($nickname); -// $msgName = $user->isAnon() ? 'signature-anon' : 'signature'; +// msgName = $user->isAnon() ? 'signature-anon' : 'signature'; // -// return wfMessage($msgName, $userText, $nickText)->inContentLanguage() +// return wfMessage(msgName, $userText, $nickText)->inContentLanguage() // ->title(this.getTitle())->text(); // } // @@ -3843,23 +3848,23 @@ public class XomwParser implements XomwParserIface { // public function cleanSig($text, $parsing = false) { // if (!$parsing) { // global $wgTitle; -// $magicScopeVariable = this.synchronized(); -// this.startParse($wgTitle, new ParserOptions, self::OT_PREPROCESS, true); +// magicScopeVariable = this.synchronized(); +// this.startParse($wgTitle, new ParserOptions, XomwParser.OT_PREPROCESS, true); // } // -// # Option to disable this feature +// // Option to disable this feature // if (!this.mOptions->getCleanSignatures()) { // return $text; // } // -// # @todo FIXME: Regex doesn't respect extension tags or nowiki -// # => Move this logic to braceSubstitution() +// // @todo FIXME: Regex doesn't respect extension tags or nowiki +// // => Move this logic to braceSubstitution() // $substWord = MagicWord::get('subst'); // $substRegex = '/\{\{(?!(?:' . $substWord->getBaseRegex() . '))/x' . $substWord->getRegexCase(); // $substText = '{{' . $substWord->getSynonym(0); // // $text = preg_replace($substRegex, $substText, $text); -// $text = self::cleanSigInSig($text); +// $text = XomwParser.cleanSigInSig($text); // $dom = this.preprocessToDom($text); // $frame = this.getPreprocessor()->newFrame(); // $text = $frame->expand($dom); @@ -3925,7 +3930,7 @@ public class XomwParser implements XomwParserIface { // public function transformMsg($text, $options, $title = null) { // static $executing = false; // -// # Guard against infinite recursion +// // Guard against infinite recursion // if ($executing) { // return $text; // } @@ -3968,8 +3973,8 @@ public class XomwParser implements XomwParserIface { // */ // public function setHook($tag, $callback) { // $tag = strtolower($tag); -// if (preg_match('/[<>\r\n]/', $tag, $m)) { -// throw new MWException("Invalid character {$m[0]} in setHook('$tag', ...) call"); +// if (preg_match('/[<>\r\n]/', $tag, m)) { +// throw new MWException("Invalid character {m[0]} in setHook('$tag', ...) call"); // } // $oldVal = isset(this.mTagHooks[$tag]) ? this.mTagHooks[$tag] : null; // this.mTagHooks[$tag] = $callback; @@ -3999,8 +4004,8 @@ public class XomwParser implements XomwParserIface { // */ // public function setTransparentTagHook($tag, $callback) { // $tag = strtolower($tag); -// if (preg_match('/[<>\r\n]/', $tag, $m)) { -// throw new MWException("Invalid character {$m[0]} in setTransparentHook('$tag', ...) call"); +// if (preg_match('/[<>\r\n]/', $tag, m)) { +// throw new MWException("Invalid character {m[0]} in setTransparentHook('$tag', ...) call"); // } // $oldVal = isset(this.mTransparentTagHooks[$tag]) ? this.mTransparentTagHooks[$tag] : null; // this.mTransparentTagHooks[$tag] = $callback; @@ -4066,25 +4071,25 @@ public class XomwParser implements XomwParserIface { // $oldVal = isset(this.mFunctionHooks[$id]) ? this.mFunctionHooks[$id][0] : null; // this.mFunctionHooks[$id] = [ $callback, $flags ]; // -// # Add to function cache -// $mw = MagicWord::get($id); -// if (!$mw) { +// // Add to function cache +// mw = MagicWord::get($id); +// if (!mw) { // throw new MWException(__METHOD__ . '() expecting a magic word identifier.'); // } // -// $synonyms = $mw->getSynonyms(); -// $sensitive = intval($mw->isCaseSensitive()); +// $synonyms = mw->getSynonyms(); +// $sensitive = intval(mw->isCaseSensitive()); // // foreach ($synonyms as $syn) { -// # Case +// // Case // if (!$sensitive) { // $syn = $wgContLang->lc($syn); // } -// # Add leading hash -// if (!($flags & self::SFH_NO_HASH)) { +// // Add leading hash +// if (!($flags & XomwParser.SFH_NO_HASH)) { // $syn = '#' . $syn; // } -// # Remove trailing colon +// // Remove trailing colon // if (substr($syn, -1, 1) === ':') { // $syn = substr($syn, 0, -1); // } @@ -4114,8 +4119,8 @@ public class XomwParser implements XomwParserIface { // */ // public function setFunctionTagHook($tag, $callback, $flags) { // $tag = strtolower($tag); -// if (preg_match('/[<>\r\n]/', $tag, $m)) { -// throw new MWException("Invalid character {$m[0]} in setFunctionTagHook('$tag', ...) call"); +// if (preg_match('/[<>\r\n]/', $tag, m)) { +// throw new MWException("Invalid character {m[0]} in setFunctionTagHook('$tag', ...) call"); // } // $old = isset(this.mFunctionTagHooks[$tag]) ? // this.mFunctionTagHooks[$tag] : null; @@ -4172,13 +4177,13 @@ public class XomwParser implements XomwParserIface { // */ // public function renderImageGallery($text, $params) { // -// $mode = false; +// mode = false; // if (isset($params['mode'])) { -// $mode = $params['mode']; +// mode = $params['mode']; // } // // try { -// $ig = ImageGalleryBase::factory($mode); +// $ig = ImageGalleryBase::factory(mode); // } catch (Exception $e) { // // If invalid type set, fallback to default. // $ig = ImageGalleryBase::factory(false); @@ -4217,32 +4222,32 @@ public class XomwParser implements XomwParserIface { // // $lines = StringUtils::explode("\n", $text); // foreach ($lines as $line) { -// # match lines like these: -// # Image:someimage.jpg|This is some image -// $matches = []; -// preg_match("/^([^|]+)(\\|(.*))?$/", $line, $matches); -// # Skip empty lines -// if (count($matches) == 0) { +// // match lines like these: +// // Image:someimage.jpg|This is some image +// matches = []; +// preg_match("/^([^|]+)(\\|(.*))?$/", $line, matches); +// // Skip empty lines +// if (count(matches) == 0) { // continue; // } // -// if (strpos($matches[0], '%') !== false) { -// $matches[1] = rawurldecode($matches[1]); +// if (strpos(matches[0], '%') !== false) { +// matches[1] = rawurldecode(matches[1]); // } -// $title = Title::newFromText($matches[1], NS_FILE); +// $title = Title::newFromText(matches[1], NS_FILE); // if (is_null($title)) { -// # Bogus title. Ignore these so we don't bomb out later. +// // Bogus title. Ignore these so we don't bomb out later. // continue; // } // -// # We need to get what handler the file uses, to figure out parameters. -// # Note, a hook can overide the file name, and chose an entirely different -// # file (which potentially could be of a different type and have different handler). +// // We need to get what handler the file uses, to figure out parameters. +// // Note, a hook can overide the file name, and chose an entirely different +// // file (which potentially could be of a different type and have different handler). // $options = []; // $descQuery = false; // Hooks::run('BeforeParserFetchFileAndTitle', // [ $this, $title, &$options, &$descQuery ]); -// # Don't register it now, as TraditionalImageGallery does that later. +// // Don't register it now, as TraditionalImageGallery does that later. // $file = this.fetchFileNoRegister($title, $options); // $handler = $file ? $file->getHandler() : false; // @@ -4257,38 +4262,38 @@ public class XomwParser implements XomwParserIface { // unset($paramMap['img_width']); // } // -// $mwArray = new MagicWordArray(array_keys($paramMap)); +// mwArray = new MagicWordArray(array_keys($paramMap)); // // $label = ''; // $alt = ''; // $link = ''; // $handlerOptions = []; -// if (isset($matches[3])) { +// if (isset(matches[3])) { // // look for an |alt= definition while trying not to break existing // // captions with multiple pipes (|) in it, until a more sensible grammar // // is defined for images in galleries // // // FIXME: Doing recursiveTagParse at this stage, and the trim before // // splitting on '|' is a bit odd, and different from makeImage. -// $matches[3] = this.recursiveTagParse(trim($matches[3])); +// matches[3] = this.recursiveTagParse(trim(matches[3])); // // Protect LanguageConverter markup // $parameterMatches = StringUtils::delimiterExplode( -// '-{', '}-', '|', $matches[3], true /* nested */ +// '-{', '}-', '|', matches[3], true /* nested */ // ); // // foreach ($parameterMatches as $parameterMatch) { -// list($magicName, $match) = $mwArray->matchVariableStartToEnd($parameterMatch); -// if ($magicName) { -// $paramName = $paramMap[$magicName]; +// list(magicName, match) = mwArray->matchVariableStartToEnd($parameterMatch); +// if (magicName) { +// $paramName = $paramMap[magicName]; // // switch ($paramName) { // case 'gallery-@gplx.Internal protected-alt': -// $alt = this.stripAltText($match, false); +// $alt = this.stripAltText(match, false); // break; // case 'gallery-@gplx.Internal protected-link': -// $linkValue = strip_tags(this.replaceLinkHoldersText($match)); -// $chars = self::EXT_LINK_URL_CLASS; -// $addr = self::EXT_LINK_ADDR; +// $linkValue = strip_tags(this.replaceLinkHoldersText(match)); +// $chars = XomwParser.EXT_LINK_URL_CLASS; +// $addr = XomwParser.EXT_LINK_ADDR; // $prots = this.mUrlProtocols; // // check to see if link matches an absolute url, if not then it must be a wiki link. // if (preg_match('/^-{R|(.*)}-$/', $linkValue)) { @@ -4307,8 +4312,8 @@ public class XomwParser implements XomwParserIface { // break; // default: // // Must be a handler specific parameter. -// if ($handler->validateParam($paramName, $match)) { -// $handlerOptions[$paramName] = $match; +// if ($handler->validateParam($paramName, match)) { +// $handlerOptions[$paramName] = match; // } else { // // Guess not, consider it as caption. // wfDebug("$parameterMatch failed parameter validation\n"); @@ -4343,7 +4348,7 @@ public class XomwParser implements XomwParserIface { // $handlerClass = ''; // } // if (!isset(this.mImageParams[$handlerClass])) { -// # Initialise static lists +// // Initialise static lists // static $internalParamNames = [ // 'horizAlign' => [ 'left', 'right', 'center', 'none' ], // 'vertAlign' => [ 'baseline', 'sub', 'super', 'top', 'text-top', 'middle', @@ -4356,18 +4361,18 @@ public class XomwParser implements XomwParserIface { // $internalParamMap = []; // foreach ($internalParamNames as $type => $names) { // foreach ($names as $name) { -// $magicName = str_replace('-', '_', "img_$name"); -// $internalParamMap[$magicName] = [ $type, $name ]; +// magicName = str_replace('-', '_', "img_$name"); +// $internalParamMap[magicName] = [ $type, $name ]; // } // } // } // -// # Add handler params +// // Add handler params // $paramMap = $internalParamMap; // if ($handler) { // $handlerParamMap = $handler->getParamMap(); -// foreach ($handlerParamMap as $magic => $paramName) { -// $paramMap[$magic] = [ 'handler', $paramName ]; +// foreach ($handlerParamMap as magic => $paramName) { +// $paramMap[magic] = [ 'handler', $paramName ]; // } // } // this.mImageParams[$handlerClass] = $paramMap; @@ -4385,67 +4390,67 @@ public class XomwParser implements XomwParserIface { // * @return String HTML // */ // public function makeImage($title, $options, $holders = false) { -// # Check if the options text is of the form "options|alt text" -// # Options are: -// # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang -// # * left no resizing, just left align. label is used for alt= only -// # * right same, but right aligned -// # * none same, but not aligned -// # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox -// # * center center the image -// # * frame Keep original image size, no magnify-button. -// # * framed Same as "frame" -// # * frameless like 'thumb' but without a frame. Keeps user preferences for width -// # * upright reduce width for upright images, rounded to full __0 px -// # * border draw a 1px border around the image -// # * alt Text for HTML alt attribute (defaults to empty) -// # * class Set a class for img node -// # * link Set the target of the image link. Can be external, interwiki, or local -// # vertical-align values (no % or length right now): -// # * baseline -// # * sub -// # * super -// # * top -// # * text-top -// # * middle -// # * bottom -// # * text-bottom +// // Check if the options text is of the form "options|alt text" +// // Options are: +// // * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang +// // * left no resizing, just left align. label is used for alt= only +// // * right same, but right aligned +// // * none same, but not aligned +// // * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox +// // * center center the image +// // * frame Keep original image size, no magnify-button. +// // * framed Same as "frame" +// // * frameless like 'thumb' but without a frame. Keeps user preferences for width +// // * upright reduce width for upright images, rounded to full __0 px +// // * border draw a 1px border around the image +// // * alt Text for HTML alt attribute (defaults to empty) +// // * class Set a class for img node +// // * link Set the target of the image link. Can be external, interwiki, or local +// // vertical-align values (no % or length right now): +// // * baseline +// // * sub +// // * super +// // * top +// // * text-top +// // * middle +// // * bottom +// // * text-bottom // -// # Protect LanguageConverter markup when splitting into parts +// // Protect LanguageConverter markup when splitting into parts // $parts = StringUtils::delimiterExplode( // '-{', '}-', '|', $options, true /* allow nesting */ // ); // -// # Give extensions a chance to select the file revision for us +// // Give extensions a chance to select the file revision for us // $options = []; // $descQuery = false; // Hooks::run('BeforeParserFetchFileAndTitle', // [ $this, $title, &$options, &$descQuery ]); -// # Fetch and register the file (file title may be different via hooks) +// // Fetch and register the file (file title may be different via hooks) // list($file, $title) = this.fetchFileAndTitle($title, $options); // -// # Get parameter map +// // Get parameter map // $handler = $file ? $file->getHandler() : false; // -// list($paramMap, $mwArray) = this.getImageParams($handler); +// list($paramMap, mwArray) = this.getImageParams($handler); // // if (!$file) { // this.addTrackingCategory('broken-file-category'); // } // -// # Process the input parameters +// // Process the input parameters // $caption = ''; // $params = [ 'frame' => [], 'handler' => [], // 'horizAlign' => [], 'vertAlign' => [] ]; // $seenformat = false; // foreach ($parts as $part) { // $part = trim($part); -// list($magicName, $value) = $mwArray->matchVariableStartToEnd($part); +// list(magicName, $value) = mwArray->matchVariableStartToEnd($part); // $validated = false; -// if (isset($paramMap[$magicName])) { -// list($type, $paramName) = $paramMap[$magicName]; +// if (isset($paramMap[magicName])) { +// list($type, $paramName) = $paramMap[magicName]; // -// # Special case; width and height come in one variable together +// // Special case; width and height come in one variable together // if ($type === 'handler' && $paramName === 'width') { // $parsedWidthParam = this.parseWidthParam($value); // if (isset($parsedWidthParam['width'])) { @@ -4462,33 +4467,33 @@ public class XomwParser implements XomwParserIface { // $validated = true; // } // } -// # else no validation -- T15436 +// // else no validation -- T15436 // } else { // if ($type === 'handler') { -// # Validate handler parameter +// // Validate handler parameter // $validated = $handler->validateParam($paramName, $value); // } else { -// # Validate @gplx.Internal protected parameters +// // Validate @gplx.Internal protected parameters // switch ($paramName) { // case 'manualthumb': // case 'alt': // case 'class': -// # @todo FIXME: Possibly check validity here for -// # manualthumb? downstream behavior seems odd with -// # missing manual thumbs. +// // @todo FIXME: Possibly check validity here for +// // manualthumb? downstream behavior seems odd with +// // missing manual thumbs. // $validated = true; // $value = this.stripAltText($value, $holders); // break; // case 'link': -// $chars = self::EXT_LINK_URL_CLASS; -// $addr = self::EXT_LINK_ADDR; +// $chars = XomwParser.EXT_LINK_URL_CLASS; +// $addr = XomwParser.EXT_LINK_ADDR; // $prots = this.mUrlProtocols; // if ($value === '') { // $paramName = 'no-link'; // $value = true; // $validated = true; // } elseif (preg_match("/^((?i)$prots)/", $value)) { -// if (preg_match("/^((?i)$prots)$addr$chars*$/u", $value, $m)) { +// if (preg_match("/^((?i)$prots)$addr$chars*$/u", $value, m)) { // $paramName = 'link-url'; // this.mOutput->addExternalLink($value); // if (this.mOptions->getExternalLinkTarget()) { @@ -4514,7 +4519,7 @@ public class XomwParser implements XomwParserIface { // $seenformat = true; // break; // default: -// # Most other things appear to be empty or numeric... +// // Most other things appear to be empty or numeric... // $validated = ($value === false || is_numeric(trim($value))); // } // } @@ -4529,7 +4534,7 @@ public class XomwParser implements XomwParserIface { // } // } // -// # Process alignment parameters +// // Process alignment parameters // if ($params['horizAlign']) { // $params['frame']['align'] = key($params['horizAlign']); // } @@ -4539,57 +4544,57 @@ public class XomwParser implements XomwParserIface { // // $params['frame']['caption'] = $caption; // -// # Will the image be presented in a frame, with the caption below? +// // Will the image be presented in a frame, with the caption below? // $imageIsFramed = isset($params['frame']['frame']) // || isset($params['frame']['framed']) // || isset($params['frame']['thumbnail']) // || isset($params['frame']['manualthumb']); // -// # In the old days, [[Image:Foo|text...]] would set alt text. Later it -// # came to also set the caption, ordinary text after the image -- which -// # makes no sense, because that just repeats the text multiple times in -// # screen readers. It *also* came to set the title attribute. -// # Now that we have an alt attribute, we should not set the alt text to -// # equal the caption: that's worse than useless, it just repeats the -// # text. This is the framed/thumbnail case. If there's no caption, we -// # use the unnamed parameter for alt text as well, just for the time be- -// # ing, if the unnamed param is set and the alt param is not. -// # For the future, we need to figure out if we want to tweak this more, -// # e.g., introducing a title= parameter for the title; ignoring the un- -// # named parameter entirely for images without a caption; adding an ex- -// # plicit caption= parameter and preserving the old magic unnamed para- -// # meter for BC; ... -// if ($imageIsFramed) { # Framed image +// // In the old days, [[Image:Foo|text...]] would set alt text. Later it +// // came to also set the caption, ordinary text after the image -- which +// // makes no sense, because that just repeats the text multiple times in +// // screen readers. It *also* came to set the title attribute. +// // Now that we have an alt attribute, we should not set the alt text to +// // equal the caption: that's worse than useless, it just repeats the +// // text. This is the framed/thumbnail case. If there's no caption, we +// // use the unnamed parameter for alt text as well, just for the time be- +// // ing, if the unnamed param is set and the alt param is not. +// // For the future, we need to figure out if we want to tweak this more, +// // e.g., introducing a title= parameter for the title; ignoring the un- +// // named parameter entirely for images without a caption; adding an ex- +// // plicit caption= parameter and preserving the old magic unnamed para- +// // meter for BC; ... +// if ($imageIsFramed) { // Framed image // if ($caption === '' && !isset($params['frame']['alt'])) { -// # No caption or alt text, add the filename as the alt text so -// # that screen readers at least get some description of the image +// // No caption or alt text, add the filename as the alt text so +// // that screen readers at least get some description of the image // $params['frame']['alt'] = $title->getText(); // } -// # Do not set $params['frame']['title'] because tooltips don't make sense -// # for framed images -// } else { # Inline image +// // Do not set $params['frame']['title'] because tooltips don't make sense +// // for framed images +// } else { // Inline image // if (!isset($params['frame']['alt'])) { -// # No alt text, use the "caption" for the alt text +// // No alt text, use the "caption" for the alt text // if ($caption !== '') { // $params['frame']['alt'] = this.stripAltText($caption, $holders); // } else { -// # No caption, fall back to using the filename for the -// # alt text +// // No caption, fall back to using the filename for the +// // alt text // $params['frame']['alt'] = $title->getText(); // } // } -// # Use the "caption" for the tooltip text +// // Use the "caption" for the tooltip text // $params['frame']['title'] = this.stripAltText($caption, $holders); // } // // Hooks::run('ParserMakeImageParams', [ $title, $file, &$params, $this ]); // -// # Linker does the rest +// // Linker does the rest // $time = isset($options['time']) ? $options['time'] : false; // $ret = Linker::makeImageLink($this, $title, $file, $params['frame'], $params['handler'], // $time, $descQuery, this.mOptions->getThumbSize()); // -// # Give the handler a chance to modify the parser Object +// // Give the handler a chance to modify the parser Object // if ($handler) { // $handler->parserTransformHook($this, $file); // } @@ -4674,12 +4679,12 @@ public class XomwParser implements XomwParserIface { // * @return String // */ // public function replaceTransparentTags($text) { -// $matches = []; +// matches = []; // $elements = array_keys(this.mTransparentTagHooks); -// $text = self::extractTagsAndParams($elements, $text, $matches); +// $text = XomwParser.extractTagsAndParams($elements, $text, matches); // $replacements = []; // -// foreach ($matches as $marker => $data) { +// foreach (matches as marker => $data) { // list($element, $content, $params, $tag) = $data; // $tagName = strtolower($element); // if (isset(this.mTransparentTagHooks[$tagName])) { @@ -4690,7 +4695,7 @@ public class XomwParser implements XomwParserIface { // } else { // $output = $tag; // } -// $replacements[$marker] = $output; +// $replacements[marker] = $output; // } // return strtr($text, $replacements); // } @@ -4713,46 +4718,46 @@ public class XomwParser implements XomwParserIface { // * // * The section number 0 pulls the text before the first heading; other numbers will // * pull the given section along with its lower-level subsections. If the section is -// * not found, $mode=get will return $newtext, and $mode=replace will return $text. +// * not found, mode=get will return $newtext, and mode=replace will return $text. // * // * Section 0 is always considered to exist, even if it only contains the empty // * String. If $text is the empty String and section 0 is replaced, $newText is // * returned. // * -// * @param String $mode One of "get" or "replace" +// * @param String mode One of "get" or "replace" // * @param String $newText Replacement text for section data. // * @return String For "get", the extracted section text. // * for "replace", the whole page with the section replaced. // */ -// private function extractSections($text, $sectionId, $mode, $newText = '') { -// global $wgTitle; # not generally used but removes an ugly failure mode +// private function extractSections($text, $sectionId, mode, $newText = '') { +// global $wgTitle; // not generally used but removes an ugly failure mode // -// $magicScopeVariable = this.synchronized(); -// this.startParse($wgTitle, new ParserOptions, self::OT_PLAIN, true); +// magicScopeVariable = this.synchronized(); +// this.startParse($wgTitle, new ParserOptions, XomwParser.OT_PLAIN, true); // $outText = ''; // $frame = this.getPreprocessor()->newFrame(); // -// # Process section extraction flags +// // Process section extraction flags // $flags = 0; // $sectionParts = explode('-', $sectionId); // $sectionIndex = array_pop($sectionParts); // foreach ($sectionParts as $part) { // if ($part === 'T') { -// $flags |= self::PTD_FOR_INCLUSION; +// $flags |= XomwParser.PTD_FOR_INCLUSION; // } // } // -// # Check for empty input +// // Check for empty input // if (strval($text) === '') { -// # Only sections 0 and T-0 exist in an empty document +// // Only sections 0 and T-0 exist in an empty document // if ($sectionIndex == 0) { -// if ($mode === 'get') { +// if (mode === 'get') { // return ''; // } else { // return $newText; // } // } else { -// if ($mode === 'get') { +// if (mode === 'get') { // return $newText; // } else { // return $text; @@ -4760,16 +4765,16 @@ public class XomwParser implements XomwParserIface { // } // } // -// # Preprocess the text +// // Preprocess the text // $root = this.preprocessToDom($text, $flags); // -// # nodes indicate section breaks -// # They can only occur at the top level, so we can find them by iterating the root's children +// // nodes indicate section breaks +// // They can only occur at the top level, so we can find them by iterating the root's children // $node = $root->getFirstChild(); // -// # Find the target section +// // Find the target section // if ($sectionIndex == 0) { -// # Section zero doesn't nest, level=big +// // Section zero doesn't nest, level=big // $targetLevel = 1000; // } else { // while ($node) { @@ -4780,7 +4785,7 @@ public class XomwParser implements XomwParserIface { // break; // } // } -// if ($mode === 'replace') { +// if (mode === 'replace') { // $outText .= $frame->expand($node, PPFrame::RECOVER_ORIG); // } // $node = $node->getNextSibling(); @@ -4788,15 +4793,15 @@ public class XomwParser implements XomwParserIface { // } // // if (!$node) { -// # Not found -// if ($mode === 'get') { +// // Not found +// if (mode === 'get') { // return $newText; // } else { // return $text; // } // } // -// # Find the end of the section, including nested sections +// // Find the end of the section, including nested sections // do { // if ($node->getName() === 'h') { // $bits = $node->splitHeading(); @@ -4805,18 +4810,18 @@ public class XomwParser implements XomwParserIface { // break; // } // } -// if ($mode === 'get') { +// if (mode === 'get') { // $outText .= $frame->expand($node, PPFrame::RECOVER_ORIG); // } // $node = $node->getNextSibling(); // } while ($node); // -// # Write out the remainder (in replace mode only) -// if ($mode === 'replace') { -// # Output the replacement text -// # Add two newlines on -- trailing whitespace in $newText is conventionally -// # stripped by the editor, so we need both newlines to restore the paragraph gap -// # Only add trailing whitespace if there is newText +// // Write out the remainder (in replace mode only) +// if (mode === 'replace') { +// // Output the replacement text +// // Add two newlines on -- trailing whitespace in $newText is conventionally +// // stripped by the editor, so we need both newlines to restore the paragraph gap +// // Only add trailing whitespace if there is newText // if ($newText != "") { // $outText .= $newText . "\n\n"; // } @@ -4828,7 +4833,7 @@ public class XomwParser implements XomwParserIface { // } // // if (is_string($outText)) { -// # Re-insert stripped tags +// // Re-insert stripped tags // $outText = rtrim(this.mStripState->unstripBoth($outText)); // } // @@ -4896,9 +4901,9 @@ public class XomwParser implements XomwParserIface { // this.mOptions->getCurrentRevisionCallback(), this.getTitle(), $this // ); // -// # If the parse is for a new revision, then the callback should have -// # already been set to force the Object and should match mRevisionId. -// # If not, try to fetch by mRevisionId for sanity. +// // If the parse is for a new revision, then the callback should have +// // already been set to force the Object and should match mRevisionId. +// // If not, try to fetch by mRevisionId for sanity. // if ($rev && $rev->getId() != this.mRevisionId) { // $rev = Revision::newFromId(this.mRevisionId); // } @@ -4920,11 +4925,11 @@ public class XomwParser implements XomwParserIface { // $revObject = this.getRevisionObject(); // $timestamp = $revObject ? $revObject->getTimestamp() : wfTimestampNow(); // -// # The cryptic '' timezone parameter tells to use the site-default -// # timezone offset instead of the user settings. -// # Since this value will be saved into the parser cache, served -// # to other users, and potentially even used inside links and such, -// # it needs to be consistent for all visitors. +// // The cryptic '' timezone parameter tells to use the site-default +// // timezone offset instead of the user settings. +// // Since this value will be saved into the parser cache, served +// // to other users, and potentially even used inside links and such, +// // it needs to be consistent for all visitors. // this.mRevisionTimestamp = $wgContLang->userAdjust($timestamp, ''); // // } @@ -4940,8 +4945,8 @@ public class XomwParser implements XomwParserIface { // if (is_null(this.mRevisionUser)) { // $revObject = this.getRevisionObject(); // -// # if this template is subst: the revision id will be blank, -// # so just use the current user's name +// // if this template is subst: the revision id will be blank, +// // so just use the current user's name // if ($revObject) { // this.mRevisionUser = $revObject->getUserText(); // } elseif (this.ot['wiki'] || this.mOptions->getIsPreview()) { @@ -4960,9 +4965,9 @@ public class XomwParser implements XomwParserIface { // if (is_null(this.mRevisionSize)) { // $revObject = this.getRevisionObject(); // -// # if this variable is subst: the revision id will be blank, -// # so just use the parser input size, because the own substituation -// # will change the size. +// // if this variable is subst: the revision id will be blank, +// // so just use the parser input size, because the own substituation +// // will change the size. // if ($revObject) { // this.mRevisionSize = $revObject->getSize(); // } else { @@ -4973,7 +4978,7 @@ public class XomwParser implements XomwParserIface { // } // // /** -// * Mutator for $mDefaultSort +// * Mutator for mDefaultSort // * // * @param String $sort New value // */ @@ -4983,7 +4988,7 @@ public class XomwParser implements XomwParserIface { // } // // /** -// * Accessor for $mDefaultSort +// * Accessor for mDefaultSort // * Will use the empty String if none is set. // * // * This value is treated as a prefix, so the @@ -5001,7 +5006,7 @@ public class XomwParser implements XomwParserIface { // } // // /** -// * Accessor for $mDefaultSort +// * Accessor for mDefaultSort // * Unlike getDefaultSort(), will return false if none is set // * // * @return String|boolean @@ -5020,7 +5025,7 @@ public class XomwParser implements XomwParserIface { // * @return String // */ // public function guessSectionNameFromWikiText($text) { -// # Strip out wikitext links(they break the anchor) +// // Strip out wikitext links(they break the anchor) // $text = this.stripSectionName($text); // $text = Sanitizer::normalizeSectionNameWhitespace($text); // return '#' . Sanitizer::escapeId($text, 'noninitial'); @@ -5035,7 +5040,7 @@ public class XomwParser implements XomwParserIface { // * @return String An anchor // */ // public function guessLegacySectionNameFromWikiText($text) { -// # Strip out wikitext links(they break the anchor) +// // Strip out wikitext links(they break the anchor) // $text = this.stripSectionName($text); // $text = Sanitizer::normalizeSectionNameWhitespace($text); // return '#' . Sanitizer::escapeId($text, [ 'noninitial', 'legacy' ]); @@ -5056,20 +5061,20 @@ public class XomwParser implements XomwParserIface { // * @return String Filtered text String // */ // public function stripSectionName($text) { -// # Strip @gplx.Internal protected link markup +// // Strip @gplx.Internal protected link markup // $text = preg_replace('/\[\[:?([^[|]+)\|([^[]+)\]\]/', '$2', $text); // $text = preg_replace('/\[\[:?([^[]+)\|?\]\]/', '$1', $text); // -// # Strip external link markup -// # @todo FIXME: Not tolerant to blank link text -// # I.E. [https://www.mediawiki.org] will render as [1] or something depending -// # on how many empty links there are on the page - need to figure that out. +// // Strip external link markup +// // @todo FIXME: Not tolerant to blank link text +// // I.E. [https://www.mediawiki.org] will render as [1] or something depending +// // on how many empty links there are on the page - need to figure that out. // $text = preg_replace('/\[(?i:' . this.mUrlProtocols . ')([^ ]+?) ([^[]+)\]/', '$2', $text); // -// # Parse wikitext quotes (italics & bold) +// // Parse wikitext quotes (italics & bold) // $text = this.doQuotes($text); // -// # Strip HTML tags +// // Strip HTML tags // $text = StringUtils::delimiterReplace('<', '>', '', $text); // return $text; // } @@ -5085,9 +5090,9 @@ public class XomwParser implements XomwParserIface { // * @return String // */ // public function testSrvus($text, Title $title, ParserOptions $options, -// $outputType = self::OT_HTML +// $outputType = XomwParser.OT_HTML // ) { -// $magicScopeVariable = this.synchronized(); +// magicScopeVariable = this.synchronized(); // this.startParse($title, $options, $outputType, true); // // $text = this.replaceVariables($text); @@ -5113,7 +5118,7 @@ public class XomwParser implements XomwParserIface { // * @return String // */ // public function testPreprocess($text, Title $title, ParserOptions $options) { -// return this.testSrvus($text, $title, $options, self::OT_PREPROCESS); +// return this.testSrvus($text, $title, $options, XomwParser.OT_PREPROCESS); // } // // /** @@ -5136,20 +5141,20 @@ public class XomwParser implements XomwParserIface { // $i = 0; // $out = ''; // while ($i < strlen($s)) { -// $markerStart = strpos($s, self::MARKER_PREFIX, $i); -// if ($markerStart === false) { +// markerStart = strpos($s, XomwParser.MARKER_PREFIX, $i); +// if (markerStart === false) { // $out .= call_user_func($callback, substr($s, $i)); // break; // } else { -// $out .= call_user_func($callback, substr($s, $i, $markerStart - $i)); -// $markerEnd = strpos($s, self::MARKER_SUFFIX, $markerStart); -// if ($markerEnd === false) { -// $out .= substr($s, $markerStart); +// $out .= call_user_func($callback, substr($s, $i, markerStart - $i)); +// markerEnd = strpos($s, XomwParser.MARKER_SUFFIX, markerStart); +// if (markerEnd === false) { +// $out .= substr($s, markerStart); // break; // } else { -// $markerEnd += strlen(self::MARKER_SUFFIX); -// $out .= substr($s, $markerStart, $markerEnd - $markerStart); -// $i = $markerEnd; +// markerEnd += strlen(XomwParser.MARKER_SUFFIX); +// $out .= substr($s, markerStart, markerEnd - markerStart); +// $i = markerEnd; // } // } // } @@ -5185,7 +5190,7 @@ public class XomwParser implements XomwParserIface { // public function serializeHalfParsedText($text) { // $data = [ // 'text' => $text, -// 'version' => self::HALF_PARSED_VERSION, +// 'version' => XomwParser.HALF_PARSED_VERSION, // 'stripState' => this.mStripState->getSubState($text), // 'linkHolders' => this.mLinkHolders->getSubArray($text) // ]; @@ -5208,18 +5213,18 @@ public class XomwParser implements XomwParserIface { // * @return String // */ // public function unserializeHalfParsedText($data) { -// if (!isset($data['version']) || $data['version'] != self::HALF_PARSED_VERSION) { +// if (!isset($data['version']) || $data['version'] != XomwParser.HALF_PARSED_VERSION) { // throw new MWException(__METHOD__ . ': invalid version'); // } // -// # First, extract the strip state. +// // First, extract the strip state. // $texts = [ $data['text'] ]; // $texts = this.mStripState->merge($data['stripState'], $texts); // -// # Now renumber links +// // Now renumber links // $texts = this.mLinkHolders->mergeForeign($data['linkHolders'], $texts); // -// # Should be good to go. +// // Should be good to go. // return $texts[0]; // } // @@ -5233,7 +5238,7 @@ public class XomwParser implements XomwParserIface { // * @return boolean // */ // public function isValidHalfParsedText($data) { -// return isset($data['version']) && $data['version'] == self::HALF_PARSED_VERSION; +// return isset($data['version']) && $data['version'] == XomwParser.HALF_PARSED_VERSION; // } // // /** @@ -5249,12 +5254,12 @@ public class XomwParser implements XomwParserIface { // if ($value === '') { // return $parsedWidthParam; // } -// $m = []; -// # (T15500) In both cases (width/height and width only), -// # permit trailing "px" for backward compatibility. -// if (preg_match('/^([0-9]*)x([0-9]*)\s*(?:px)?\s*$/', $value, $m)) { -// $width = intval($m[1]); -// $height = intval($m[2]); +// m = []; +// // (T15500) In both cases (width/height and width only), +// // permit trailing "px" for backward compatibility. +// if (preg_match('/^([0-9]*)x([0-9]*)\s*(?:px)?\s*$/', $value, m)) { +// $width = intval(m[1]); +// $height = intval(m[2]); // $parsedWidthParam['width'] = $width; // $parsedWidthParam['height'] = $height; // } elseif (preg_match('/^[0-9]*\s*(?:px)?\s*$/', $value)) { @@ -5298,10 +5303,10 @@ public class XomwParser implements XomwParserIface { // * @since 1.24 // */ // public static function stripOuterParagraph($html) { -// $m = []; -// if (preg_match('/^

(.*)\n?<\/p>\n?$/sU', $html, $m)) { -// if (strpos($m[1], '

') === false) { -// $html = $m[1]; +// m = []; +// if (preg_match('/^

(.*)\n?<\/p>\n?$/sU', $html, m)) { +// if (strpos(m[1], '

') === false) { +// $html = m[1]; // } // } // @@ -5311,7 +5316,7 @@ public class XomwParser implements XomwParserIface { // /** // * Return this parser if it is not doing anything, otherwise // * get a fresh parser. You can use this method by doing -// * $myParser = $wgParser->getFreshParser(), or more simply +// * myParser = $wgParser->getFreshParser(), or more simply // * $wgParser->getFreshParser()->parse(...); // * if you're unsure if $wgParser is safe to use. // * diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java index da3148488..e8b8bc22b 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java @@ -99,10 +99,10 @@ public class XomwParserOptions { // */ // private $mExpensiveParserFunctionLimit; // -// /** -// * Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS -// */ -// private $mRemoveComments = true; + /** + * Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS + */ + private boolean mRemoveComments = true; // // /** // * @var callable Callback for current revision fetching; first argument to call_user_func(). @@ -297,9 +297,9 @@ public class XomwParserOptions { // return this.mExpensiveParserFunctionLimit; // } // -// public function getRemoveComments() { -// return this.mRemoveComments; -// } + public boolean getRemoveComments() { + return this.mRemoveComments; + } // // /* @since 1.24 */ // public function getCurrentRevisionCallback() { diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor.java index 2d83b4ca6..f9994a7fd 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor.java @@ -20,6 +20,7 @@ import gplx.xowa.mediawiki.includes.parsers.preprocessors.*; * @ingroup Parser */ public abstract class XomwPreprocessor { + public abstract XomwParser Parser(); // XOWA: not in MW, but both Preprocessor_DOM and Preprocessor_Hash have the member variable // private static final int CACHE_VERSION = 1; diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_DOM.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_DOM.java index dcdf84299..b14bca6b5 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_DOM.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_DOM.java @@ -19,6 +19,8 @@ import gplx.xowa.mediawiki.includes.parsers.preprocessors.*; // THREAD.UNSAFE: caching for repeated calls class XomwPreprocessor_DOM extends XomwPreprocessor { private final Bry_bfr tmp_bfr = Bry_bfr_.New(); private Xomw_prepro_accum__dom accum_dom = new Xomw_prepro_accum__dom(""); + public XomwPreprocessor_DOM(XomwParser parser) {this.parser = parser;} + @Override public XomwParser Parser() {return parser;} private final XomwParser parser; @Override protected XomwPPDPart Factory__part() {return new XomwPPDPart_DOM("");} @Override protected XomwPPDStack Factory__stack() {return new XomwPPDStack(Xomw_prepro_accum__dom.Instance);} @@ -152,6 +154,6 @@ class XomwPreprocessor_DOM extends XomwPreprocessor { private final Bry_bfr return root_accum.To_bry_and_clear(); } - @Override public XomwPreprocessor Make_new(XomwParser parser) {return new XomwPreprocessor_DOM();} - public static final XomwPreprocessor Instance = new XomwPreprocessor_DOM(); + @Override public XomwPreprocessor Make_new(XomwParser parser) {return new XomwPreprocessor_DOM(parser);} + public static final XomwPreprocessor Instance = new XomwPreprocessor_DOM(null); } diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_Hash.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_Hash.java index 99f0aa61b..196551a87 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_Hash.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_Hash.java @@ -16,6 +16,8 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt package gplx.xowa.mediawiki.includes.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.preprocessors.*; class XomwPreprocessor_Hash extends XomwPreprocessor { private XophpArray accum; + public XomwPreprocessor_Hash(XomwParser parser) {this.parser = parser;} + @Override public XomwParser Parser() {return parser;} private final XomwParser parser; @Override public XomwPPFrame newFrame() { return null; @@ -192,6 +194,6 @@ class XomwPreprocessor_Hash extends XomwPreprocessor { private XophpArray accum } } - @Override public XomwPreprocessor Make_new(XomwParser parser) {return new XomwPreprocessor_Hash();} - public static final XomwPreprocessor Instance = new XomwPreprocessor_Hash(); + @Override public XomwPreprocessor Make_new(XomwParser parser) {return new XomwPreprocessor_Hash(parser);} + public static final XomwPreprocessor Instance = new XomwPreprocessor_Hash(null); } diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor__tst.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor__tst.java index 07822e981..ce8970627 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor__tst.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor__tst.java @@ -235,12 +235,12 @@ class XomwPreprocessor__fxt { public void Test__parse(String src_str, String expd) { List_adp list = List_adp_.New(); if (hash_enabled) { - XomwPreprocessor_Hash wkr_hash = new XomwPreprocessor_Hash(); + XomwPreprocessor_Hash wkr_hash = new XomwPreprocessor_Hash(null); wkr_hash.Init_by_wiki("pre"); list.Add(wkr_hash); } if (dom_enabled) { - XomwPreprocessor_DOM wkr_dom = new XomwPreprocessor_DOM(); + XomwPreprocessor_DOM wkr_dom = new XomwPreprocessor_DOM(null); wkr_dom.Init_by_wiki("pre"); list.Add(wkr_dom); } diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame.java index d7c39bff3..c7f27c3c1 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame.java @@ -18,6 +18,7 @@ package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; impor /** * @ingroup Parser */ +// XOWA: TODO: change VIRTUAL back to ABSTRACT; WHEN: after adding _DOM classes public abstract class XomwPPFrame { public static final int NO_ARGS = 1; public static final int NO_TEMPLATES = 2; @@ -40,7 +41,7 @@ public abstract class XomwPPFrame { * * @return PPFrame */ - public abstract XomwPPFrame newChild(Object args, XomwTitle title, int indexOffset); + @gplx.Virtual public XomwPPFrame newChild(XophpArray args, XomwTitle title, int indexOffset) {return null;} /** * Expand a document tree node, caching the result on its parent with the given key @@ -49,7 +50,7 @@ public abstract class XomwPPFrame { * @param int $flags * @return String */ - public abstract String cachedExpand(String key, XomwPPNode root, int flags); + @gplx.Virtual public String cachedExpand(String key, XomwPPNode root, int flags) {return null;} /** * Expand a document tree node @@ -57,7 +58,7 @@ public abstract class XomwPPFrame { * @param int $flags * @return String */ - public abstract String expand(XomwPPNode root, int flags); + @gplx.Virtual public String expand(XomwPPNode root, int flags) {return null;} /** * Implode with flags for expand() @@ -66,7 +67,7 @@ public abstract class XomwPPFrame { * @param String|PPNode $args,... * @return String */ - public abstract String implodeWithFlags(String sep, int flags, Object... args); + @gplx.Virtual public String implodeWithFlags(String sep, int flags, Object... args) {return null;} /** * Implode with no flags specified @@ -74,7 +75,7 @@ public abstract class XomwPPFrame { * @param String|PPNode $args,... * @return String */ - public abstract String implode(String sep, Object... args); + @gplx.Virtual public String implode(String sep, Object... args) {return null;} /** * Makes an Object that, when expand()ed, will be the same as one obtained @@ -83,7 +84,7 @@ public abstract class XomwPPFrame { * @param String|PPNode $args,... * @return PPNode */ - public abstract XomwPPNode virtualImplode(String sep, Object... args); + @gplx.Virtual public XomwPPNode virtualImplode(String sep, Object... args) {return null;} /** * Virtual implode with brackets @@ -93,39 +94,39 @@ public abstract class XomwPPFrame { * @param String|PPNode $args,... * @return PPNode */ - public abstract XomwPPNode virtualBracketedImplode(String start, String sep, String end, Object... args); + @gplx.Virtual public XomwPPNode virtualBracketedImplode(String start, String sep, String end, Object... args) {return null;} /** * Returns true if there are no arguments in this frame * * @return boolean */ - public abstract boolean isEmpty(); + @gplx.Virtual public boolean isEmpty() {return false;} /** * Returns all arguments of this frame * @return array */ - public abstract Object[] getArguments(); + @gplx.Virtual public XophpArray getArguments() {return null;} /** * Returns all numbered arguments of this frame * @return array */ - public abstract Object[] getNumberedArguments(); + @gplx.Virtual public XophpArray getNumberedArguments() {return null;} /** * Returns all named arguments of this frame * @return array */ - public abstract Object[] getNamedArguments(); + @gplx.Virtual public XophpArray getNamedArguments() {return null;} /** * Get an argument to this frame by name * @param int|String $name * @return String|boolean */ - public abstract String getArgument(String name); + @gplx.Virtual public String getArgument(String name) {return null;} /** * Returns true if the infinite loop check is OK, false if a loop is detected @@ -133,13 +134,13 @@ public abstract class XomwPPFrame { * @param Title $title * @return boolean */ - public abstract boolean loopCheck(XomwTitle title); + @gplx.Virtual public boolean loopCheck(XomwTitle title) {return false;} /** * Return true if the frame is a template frame * @return boolean */ - public abstract boolean isTemplate(); + @gplx.Virtual public boolean isTemplate() {return false;} /** * Set the "volatile" flag. @@ -152,7 +153,7 @@ public abstract class XomwPPFrame { * * @param boolean $flag */ - public abstract void setVolatile(boolean flag); + @gplx.Virtual public void setVolatile(boolean flag) {} /** * Get the "volatile" flag. @@ -163,7 +164,7 @@ public abstract class XomwPPFrame { * @see self::setVolatile() * @return boolean */ - public abstract boolean isVolatile(); + @gplx.Virtual public boolean isVolatile() {return false;} /** * Get the TTL of the frame's output. @@ -177,7 +178,7 @@ public abstract class XomwPPFrame { * * @return int|null */ - public abstract int getTTL(); + @gplx.Virtual public int getTTL() {return 0;} /** * Set the TTL of the output of this frame and all of its ancestors. @@ -188,12 +189,12 @@ public abstract class XomwPPFrame { * @see self::getTTL() * @param int $ttl */ - public abstract void setTTL(int ttl); + @gplx.Virtual public void setTTL(int ttl) {} /** * Get a title of frame * * @return Title */ - public abstract XomwTitle getTitle(); + @gplx.Virtual public XomwTitle getTitle() {return null;} } diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame_Hash.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame_Hash.java new file mode 100644 index 000000000..74ae0ccc2 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame_Hash.java @@ -0,0 +1,626 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +import gplx.xowa.mediawiki.includes.exception.*; +import gplx.core.bits.*; +/** +* An expansion frame, used as a context to expand the result of preprocessToObj() +* @ingroup Parser +*/ +class XomwPPFrame_Hash extends XomwPPFrame { /** + * @var Parser + */ + public XomwParser parser; + + /** + * @var Preprocessor + */ + public XomwPreprocessor preprocessor; + + /** + * @var Title + */ + public XomwTitle title; + public XophpArray titleCache; + + /** + * Hashtable listing templates which are disallowed for expansion in this frame, + * having been encountered previously in parent frames. + */ + public XophpArray loopCheckHash; + + /** + * Recursion depth of this frame, top = 0 + * Note that this is NOT the same as expansion depth in expand() + */ + public int depth; + + private boolean volatile_bool; + private int ttl; + + /** + * @var array + */ + protected XophpArray childExpansionCache; + + /** + * Construct a new preprocessor frame. + * @param Preprocessor preprocessor The parent preprocessor + */ + public XomwPPFrame_Hash(XomwPreprocessor preprocessor) { + this.preprocessor = preprocessor; + this.parser = preprocessor.Parser(); + this.title = this.parser.mTitle; + this.titleCache = XophpArray.New().Add(XophpObject.is_true(this.title) ? this.title.getPrefixedDBkeyStr() : XophpString_.False); + this.loopCheckHash = XophpArray.New(); + this.depth = 0; + this.childExpansionCache = XophpArray.New(); + } + +// /** +// * Create a new child frame +// * $args is optionally a multi-root PPNode or array containing the template arguments +// * +// * @param array|boolean|PPNode_Hash_Array $args +// * @param Title|boolean $title +// * @param int $indexOffset +// * @throws MWException +// * @return PPTemplateFrame_Hash +// */ +// public function newChild($args = false, $title = false, $indexOffset = 0) { +// $namedArgs = []; +// $numberedArgs = []; +// if ($title === false) { +// $title = this.title; +// } +// if ($args !== false) { +// if ($args instanceof PPNode_Hash_Array) { +// $args = $args.value; +// } else if (!is_array($args)) { +// throw new MWException(__METHOD__ . ': $args must be array or PPNode_Hash_Array'); +// } +// foreach ($args as $arg) { +// $bits = $arg.splitArg(); +// if ($bits['index'] !== '') { +// // Numbered parameter +// $index = $bits['index'] - $indexOffset; +// if (isset($namedArgs[$index]) || isset($numberedArgs[$index])) { +// this.parser.getOutput().addWarning(wfMessage('duplicate-args-warning', +// wfEscapeWikiText(this.title), +// wfEscapeWikiText($title), +// wfEscapeWikiText($index)).text()); +// this.parser.addTrackingCategory('duplicate-args-category'); +// } +// $numberedArgs[$index] = $bits['value']; +// unset($namedArgs[$index]); +// } else { +// // Named parameter +// $name = trim(this.expand($bits['name'], PPFrame.STRIP_COMMENTS)); +// if (isset($namedArgs[$name]) || isset($numberedArgs[$name])) { +// this.parser.getOutput().addWarning(wfMessage('duplicate-args-warning', +// wfEscapeWikiText(this.title), +// wfEscapeWikiText($title), +// wfEscapeWikiText($name)).text()); +// this.parser.addTrackingCategory('duplicate-args-category'); +// } +// $namedArgs[$name] = $bits['value']; +// unset($numberedArgs[$name]); +// } +// } +// } +// return new PPTemplateFrame_Hash(this.preprocessor, $this, $numberedArgs, $namedArgs, $title); +// } + + /** + * @throws MWException + * @param String|int $key + * @param String|PPNode $root + * @param int $flags + * @return String + */ + public String cachedExpand(String key, Object root, int flags) { // DEFAULT:flags=0 + // we don't have a parent, so we don't have a cache + return this.expand(root, flags); + } + + private static int expansionDepth = 0; // MW.GLOBAL:expand + private static int expand_flags_default = 0; + /** + * @throws MWException + * @param String|PPNode $root + * @param int $flags + * @return String + */ + public String expand(Object root, int flags) { + if (XophpString.is_string(root)) { + return (String)root; + } + +// if (++this.parser.mPPNodeCount > this.parser.mOptions.getMaxPPNodeCount()) { +// this.parser.limitationWarn('node-count-exceeded', +// this.parser.mPPNodeCount, +// this.parser.mOptions.getMaxPPNodeCount() +// ); +// return 'Node-count limit exceeded'; +// } +// if (expansionDepth > this.parser.mOptions.getMaxPPExpandDepth()) { +// this.parser.limitationWarn('expansion-depth-exceeded', +// expansionDepth, +// this.parser.mOptions.getMaxPPExpandDepth() +// ); +// return 'Expansion depth limit exceeded'; +// } + ++expansionDepth; + if (expansionDepth > this.parser.mHighestExpansionDepth) { + this.parser.mHighestExpansionDepth = expansionDepth; + } + + XophpArray outStack = XophpArray.New("", ""); + XophpArray iteratorStack = XophpArray.New(XophpObject.False, root); + XophpArray indexStack = XophpArray.New(0, 0); + + while (iteratorStack.Count() > 1) { + int level = outStack.Count() - 1; + Object iteratorNode = iteratorStack.Get_at(level); + String outItm = outStack.Get_at_str(level); + int index = indexStack.Get_at_int(level); + Object contextNode; + if (XophpArray.is_array(iteratorNode)) { + XophpArray iteratorNodeArray = (XophpArray)iteratorNode; + if (index >= iteratorNodeArray.Count()) { + // All done with this iterator + iteratorStack.Set(level, XophpObject.False); + contextNode = XophpObject.False; + } else { + contextNode = iteratorNodeArray.Get_at(index); + index++; + } + } else if (Type_.Eq_by_obj(iteratorNode, XomwPPNode_Hash_Array.class)) { + XomwPPNode_Hash_Array iteratorNodeHashArray = (XomwPPNode_Hash_Array)iteratorNode; + if (index >= iteratorNodeHashArray.getLength()) { + // All done with this iterator + iteratorStack.Set(level, XophpObject.False); + contextNode = XophpObject.False; + } else { + contextNode = iteratorNodeHashArray.item(index); + index++; + } + } else { + // Copy to contextNode and then delete from iterator stack, + // because this is not an iterator but we do have to execute it once + contextNode = iteratorStack.Get_at(level); + iteratorStack.Set(level, XophpObject.False); + } + + Object newIterator = XophpObject.False; + String contextName = XophpString_.False; + XophpArray contextChildren = XophpArray.False; + + if (contextNode == XophpObject.False) { + // nothing to do + } else if (XophpString.is_string(contextNode)) { + outItm += (String)contextNode; + } else if (Type_.Eq_by_obj(contextNode, XomwPPNode_Hash_Array.class)) { + newIterator = contextNode; + } else if (Type_.Eq_by_obj(contextNode, XomwPPNode_Hash_Attr.class)) { + // No output + } else if (Type_.Eq_by_obj(contextNode, XomwPPNode_Hash_Text.class)) { + outItm += ((XomwPPNode_Hash_Text)contextNode).value; + } else if (Type_.Eq_by_obj(contextNode, XomwPPNode_Hash_Tree.class)) { + XomwPPNode_Hash_Tree contextNodeHashTree = (XomwPPNode_Hash_Tree)contextNode; + contextName = contextNodeHashTree.name; + contextChildren = contextNodeHashTree.getRawChildren(); + } else if (XophpArray.is_array(contextNode)) { + XophpArray contextNodeArray = (XophpArray)contextNode; + // Node descriptor array + if (contextNodeArray.Count() != 2) { + throw XomwMWException.New_by_method(XomwPPFrame_Hash.class, "expand", + ": found an array where a node descriptor should be"); + } + contextName = (String)contextNodeArray.Get_at(0); + contextChildren = contextNodeArray.Get_at_ary(1); + } else { + throw XomwMWException.New_by_method(XomwPPFrame_Hash.class, "expand", ": Invalid parameter type"); + } + + // Handle node descriptor array or tree Object + if (contextName == XophpString_.False) { + // Not a node, already handled above + } else if (String_.CharAt(contextName, 0) == '@') { + // Attribute: no output + } else if (String_.Eq(contextName, "template")) { + // Double-brace expansion + XophpArray bits = XomwPPNode_Hash_Tree.splitRawTemplate(contextChildren); + if (Bitmask_.Has_int(flags, XomwPPFrame.NO_TEMPLATES)) { + newIterator = this.virtualBracketedImplode( + "{{", "|", "}}", + bits.Get_by("title"), + bits.Get_by("parts") + ); + } else { + XophpArray ret = this.parser.braceSubstitution(bits, this); + if (ret.is_set(Object_.Cls_val_name)) {// NOTE: using Cls_val_name b/c of transpilation and Object . Object + newIterator = ret.Get_by(Object_.Cls_val_name); + } else { + outItm += ret.Get_by_str("text"); + } + } + } else if (String_.Eq(contextName, "tplarg")) { + // Triple-brace expansion + XophpArray bits = XomwPPNode_Hash_Tree.splitRawTemplate(contextChildren); + if (Bitmask_.Has_int(flags, XomwPPFrame.NO_ARGS)) { + newIterator = this.virtualBracketedImplode( + "{{{", "|", "}}}", + bits.Get_by("title"), + bits.Get_by("parts") + ); + } else { + XophpArray ret = this.parser.argSubstitution(bits, this); + if (ret.is_set(Object_.Cls_val_name)) {// NOTE: using Cls_val_name b/c of transpilation and Object . Object + newIterator = ret.Get_by("Object"); + } else { + outItm += ret.Get_by_str("text"); + } + } + } else if (String_.Eq(contextName, "comment")) { + // HTML-style comment + // Remove it in HTML, pre+remove and STRIP_COMMENTS modes + // Not in RECOVER_COMMENTS mode (msgnw) though. + if ((this.parser.ot.Has("html")) + || (this.parser.ot.Has("pre") && this.parser.mOptions.getRemoveComments()) + || (Bitmask_.Has_int(flags, XomwPPFrame.STRIP_COMMENTS)) + && !(Bitmask_.Has_int(flags, XomwPPFrame.RECOVER_COMMENTS)) + ) { + outItm += ""; // XOWA: no purpose? + } else if (this.parser.ot.Has("wiki") && !(Bitmask_.Has_int(flags, XomwPPFrame.RECOVER_COMMENTS))) { + // Add a strip marker in PST mode so that pstPass2() can + // run some old-fashioned regexes on the result. + // Not in RECOVER_COMMENTS mode (extractSections) though. + outItm += this.parser.insertStripItem(contextChildren.Get_at_str(0)); + } else { + // Recover the literal comment in RECOVER_COMMENTS and pre+no-remove + outItm += contextChildren.Get_at_str(0); + } + } else if (String_.Eq(contextName, "ignore")) { + // Output suppression used by etc. + // OT_WIKI will only respect in substed templates. + // The other output types respect it unless NO_IGNORE is set. + // extractSections() sets NO_IGNORE and so never respects it. +// if ((!XophpUtility.isset(this.parent) && this.parser.ot.Has("wiki")) // this.parent doesn't exist? + if ((this.parser.ot.Has("wiki")) + || (Bitmask_.Has_int(flags, XomwPPFrame.NO_IGNORE)) + ) { + outItm += contextChildren.Get_at_str(0); + } else { + // outItm .= ''; + } + } else if (String_.Eq(contextName, "ext")) { + // Extension tag + XophpArray bits = XomwPPNode_Hash_Tree.splitRawExt(contextChildren) + .Add("attr", null).Add("inner", null).Add("close", null); + if (Bitmask_.Has_int(flags, XomwPPFrame.NO_TAGS)) { + String s = '<' + ((XomwPPNode_Hash_Text)((XomwPPNode)bits.Get_by("name")).getFirstChild()).value; + if (bits.Has("attr")) { + s += ((XomwPPNode_Hash_Text)((XomwPPNode)bits.Get_by("attr")).getFirstChild()).value; + } + if (bits.Has("inner")) { + s += '>' + ((XomwPPNode_Hash_Text)((XomwPPNode)bits.Get_by("inner")).getFirstChild()).value; + if (bits.Has("close")) { + s += ((XomwPPNode_Hash_Text)((XomwPPNode)bits.Get_by("close")).getFirstChild()).value; + } + } else { + s += "/>"; + } + outItm += s; + } else { + outItm += this.parser.extensionSubstitution(bits, this); + } + } else if (String_.Eq(contextName, "h")) { + // Heading + if (this.parser.ot.Has("html")) { + // Expand immediately and insert heading index marker + String s = this.expand(contextChildren, flags); + XophpArray bits = XomwPPNode_Hash_Tree.splitRawHeading(contextChildren); +// String titleText = this.title.getPrefixedDBkey(); +// this.parser.mHeadings[] = [titleText, bits['i']]; +// serial = count(this.parser.mHeadings) - 1; + String marker = XomwParser.MARKER_PREFIX + "-h-serial-" + XomwParser.MARKER_SUFFIX; + s = XophpString.substr(s, 0, bits.Get_by_int("level")) + marker + XophpString.substr(s, bits.Get_by_int("level")); +// this.parser.mStripState.addGeneral(marker, ''); + outItm += s; + } else { + // Expand in virtual stack + newIterator = contextChildren; + } + } else { + // Generic recursive expansion + newIterator = contextChildren; + } + + if (newIterator != XophpObject.False) { + outStack.Add(""); + iteratorStack.Add(newIterator); + indexStack.Add(0); + } else if (iteratorStack.Get_at(level) == XophpObject.False) { + // Return accumulated value to parent + // With tail recursion + while (iteratorStack.Get_at(level) == XophpObject.False && level > 0) { + outStack.Itm_str_concat_end(level - 1, outItm); + outStack.Pop(); + iteratorStack.Pop(); + indexStack.Pop(); + level--; + } + } + } + --expansionDepth; + return outStack.Get_at_str(0); + } + + /** + * @param String $sep + * @param int $flags + * @param String|PPNode $args,... + * @return String + */ +// public function implodeWithFlags($sep, $flags /*, ... */) { +// $args = array_slice(func_get_args(), 2); +// +// $first = true; +// $s = ''; +// foreach ($args as $root) { +// if ($root instanceof PPNode_Hash_Array) { +// $root = $root.value; +// } +// if (!is_array($root)) { +// $root = [$root]; +// } +// foreach ($root as $node) { +// if ($first) { +// $first = false; +// } else { +// $s .= $sep; +// } +// $s .= this.expand($node, $flags); +// } +// } +// return $s; +// } + + /** + * Implode with no flags specified + * This previously called implodeWithFlags but has now been inlined to reduce stack depth + * @param String $sep + * @param String|PPNode $args,... + * @return String + */ + @Override public String implode(String sep, Object... args) { + boolean first = true; + String s = ""; + for (Object rootObj : args) { + XophpArray root = null; + if (Type_.Eq_by_obj(root, XomwPPNode_Hash_Array.class)) { + root = ((XomwPPNode_Hash_Array)rootObj).value; + } + if (!XophpArray.is_array(rootObj)) { + root = XophpArray.New().Add(root); + } + int rootLen = root.Len(); + for (int i = 0; i < rootLen; i++) { + Object node = root.Get_at(i); + if (first) { + first = false; + } else { + s += sep; + } + s += this.expand(node, expand_flags_default); + } + } + return s; + } + + /** + * Makes an Object that, when expand()ed, will be the same as one obtained + * with implode() + * + * @param String $sep + * @param String|PPNode $args,... + * @return PPNode_Hash_Array + */ + @Override public XomwPPNode virtualImplode(String sep, Object... args) { + XophpArray outItm = XophpArray.New(); + boolean first = true; + + for (Object rootObj : args) { + XophpArray root = null; + if (Type_.Eq_by_obj(root, XomwPPNode_Hash_Array.class)) { + root = ((XomwPPNode_Hash_Array)rootObj).value; + } + if (!XophpArray.is_array(rootObj)) { + root = XophpArray.New().Add(root); + } + int rootLen = root.Len(); + for (int i = 0; i < rootLen; i++) { + Object node = root.Get_at(i); + if (first) { + first = false; + } else { + outItm.Add(sep); + } + outItm.Add(node); + } + } + return new XomwPPNode_Hash_Array(outItm); + } + + /** + * Virtual implode with brackets + * + * @param String $start + * @param String $sep + * @param String $end + * @param String|PPNode $args,... + * @return PPNode_Hash_Array + */ + @Override public XomwPPNode virtualBracketedImplode(String start, String sep, String end, Object... args) { + XophpArray outItm = XophpArray.New(start); + boolean first = true; + + for (Object rootObj : args) { + XophpArray root = null; + if (Type_.Eq_by_obj(rootObj, XomwPPNode_Hash_Array.class)) { + root = ((XomwPPNode_Hash_Array)rootObj).value; + } + if (!XophpArray.is_array(rootObj)) { + root = XophpArray.New((String)rootObj); + } + int root_len = root.Len(); + for (int i = 0; i < root_len; i++) { + String node = root.Get_at_str(i); + if (first) { + first = false; + } else { + outItm.Add(sep); + } + outItm.Add(node); + } + } + outItm.Add(end); + return new XomwPPNode_Hash_Array(outItm); + } + +// public function __toString() { +// return 'frame{}'; +// } +// + /** + * @param boolean $level + * @return array|boolean|String + */ + public String getPDBK(boolean level) { // DEFAULT:false + if (level == false) { + return this.title.getPrefixedDBkeyStr(); + } else { + // return isset( $this->titleCache[$level] ) ? $this->titleCache[$level] : false; + return this.titleCache.Count() > 0 ? ((String)this.titleCache.Get_at(0)) : XophpString_.False; + } + } + + /** + * @return array + */ + @Override public XophpArray getArguments() { + return XophpArray.False; + } + + /** + * @return array + */ + @Override public XophpArray getNumberedArguments() { + return XophpArray.False; + } + + /** + * @return array + */ + @Override public XophpArray getNamedArguments() { + return XophpArray.False; + } + + /** + * Returns true if there are no arguments in this frame + * + * @return boolean + */ + @Override public boolean isEmpty() { + return true; + } + + /** + * @param int|String $name + * @return boolean Always false in this implementation. + */ + @Override public String getArgument(String name) { + return XophpString_.False; + } + + /** + * Returns true if the infinite loop check is OK, false if a loop is detected + * + * @param Title $title + * + * @return boolean + */ + @Override public boolean loopCheck(XomwTitle title) { + return !this.loopCheckHash.is_set(title.getPrefixedDBkeyStr()); + } + + /** + * Return true if the frame is a template frame + * + * @return boolean + */ + @Override public boolean isTemplate() { + return false; + } + + /** + * Get a title of frame + * + * @return Title + */ + @Override public XomwTitle getTitle() { + return this.title; + } + + /** + * Set the volatile_bool flag + * + * @param boolean $flag + */ + @Override public void setVolatile(boolean flag) { // DEFAULT: flag = true + this.volatile_bool = flag; + } + + /** + * Get the volatile_bool flag + * + * @return boolean + */ + @Override public boolean isVolatile() { + return this.volatile_bool; + } + + /** + * Set the TTL + * + * @param int ttl + */ + @Override public void setTTL(int val) { + if (this.ttl == Int_.Null || val < this.ttl) { + this.ttl = val; + } + } + + /** + * Get the TTL + * + * @return int|null + */ + @Override public int getTTL() { + return this.ttl; + } +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Array.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Array.java index b61605822..4528a5094 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Array.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Array.java @@ -18,24 +18,26 @@ package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; impor /** * @ingroup Parser */ -public class XomwPPNode_Hash_Array extends XomwPPNode { // public $value; -// -// public function __construct( $value ) { -// $this->value = $value; -// } +public class XomwPPNode_Hash_Array extends XomwPPNode { public XophpArray value; + + public XomwPPNode_Hash_Array(XophpArray value) { + this.value = value; + } @Override public String toString() { // return var_export( $this, true ); return null; } -// -// public function getLength() { -// return count( $this->value ); -// } -// -// public function item( $i ) { -// return $this->value[$i]; -// } + + public int getLength() { + return -1; +// return count( this.value ); + } + + public Object item(int i) { + return null; +// return this.value[$i]; + } @Override public String getName() { return "#nodelist"; diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Tree.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Tree.java index 486ead9f7..664fe162e 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Tree.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode_Hash_Tree.java @@ -50,11 +50,11 @@ public class XomwPPNode_Hash_Tree extends XomwPPNode { public final String na public static final int CHILDREN = 1; /** - * Construct an Object using the data from $store[$index]. The rest of the + * Construct an Object using the data from store[index]. The rest of the * store array can be accessed via getNextSibling(). * - * @param array $store - * @param integer $index + * @param array store + * @param integer index */ public XomwPPNode_Hash_Tree(XophpArray store, int index) { this.store = store; @@ -75,8 +75,8 @@ public class XomwPPNode_Hash_Tree extends XomwPPNode { public final String na * Construct an appropriate PPNode_Hash_* Object with a class that depends * on what is at the relevant store index. * - * @param array $store - * @param integer $index + * @param array store + * @param integer index * @return PPNode_Hash_Tree|PPNode_Hash_Attr|PPNode_Hash_Text */ public static XomwPPNode factory(XophpArray store, int index) { @@ -130,16 +130,17 @@ public class XomwPPNode_Hash_Tree extends XomwPPNode { public final String na } } -// /** -// * @return PPNode_Hash_Array -// */ -// public function getChildren() { -// $children = []; -// foreach (this.rawChildren as $i => $child) { -// $children[] = self::factory(this.rawChildren, $i); + /** + * @return PPNode_Hash_Array + */ + public XomwPPNode_Hash_Array getChildren() { +// children = []; +// foreach (this.rawChildren as i => child) { +// children[] = self::factory(this.rawChildren, i); // } -// return new PPNode_Hash_Array($children); -// } +// return new PPNode_Hash_Array(children); + return null; + } /** * Get the first child, or false if there is none. Note that this will @@ -171,27 +172,28 @@ public class XomwPPNode_Hash_Tree extends XomwPPNode { public final String na // /** // * Get an array of the children with a given node name // * -// * @param String $name +// * @param String name // * @return PPNode_Hash_Array // */ -// public function getChildrenOfType($name) { -// $children = []; -// foreach (this.rawChildren as $i => $child) { -// if (is_array($child) && $child[self::NAME] === $name) { -// $children[] = self::factory(this.rawChildren, $i); +// public function getChildrenOfType(name) { +// children = []; +// foreach (this.rawChildren as i => child) { +// if (is_array(child) && child[self::NAME] === name) { +// children[] = self::factory(this.rawChildren, i); // } // } -// return new PPNode_Hash_Array($children); +// return new PPNode_Hash_Array(children); // } -// -// /** -// * Get the raw child array. For @gplx.Internal protected use. -// * @return array -// */ -// public function getRawChildren() { + + /** + * Get the raw child array. For @gplx.Internal protected use. + * @return array + */ + public XophpArray getRawChildren() { // return this.rawChildren; -// } -// + return null; + } + // /** // * @return boolean // */ @@ -200,10 +202,10 @@ public class XomwPPNode_Hash_Tree extends XomwPPNode { public final String na // } // // /** -// * @param int $i +// * @param int i // * @return boolean // */ -// public function item($i) { +// public function item(i) { // return false; // } @@ -230,31 +232,31 @@ public class XomwPPNode_Hash_Tree extends XomwPPNode { public final String na // /** // * Like splitArg() but for a raw child array. For @gplx.Internal protected use only. // */ -// public static function splitRawArg(array $children) { -// $bits = []; -// foreach ($children as $i => $child) { -// if (!is_array($child)) { +// public static function splitRawArg(array children) { +// bits = []; +// foreach (children as i => child) { +// if (!is_array(child)) { // continue; // } -// if ($child[self::NAME] === 'name') { -// $bits['name'] = new self($children, $i); -// if (isset($child[self::CHILDREN][0][self::NAME]) -// && $child[self::CHILDREN][0][self::NAME] === '@index' +// if (child[self::NAME] === 'name') { +// bits['name'] = new self(children, i); +// if (isset(child[self::CHILDREN][0][self::NAME]) +// && child[self::CHILDREN][0][self::NAME] === '@index' // ) { -// $bits['index'] = $child[self::CHILDREN][0][self::CHILDREN][0]; +// bits['index'] = child[self::CHILDREN][0][self::CHILDREN][0]; // } -// } elseif ($child[self::NAME] === 'value') { -// $bits['value'] = new self($children, $i); +// } elseif (child[self::NAME] === 'value') { +// bits['value'] = new self(children, i); // } // } // -// if (!isset($bits['name'])) { +// if (!isset(bits['name'])) { // throw new MWException('Invalid brace node passed to ' . __METHOD__); // } -// if (!isset($bits['index'])) { -// $bits['index'] = ""; +// if (!isset(bits['index'])) { +// bits['index'] = ""; // } -// return $bits; +// return bits; // } // // /** @@ -267,107 +269,115 @@ public class XomwPPNode_Hash_Tree extends XomwPPNode { public final String na // public function splitExt() { // return self::splitRawExt(this.rawChildren); // } -// -// /** -// * Like splitExt() but for a raw child array. For @gplx.Internal protected use only. -// */ -// public static function splitRawExt(array $children) { -// $bits = []; -// foreach ($children as $i => $child) { -// if (!is_array($child)) { -// continue; -// } -// switch ($child[self::NAME]) { -// case 'name': -// $bits['name'] = new self($children, $i); -// break; -// case 'attr': -// $bits['attr'] = new self($children, $i); -// break; -// case 'inner': -// $bits['inner'] = new self($children, $i); -// break; -// case 'close': -// $bits['close'] = new self($children, $i); -// break; -// } -// } -// if (!isset($bits['name'])) { -// throw new MWException('Invalid ext node passed to ' . __METHOD__); -// } -// return $bits; -// } -// -// /** -// * Split an "" node -// * -// * @throws MWException -// * @return array -// */ -// public function splitHeading() { -// if (this.name !== 'h') { -// throw new MWException('Invalid h node passed to ' . __METHOD__); -// } -// return self::splitRawHeading(this.rawChildren); -// } -// -// /** -// * Like splitHeading() but for a raw child array. For @gplx.Internal protected use only. -// */ -// public static function splitRawHeading(array $children) { -// $bits = []; -// foreach ($children as $i => $child) { -// if (!is_array($child)) { -// continue; -// } -// if ($child[self::NAME] === '@i') { -// $bits['i'] = $child[self::CHILDREN][0]; -// } elseif ($child[self::NAME] === '@level') { -// $bits['level'] = $child[self::CHILDREN][0]; -// } -// } -// if (!isset($bits['i'])) { -// throw new MWException('Invalid h node passed to ' . __METHOD__); -// } -// return $bits; -// } -// -// /** -// * Split a "