Commit graph

85 commits

Author SHA1 Message Date
jenkins-bot 45119f8c61 Merge "Move "dir" error handling to validation" 2019-12-19 10:18:24 +00:00
Thiemo Kreuz 5c65525c95 Introduce ReferenceStack::appendText
I feel this is a little better than before. It looks like we never need
to *replace* a text that existed before.

This depends on I4a156aa which fixes one of the last remaining trimming
issues. Outside of <references>, a <ref> </ref> with no other content
but some whitespace was already forbidden. But not inside of <references>.
This is relevant for appendText(). It should not be called with null, but
was because of the inconsistent behavior.

Change-Id: I38c9929f2fa6e69482e45919e2f8dbf823cb1c8b
2019-12-19 08:52:48 +01:00
jenkins-bot 0d7e04e1ee Merge "Fix inconsistent error reporting for invisible content" 2019-12-18 09:27:03 +00:00
Adam Wight 1e82f8f073 Move "dir" error handling to validation
Note that this patch changes behavior, an invalid "dir" will result in
a cite reference at the point where the <ref> is declared rather than
in the references section.  This is consistent with other errors.

Bug: T15673
Change-Id: Id10db40aa0b391f2f1d9274aa09d22a7278d65e3
2019-12-18 10:05:59 +01:00
Thiemo Kreuz 1f76199ed8 Add parser tests for the responsive="…" feature
Change-Id: Id9d733dabf82f2c26f51c6fbd1e03fe0574e88a8
2019-12-17 15:51:41 +01:00
Thiemo Kreuz 1bd66081f7 Fix inconsistent error reporting for invisible content
This makes one of the last remaining edge-cases about non-empty, but
non-visible content (a <ref> that only contains whitespace) behave
identical to all other places. We already reported it as being empty
everywhere else, except inside of <references>.

Note that the test cases look like they are reporting the same errors
twice. But this is not the case:

The first set of errors is about <ref name="…"> inside of <references>
not having visible content. This should always be reported, even if the
<ref> got content from somewhere else on the page.

The second set of errors is when a <ref name="…"> *never* got any
content.

This patch will slightly increase the numbers of errors reported.

Change-Id: I4a156aa9e466f735d92fe0ba5cc0678ec8bbdd50
2019-12-17 13:37:01 +01:00
Thiemo Kreuz 51ff3cc819 Several code cleanups after getting rid of cloning
* Use the Html class to safely create HTML code.
* $this->referenceStack can not be null any more.
* $this->inReferencesGroup is not needed during output, only when
  parsing tags.
* Replace ReferencesStack::getGroupRefs() as well as deleteGroup()
  with a combined popGroup() that does both things.
* Extract the code responsible for the "responsive" behavior to a
  separate function.
* Some TestingAccessWrapper are not needed.

Change-Id: Ie1cf2533d7417ae2f6647664ff1145e37b814a39
2019-12-16 15:47:23 +01:00
Adam Wight 9fd825e6a6 Simplify null comparison
In these cases, an expression is either true-ish or null, so we can use
the implicit boolean cast to test.

Change-Id: Ibe94829f9774bf2a1907635a8bd28369908b4d1e
2019-12-12 16:42:53 +01:00
Adam Wight ab07a3253c Remove Parser state from CiteErrorReporter
Finishes breaking the circular reference between Cite and Parser.

This patch also demonstrates how evil it is to allow the error reporter
to be called from anywhere, and have side-effects.  At least it's explicit
now.

Also fixes a bug where the inner error message would not be in the
interface language.

Bug: T240431
Change-Id: Ic3325cafb503e78295d72231ac6da5c121402def
2019-12-12 11:15:07 +01:00
Adam Wight 22b2f78db6 Remove Parser state from ReferencesFormatter
Bug: T240431
Change-Id: I3477a64b9a9dba0cfe890c4b598a51c2f971c76c
2019-12-12 11:12:17 +01:00
Adam Wight 2a5976f007 Remove Parser state from FootnoteMarkFormatter
Bug: T240431
Change-Id: Ie53444114c032e083293d3b5325252debb0640a7
2019-12-12 11:12:17 +01:00
Adam Wight 852a503262 Don't keep parser reference in Cite
This begins our journey of breaking the circular reference between
Cite and Parser.  In later patches the child objects will also take
Parser as a parameter.

Bug: T240431
Change-Id: Ic672bb4bae19ac5f1e1f5817de171d76b3bd8786
2019-12-12 11:12:17 +01:00
Adam Wight a227395e3a Lazy instantiation of Cite
Only create a Cite object if we need one.  Never clearState, just
destroy and recreate later.

This makes it less likely that we leak state between parsers, and
saves memory and processing on pages without references.

