Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Core;
5
6/**
7 * Interface for collecting the results of a parse.
8 *
9 * This class is used by Parsoid to record metainformation about a
10 * particular bit of parsed content which is extracted during the
11 * parse.  This includes (for example) table of contents information,
12 * and lists of links/categories/templates/images present in the
13 * content.  Expected cache lifetime of this parsed content is also
14 * recorded here, as it is influenced by certain things which may
15 * be encountered during the parse.
16 *
17 * In core this is implemented by ParserOutput.  Core uses
18 * ParserOutput to record the rendered HTML (and rendered table of
19 * contents HTML), but on the Parsoid side we're going to keep
20 * rendered HTML DOM out of this interface (we use HtmlPageBundle for
21 * this).
22 */
23interface ContentMetadataCollector {
24    /*
25     * Internal implementation notes:
26     * This class was refactored out of ParserOutput in core.
27     *
28     * == Deliberately omitted ==
29     * ::get*()/::has*() and other getters
30     *   This is a builder-only interface.  This also avoids ordering
31     *   issues if/when Parsoid passes this class to sub-parses/extensions.
32     * ::setSpeculativeRevIdUsed()
33     * ::setRevisionTimestampUsed()
34     * ::setRevisionUsedSha1Base36()
35     * ::setSpeculativePageIdUsed()
36     *   T292865: these should be plumbed through direct from ParserOptions
37     *   or use the ::setOutputFlag() or appendOutputStrings() mechanism.
38     * ::setTimestamp()
39     *   This is used by ParserCache and is a little optimization used to
40     *   show the correct 'article was last edited on blablablah' box on
41     *   page views.  Parsoid shouldn't need to worry about this; probably
42     *   part of T292865.
43     * ::addCacheMessage()
44     *   This is marked @internal in core.
45     *   Not clear yet whether Parsoid needs this.
46     * ::getText()/::setText()
47     *   T293512: rendered HTML doesn't belong in ParserOutput
48     * ::addWrapperDivClass()/::clearWrapperDivClass()
49     *   Has to do with ::getText() implementation, see above
50     * ::setTitleText()
51     *   Omited because it contains rendered HTML
52     *   (should become a method which takes a DOM tree instead?)
53     * ::setTOCHTML()
54     *   Omitted because it contains rendered HTML.
55     *   T293513 will remove this method from ParserOutput
56     * ::addHeadItem()
57     *   Not clear this is needed by Parsoid (but maybe some of the stuff
58     *   Parsoid adds to head could be refactored to use this interface).
59     *   Should be DOM not string data!
60     * ::addOutputPageMetadata()
61     *   OutputPage isn't a Parsoid interface, so this shouldn't be needed
62     *   by Parsoid.
63     * ::setDisplayTitle()
64     *   T293514: This desugars to calls to two other methods in
65     *   ContentOutputBuilder; callers can refactor to invoke those directly.
66     * ::unsetPageProperty()
67     *   If parse fragment A is setting a property
68     *   and parse fragment B is unsetting the property, we've introduced
69     *   an ordering dependency. We'd like to avoid that code pattern.
70     * ::resetParseStartTime()/::getTimeSinceStart()
71     *   Not needed by parsoid?
72     * ::finalizeAdaptiveCacheExpiry()
73     *   Same as above, can probably be invoked by caller of parsoid,
74     *   doesn't need to be in Parsoid library code.
75     * ::mergeInternalMetaDataFrom()
76     * ::mergeHtmlMetaDataFrom()
77     * ::mergeTrackingMetaDataFrom()
78     *   Rather than explicitly merging ContentMetadataCollectors, we'd
79     *   prefer to pass a single ContentOutputBuilder around to accumulate
80     *   results.  We're going to wait and see to what extent methods like
81     *   this are necessary.
82     *   (ParserOutput will implement a ::mergeTo(ContentMetadataCollector)
83     *   method, as it has read access to its own contents.)
84     * ::setNoGallery()/::setEnableOOUI()/::setNewSection()/::setHideNewSection()
85     * ::setPreventClickjacking()/::setIndexPolicy()/
86     *   Available via ::setOutputFlag() (see T292868)
87     * ::setCategories()
88     *   Doesn't seem necessary, we have ::addCategory().
89     *   (And adding the ability to overwrite categories would be bad.)
90     * ::addTrackingCategory()
91     *   This was moved to Parser / the TrackingCategories service, and
92     *   equivalently DataAccess in Parsoid.
93     * ::isLinkInternal()
94     *   T296036: Should be non-public or at least @internal?
95     * ::addInterwikiLink()
96     *   invoked from ::addLink() if the link is external, we don't
97     *   need a separate entry point.
98     * ::setSections()
99     *   T296025: replaced with ::setTOCData()
100     * ::setLanguageLinks()
101     *   Deprecated; replaced with ::addLanguageLink()
102     * ::addExtraCSPDefaultSrc()
103     * ::addExtraCSPStyleSrc()
104     * ::addExtraCSPScriptSrc()
105     *   T296345: handled through ::appendOutputStrings()
106     * ::updateRuntimeAdaptiveExpiry()
107     *   See discussion in T296345.  Parsoid shouldn't need to know about
108     *   this; extensions can bypass Parsoid to invoke the ParserOutput
109     *   method directly.
110     *
111     * == Temporarily omitted ==
112     * ::addTemplate()
113     *   T296038: Requires page id and revision id.  In addition, this
114     *   interacts with user hooks.  The MediaWiki side should probably be
115     *   responsible for updating the Template dependencies not Parsoid.
116     *   OTOH, we need to return *something* like a Title back because
117     *   eventually Parsoid has to fetch the template to expand it.
118     * ::setTitleText()
119     *   T293514: This contains the title in HTML and is redundant with
120     *   ::setDisplayTitle()
121     */
122
123    /**
124     * Add a category, with the given sort key.
125     *
126     * @param LinkTarget $c Category name
127     * @param string $sort Sort key (pass the empty string to use the default)
128     */
129    public function addCategory( $c, $sort = '' ): void;
130
131    /**
132     * Record a local or interwiki inline link for saving in future link tables.
133     *
134     * @param LinkTarget $link (used to require Title until 1.38)
135     * @param int|null $id Optional known page_id so we can skip the lookup
136     *   (generally not used by Parsoid)
137     */
138    public function addLink( LinkTarget $link, $id = null ): void;
139
140    /**
141     * Register a file dependency for this output
142     * @param LinkTarget $name Title dbKey
143     * @param string|false|null $timestamp MW timestamp of file creation (or false if non-existing)
144     * @param string|false|null $sha1 Base 36 SHA-1 of file (or false if non-existing)
145     */
146    public function addImage( LinkTarget $name, $timestamp = null, $sha1 = null ): void;
147
148    /**
149     * Add a language link.
150     * @param LinkTarget $lt
151     */
152    public function addLanguageLink( LinkTarget $lt ): void;
153
154    /**
155     * Add a warning to the output for this page.
156     * @param string $msg The localization message key for the warning
157     * @param mixed ...$args Optional arguments for the message
158     */
159    public function addWarningMsg( string $msg, ...$args ): void;
160
161    /**
162     * @param string $url External link URL
163     */
164    public function addExternalLink( string $url ): void;
165
166    /**
167     * Provides a uniform interface to various boolean flags stored
168     * in the content metadata.  Flags internal to MediaWiki core should
169     * have names which are constants in ParserOutputFlags.  Extensions
170     * should use ::setExtensionData() rather than creating new flags
171     * with ::setOutputFlag() in order to prevent namespace conflicts.
172     *
173     * @param string $name A flag name
174     * @param bool $val
175     */
176    public function setOutputFlag( string $name, bool $val = true ): void;
177
178    /**
179     * Provides a uniform interface to various appendable lists of strings
180     * stored in the content metadata. Strings internal to MediaWiki core should
181     * have names which are constants in ParserOutputStrings.  Extensions
182     * should use ::setExtensionData() rather than creating new keys here
183     * in order to prevent namespace conflicts.
184     *
185     * @param string $name A string name
186     * @param string[] $value
187     */
188    public function appendOutputStrings( string $name, array $value ): void;
189
190    /**
191     * Set a numeric page property whose *value* is intended to be sorted
192     * and indexed.  The sort key used for the property will be the value,
193     * coerced to a number. It is also possible to efficiently look up all
194     * the pages with a certain property (the "presence" of the
195     * property is also indexed; see Special:PagesWithProp,
196     * list=pageswithprop).
197     *
198     * The page property is stored in the page_props database
199     * table. The page_props table is a key-value store indexed by the
200     * page ID. This allows the parser to set a property on a page
201     * whose value can then be quickly retrieved given the page ID or via a
202     * DB join when given the page title.  The page_props table is *also*
203     * indexed on the numeric sort key passed as $numericValue to this
204     * method. This allows for efficient "top k" queries of pages with
205     * respect to a given property.
206     *
207     * In the future, we may allow the value to be specified independent
208     * of sort key (T357783).
209     *
210     * The setNumericPageProperty() method is thus used to propagate
211     * properties from the parsed page to request contexts other than
212     * a page view of the currently parsed article.
213     *
214     * Some applications examples:
215     *
216     *   * The Proofread page extension stores
217     *     `proofread_page_quality_level` as a numeric property to allow
218     *     efficient retrieval of pages of a certain quality level.
219     *
220     *   * Keeping a count of the number of errors found in a page property
221     *     to allow listing pages in order from most errors to least.
222     *
223     * If you need a placeholder value, you likely should be using
224     * ::setUnsortedPageProperty() instead.
225     *
226     * @note Note that the PageProp service always returns strings
227     *  for the value of the page property, while values retrieved
228     *  from this ParserOutput will be numeric.  Be careful to distinguish
229     *  these two cases.
230     *
231     * @note Do not use setNumericPageProperty() to set a property
232     * which is only used in a context where the ParserOutput object
233     * itself is already available, for example a normal page
234     * view. There is no need to save such a property in the database
235     * since the text is already parsed; use ::setExtensionData()
236     * instead.
237     *
238     * @par Example:
239     * @code
240     *    $parser->getOutput()->setExtensionData( 'my_ext_foo', '...' );
241     * @endcode
242     *
243     * And then later, in the OutputPageParserOutput hook or similar:
244     *
245     * @par Example:
246     * @code
247     *    $output->getExtensionData( 'my_ext_foo' );
248     * @endcode
249     *
250     * @param string $propName The name of the page property
251     * @param int|float|string $numericValue the numeric value
252     * @since 1.42
253     */
254    public function setNumericPageProperty( string $propName, $numericValue ): void;
255
256    /**
257     * Set a page property whose *value* is not intended to be sorted
258     * and indexed. It is still possible to efficiently look up all
259     * the pages with a certain property (the "presence" of the
260     * property *is* indexed; see Special:PagesWithProp,
261     * list=pageswithprop).
262     *
263     * The page property is stored in the page_props database
264     * table. The page_props table is a key-value store indexed by the
265     * page ID. This allows the parser to set a property on a page
266     * whose value can then be quickly retrieved given the page ID or via a
267     * DB join when given the page title.
268     *
269     * The setUnsortedPageProperty() method is thus used to propagate
270     * properties from the parsed page to request contexts other than
271     * a page view of the currently parsed article.
272     *
273     * Some applications examples:
274     *
275     *   * To implement hidden categories, hiding pages from category listings
276     *     by storing a page property.
277     *
278     *   * Overriding the displayed article title
279     *     (ParserOutput::setDisplayTitle()).
280     *
281     *   * To implement image tagging, for example displaying an icon on an
282     *     image thumbnail to indicate that it is listed for deletion on
283     *     Wikimedia Commons.
284     *     (This is not actually implemented yet but would be pretty cool.)
285     *
286     * It is recommended to use the empty string if you need a
287     * placeholder value (ie, if it is the *presence* of the property
288     * which is important, not the *value* the property is set to).
289     *
290     * @note Do not use setUnsortedPageProperty() to set a property
291     * which is only used in a context where the ParserOutput object
292     * itself is already available, for example a normal page
293     * view. There is no need to save such a property in the database
294     * since the text is already parsed; use ::setExtensionData()
295     * instead.
296     *
297     * @par Example:
298     * @code
299     *    $parser->getOutput()->setExtensionData( 'my_ext_foo', '...' );
300     * @endcode
301     *
302     * And then later, in the OutputPageParserOutput hook or similar:
303     *
304     * @par Example:
305     * @code
306     *    $output->getExtensionData( 'my_ext_foo' );
307     * @endcode
308     *
309     * @param string $propName The name of the page property
310     * @param string $value Optional value; defaults to the empty string.
311     * @since 1.42
312     */
313    public function setUnsortedPageProperty( string $propName, string $value = '' ): void;
314
315    /**
316     * Attaches arbitrary data to this content. This can be used to
317     * store some information for later use during page output. The
318     * data will be cached along with the parsed page, but unlike data
319     * set using set*PageProperty(), it is not recorded in the
320     * database.
321     *
322     * To use setExtensionData() to pass extension information from a
323     * hook inside the parser to a hook in the page output, use this
324     * in the parser hook:
325     *
326     * @par Example:
327     * @code
328     *    $parser->getOutput()->setExtensionData( 'my_ext_foo', '...' );
329     * @endcode
330     *
331     * And then later, in OutputPageParserOutput or similar:
332     *
333     * @par Example:
334     * @code
335     *    $output->getExtensionData( 'my_ext_foo' );
336     * @endcode
337     *
338     * @note Only scalar values, e.g. numbers, strings, arrays or
339     * MediaWiki\Json\JsonUnserializable instances are supported as a
340     * value. Attempt to set other class instance as a extension data
341     * will break ParserCache for the page.
342     *
343     * @note As with ::setJsConfigVar(), setting a page property to multiple
344     * conflicting values during the parse is not supported.
345     *
346     * @param string $key The key for accessing the data. Extensions
347     *   should take care to avoid conflicts in naming keys. It is
348     *   suggested to use the extension's name as a prefix.  Keys
349     *   beginning with `mw-` are reserved for use by mediawiki core.
350     *
351     * @param mixed $value The value to set.
352     *   Setting a value to null is equivalent to removing the value.
353     */
354    public function setExtensionData( string $key, $value ): void;
355
356    /**
357     * Appends arbitrary data to this ParserObject. This can be used
358     * to store some information in the ParserOutput object for later
359     * use during page output. The data will be cached along with the
360     * ParserOutput object, but unlike data set using
361     * set*PageProperty(), it is not recorded in the database.
362     *
363     * See ::setExtensionData() for more details on rationale and use.
364     *
365     * In order to provide for out-of-order/asynchronous/incremental
366     * parsing, this method appends values to a set.  See
367     * ::setExtensionData() for the flag-like version of this method.
368     *
369     * @note Only values which can be array keys are currently supported
370     * as values.  Be aware that array keys which 'look like' numbers are
371     * converted to ints by PHP, and so if you put in `"0"` as a value you
372     * will get `[0=>true]` out.
373     *
374     * @param string $key The key for accessing the data. Extensions should take care to avoid
375     *   conflicts in naming keys. It is suggested to use the extension's name as a prefix.
376     *
377     * @param string|int $value The value to append to the list.
378     * @param MergeStrategy $strategy Merge strategy; defaults to
379     *  MergeStrategy::UNION.
380     */
381    public function appendExtensionData(
382        string $key,
383        string|int $value,
384        string|MergeStrategy $strategy = MergeStrategy::UNION
385    ): void;
386
387    /**
388     * Add a variable to be set in mw.config in JavaScript.
389     *
390     * In order to ensure the result is independent of the parse order, the values
391     * set here must be unique -- that is, you can pass the same $key
392     * multiple times but ONLY if the $value is identical each time.
393     * If you want to collect multiple pieces of data under a single key,
394     * use ::appendJsConfigVar().
395     *
396     * @param string $key Key to use under mw.config
397     * @param mixed|null $value Value of the configuration variable.
398     */
399    public function setJsConfigVar( string $key, $value ): void;
400
401    /**
402     * Append a value to a variable to be set in mw.config in JavaScript.
403     *
404     * In order to ensure the result is independent of the parse order,
405     * the value of this key will be an associative array, mapping all of
406     * the values set under that key to true.  (The array is implicitly
407     * ordered in PHP, but you should treat it as unordered.)
408     * If you want a non-array type for the key, and can ensure that only
409     * a single value will be set, you should use ::setJsConfigVar() instead.
410     *
411     * @note Only values which can be array keys are currently supported
412     * as values.  Be aware that array keys which 'look like' numbers are
413     * converted to ints by PHP, and so if you put in `"0"` as a value you
414     * will get `[0=>true]` out.
415     *
416     * @param string $key Key to use under mw.config
417     * @param string|int $value Value to append to the configuration variable.
418     * @param MergeStrategy $strategy Merge strategy; defaults to
419     *  MergeStrategy::UNION.
420     */
421    public function appendJsConfigVar(
422        string $key,
423        string|int $value,
424        string|MergeStrategy $strategy = MergeStrategy::UNION
425    ): void;
426
427    /**
428     * @see OutputPage::addModules
429     * @param string[] $modules
430     * @deprecated use ::appendOutputStrings(::MODULE, ...)
431     */
432    public function addModules( array $modules ): void;
433
434    /**
435     * @see OutputPage::addModuleStyles
436     * @param string[] $moduleStyles
437     * @deprecated use ::appendOutputStrings(::MODULE_STYLE, ...)
438     */
439    public function addModuleStyles( array $moduleStyles ): void;
440
441    /**
442     * Sets parser limit report data for a key
443     *
444     * The key is used as the prefix for various messages used for formatting:
445     *  - $key: The label for the field in the limit report
446     *  - $key-value-text: Message used to format the value in the "NewPP limit
447     *      report" HTML comment. If missing, uses $key-format.
448     *  - $key-value-html: Message used to format the value in the preview
449     *      limit report table. If missing, uses $key-format.
450     *  - $key-value: Message used to format the value. If missing, uses "$1".
451     *
452     * Note that all values are interpreted as wikitext, and so should be
453     * encoded with htmlspecialchars() as necessary, but should avoid complex
454     * HTML for sanity of display in the "NewPP limit report" comment.
455     *
456     * @param string $key Message key
457     * @param mixed $value Appropriate for Message::params()
458     */
459    public function setLimitReportData( string $key, $value ): void;
460
461    /**
462     * Sets Table of Contents data for this page.
463     *
464     * Note that merging of TOCData is not supported; exactly one fragment
465     * should set TOCData.
466     *
467     * @param TOCData $tocData
468     */
469    public function setTOCData( TOCData $tocData ): void;
470
471    /**
472     * Set the content for an indicator.
473     *
474     * @param string $name
475     * @param string $content
476     * @param-taint $content exec_html
477     */
478    public function setIndicator( $name, $content ): void;
479}