It's also preparation to decouple Cite logic from state.

Change-Id: I3db517591f4131c23151c76c223af7419cc00ae9
2019-12-12 11:12:17 +01:00
Thiemo Kreuz 3f2aeb7e31 Rename two Cite… classes and clean up test setups
* All classes are in a Cite\ namespace now. No need to repeat the word
"Cite" all over the place.

* The "key formatter" is more an ID or anchor formatter. The strings it
returns are all used in id="…" attributes, as well as in href="#…" links
to jump to these IDs.

* This patch also removes quite a bunch of callbacks from tests that
don't need to be callbacks.

* I'm also replacing all json_encode().

* To make the test code more readable, I shorten a bunch of variable
names to e.g. $msg. The fact they are mocks is still relevant, and still
visible because these variable names are only used in very short scopes.

Change-Id: I2bd7c731efd815bcdc5d33bccb0c8e280d55bd06
2019-12-12 08:48:02 +01:00
jenkins-bot e39b1d6cbd Merge "Use messagelocalizer in CiteErrorReporter" 2019-12-11 11:42:28 +00:00
Adam Wight f93f1b4fe0 Use messagelocalizer in CiteErrorReporter
Fixes a bug introduced in Icf61c9a27fd, which would cause a parser
cache split any time the Cite extension was initialized.  The
`setLanguage` interface is regrettable, but I'm hoping it will only
be around temporarily.

Converts an integration test into a unit test and completes coverage.

Bug: T239988
Change-Id: I4b1f8909700845c9fa0cbc1a3de50ee7d42f69a5
2019-12-11 09:53:47 +01:00
jenkins-bot 37ea791a4c Merge "Use a guard clause in Cite::checkRefsNoReferences" 2019-12-11 08:18:18 +00:00
Thiemo Kreuz 66069d9dcf Use a guard clause in Cite::checkRefsNoReferences
This patch also cleans up a few pieces of PHPDoc documentation.

Change-Id: Ib207b11121769c543723db4668786f4916470368
2019-12-10 15:33:53 +00:00
Thiemo Kreuz df1a45b84c Fix incomplete cloning of the Parser::$extCite instance
This is what happens:
* The issue happens only on pages with two <ref> tags than share the
same name and group, but have conflicting text.
* This triggers a code path that renders an error message and calls
Message::plain() as well as Parser::addTrackingCategory(), which calls
Message::text().
* The Message class is asking for a new, fresh parser. This means the
parser is cloned and it's state cleared, while keeping stuff like
parser hooks.
* Cloning the parser triggers the ParserCloned hook.
* The hook handler clones the Cite instance stored in Parser::$extCite.
* PHP doesn't do deep cloning. Object properties are not cloned.
* Since I091a0b7 the internal state of the Cite class is extracted to
another class.
* This means the state is not cloned any more since I091a0b7.
* Now two Cite instances share the same state.
* At the end of the hook handler, the state is cleared, which also
clears the state of the original instance.

We will most probably solve this on master by getting rid of cloning
Cite. We propose this additional hotfix for the branch.

Bug: T240248
Change-Id: Ic5a438e04d003a637ae08aae936d9977cc90d5d3
2019-12-10 14:20:00 +00:00
Thiemo Kreuz 71c6dc7fe4 Better naming for ReferenceFormatter class and methods
This class renders a <references> tag and everything inside. The
previous name sounds like it is responsible for rendering the contents
of a <ref>…</ref> tag. I mean, the class contains a method that does
exactly this. But this method is private.

Change-Id: I1cd06c9a11e0a74104f2874a34efa3e0843a0f70
2019-12-10 08:40:09 +01:00
Thiemo Kreuz 7c1849d7b0 Report both nested <ref> and <references> as an error
Before, this regular expression was looking for incomplete wikitext
like this:

<ref>unclosed
<ref>closed</ref>

With this change, wikitext like this will trigger the same error:

<ref>unclosed
<references />
incomplete</ref>

This should be much, much more rare. But I feel it's reasonable to mark
this as an error, instead of just rendering the broken inner tag in
plain text.

This patch also replaces `.*?>` with `[^>]*+>`. Both do the exact same.
Instead of doing an "ungreedy search for the first possible closing
bracket", which might cause backtracking, the new syntax consumes all
non-brackets before expecting one. This is guaranteed to never backtrack
(guaranteed by the extra +), and potentially faster because of this.

Change-Id: Ic76a52cd111b28e4522f095ce3984e3583f602c1
2019-12-09 14:26:28 +01:00
Adam Wight 8097c4c148 Split validation function depending on inReferencesGroup
Some validation is exclusively used in a specific context, some is shared.

Change-Id: I390db1c9d4854871e25a2e74411476e4e1c0b66f
2019-12-09 12:27:52 +01:00
jenkins-bot 0f0356ffc1 Merge "Refine and fix "unclosed <ref> detected" regular expression" 2019-12-09 10:29:13 +00:00
jenkins-bot a8e882e39f Merge "Show "Preview" headline in user instead of content language" 2019-12-09 10:13:17 +00:00
Thiemo Kreuz c5fe49ff11 Fail early on nested extends="…", if possible
This partly reverts Ied2e3f5. I haven't properly tested this before.
Rendering a bad extends (that extends a <ref> that's already extended)
not indented messes the order up and rips other extended <ref>s out of
context.

For now it might be better to stick to the previous, "magic" behavior:
Such an extends behaves like it is extending the *parent*, and is
ordered and indented as such. This is still not correct, but I feel
this is much better than rendering such a bad extends on the top level.

This patch also makes the code fail much earlier for a nested extends,
if this decision can be made already. In this case the error message is
rendered in the middle of the text (as other errors also are), not in
the <references> section.

Change-Id: I33c6a763cd6c11df09d10dfab73f955ed15e9d36
2019-12-09 10:54:52 +01:00
Thiemo Kreuz 8fdce945bd Show "Preview" headline in user instead of content language
This partly reverts Id7a4036e64920acdeccb4dfcf6bef31d0e5657ab.

The message "cite_section_preview_references" says "Preview of references".
This line is not meant to be part of the content, but an interface message.
It should use the users (interface) language, not the content language.

Change-Id: I1b1b5106266606eb0dfaa31f4abd3cee9ba92e8c
2019-12-09 10:53:07 +01:00
Thiemo Kreuz a7ee7c9586 Refine and fix "unclosed <ref> detected" regular expression
This simplifies as well as fixes a series of issues with this regular
expression:

* Before, the wikitext `<REF><REF>` would not trigger the error, but
`<ref><ref>` would. Parser tags are case-insensitive, but the error
check was not.

* Before, the wikitext `<ref><ref name="<">` would not trigger the error.
That's a valid name. The error check should not stop just because it
found a `<`.

* Both the old and the new code do *not* fail with the wikitext
`<ref><ref</ref>` where the inner `<ref` does not have a closing `>`. I
was thinking about changing this, but figured it might be used as a
feature.

* The old code was not able to properly understand HTML comments,
<nowiki> tags and such that contain a line break. That caused
inconsistent and confusing error reporting in some cases, but not in
others. This change *reduces* the amount of errors this code produces.

* The old code was looking for "SGML tags" with names that could be
anything, not just alphanumeric characters. This allowed for strange
edge-cases like `<ref><>><ref></>></ref>` that have not been reported,
but should be. This change *increases* the amount of errors. However,
relevant edge-cases should be extremely rare.

Note the ++ avoids backtracking, speeding up the regex.

Change-Id: I0c61a245f4f743871b4cad886ce239650af2b37c
2019-12-08 04:37:13 +00:00
Adam Wight 01c76f46a6 Use message localizer in CiteKeyFormatter
Makes more tests easier.

Change-Id: I222ba61bfcf0be3e29cb04e39f44f0be7a9e0778
2019-12-05 14:57:32 +01:00
Adam Wight 1ce4079ce2 Use message localizer in FootnoteMarkFormatter
Completes test coverage.

Change-Id: Ib2ec24cf4a9de52769744d1888cb13d2bf08ae3b
2019-12-05 14:56:53 +01:00
Adam Wight 430086cb6b Use the message localizer in Cite
Allows us to convert another integration test into a unit test.

Change-Id: Id7a4036e64920acdeccb4dfcf6bef31d0e5657ab
2019-12-05 13:23:31 +01:00
Adam Wight 646dc5f974 Drop unused variable
Change-Id: I393a89ca909a632729c88ff73543bcf71061a8bf
2019-12-05 09:03:17 +01:00
Adam Wight 5705228d17 Complete validateRef coverage
Change-Id: Id61fba34a8815a0c512ecf4bc57da3be4e15c8bb
2019-12-04 18:00:13 +01:00
Thiemo Kreuz a7c4e14f42 Remove obsolete ParserBeforeTidy hook handler
I was able to track this code down to I093d85d from 2012, which was done
right after the ParserAfterParse hook was introduced. I believe the
redundant code path was left to keep the Cite extension compatible with
old MediaWiki versions that did not had this hook yet.

I also noticed this code path is most probably entirely redundant with
the current version of MediaWiki. The *only* thing this code does is
blocking the ParserBeforeTidy hook from doing the same thing a second
time if the ParserAfterParse hook was called before. But it does *not*
block any other compination, e.g. if the two hooks are called the other
way around, or the same hook twice.

In core, it looks like it is impossible for the ParserBeforeTidy hook
being fired without the ParserAfterParse hook being fired before. If this
is true, this is in fact dead code.

Change-Id: Iacf8b600c7abdeaf89c22c2fc31e646f57245e47
2019-12-04 16:56:43 +01:00
Adam Wight c09d90aff3 Use message localizer in FootnoteBodyFormatter
Makes the class more easily testable.

Patch also changes an integration test into a unit test.

Change-Id: I545730404aceed7e3857d96f4fd3c1b0a900c0c2
2019-12-04 13:41:44 +01:00
Adam Wight d04cc36fa4 Replace reference parameter with return value
This makes it obvious that our function isn't sensitive to the input value.

Also rearranges a string concatenation to make the element wrapping clearer.
I probably should have switched to the HTML class here, but I'm not sure what
the advantages would be.

Change-Id: Ife3424ce68588f73f168b10e63e6cd81c4a60084
2019-12-04 11:28:38 +01:00
Adam Wight e9958d569b Formatter takes responsibility for rendering footnote mark
Pass the full ref structure from ReferenceStack to FootnoteMarkFormatter,
to give it control over the final rendering.  This is aligned with how
the FootnoteBodyFormatter directly scans over groupRefs.

Change-Id: I3294fd9366f01daa4250a5d481f4adbae84c72b1
2019-12-02 10:17:24 +01:00
Thiemo Kreuz 504db2c46a Add strict PHP 7 type hints to most code
This patch does two things:
* Add strict PHP 7 type hints to most code.
* Narrow the interface of the checkRefsNoReferences() method to not
  require a ParserOptions object any more.

Change-Id: I91c6a2d9b76915d7677a3f735ee8e054c898fcc5
2019-12-02 08:51:42 +01:00
Adam Wight ffedf86a19 Clean up text and name conditionals
The "no key" error should have been unreachable, but I'm afraid that
null `$text` and empty string `$text` were reporting slightly different errors.

Unfortunately, we still have to care about `$text = '0'` because PHP, so
the expressions don't reduce to `if ( !$text ...`

Change-Id: Id1028611ec3bc462dca413f31f7f59637bd7cc7b
2019-11-29 19:26:12 +00:00
Adam Wight a40b1b10be Extract footnote body rendering
Change-Id: I9537849cbd700d5dc7ec1a53d852d69b0fe0dc35
2019-11-29 16:22:35 +01:00
Adam Wight c236524138 Extract footnote mark rendering
Change-Id: I79de89e46da36dc1f0ee2b2fdb9a139e6434fde2
2019-11-29 16:22:35 +01:00
jenkins-bot 4b58a25459 Merge "Extract key formatting" 2019-11-29 15:19:52 +00:00
jenkins-bot 50ccd05def Merge "Render nested references" 2019-11-29 15:19:50 +00:00
Thiemo Kreuz f8affe8eee Remove redundant variable names from @var docs
Change-Id: I5ba2f1041d3d6770c58f496482d2799bb24786be
2019-11-29 14:37:58 +01:00
Adam Wight a4c056f59b Extract key formatting
Change-Id: I155ec6f3e21075587dbcfdfdc346f28f958e3c15
2019-11-29 13:41:12 +01:00
Thiemo Kreuz 13598ba11e Render nested references
Forked from Icd933fc983.

Bugs and unimplemented features are documented as TODOs in the parser test
fixtures.

Bug: T237241
Change-Id: I9427e025ea0bcf2fa24fd539a775429cc64767cc
2019-11-29 13:40:34 +01:00
jenkins-bot 3beb5c3634 Merge "Remove ApiQueryReferences support" 2019-11-29 11:30:38 +00:00
Adam Wight a176e22097 Remove ApiQueryReferences support
This API was never used in Wikimedia production, and would have caused
performance problems.  Removing the dead code will simplify our refactoring.

Bug: T238195
Change-Id: I7088f257ec034c0d089e0abdaa5a739910598300
2019-11-28 11:08:46 +01:00
Adam Wight ab78df8d5c Wire extends into ReferenceStack
Takes no action, just shuttle the value between functions.

(Split from I9427e025ea0)

Change-Id: I271043e9161835f3278098787bf58b50ed93c892
2019-11-28 02:10:11 +01:00
jenkins-bot dbf4c56896 Merge "[Refactor] Pass validation error with StatusValue" 2019-11-27 21:23:30 +00:00
jenkins-bot e4a961a6c1 Merge "Rename $valid to $status for clarity" 2019-11-27 21:23:29 +00:00