Fix two problems that made it difficult to convert between Message
and MessageValue, or to write code that could accept both of them,
as exemplified by the StatusValue class:
* Implement a common interface
* Use the same internal format for message parameters
While these changes should be compatible with most of existing code,
where the authors were courteous enough to simply call methods such
as Message::numParam() and not look inside the values they return,
it is potentially a breaking change for anything that depended on
the formatted params being arrays or accessed their keys.
Example patches: https://gerrit.wikimedia.org/r/q/topic:message-param
Notable changes:
* Message and MessageValue now both implement MessageSpecifier
(only Message implemented it before).
* Message::numParam() and other static methods for encoding params
now return MessageParam objects, instead of special arrays.
Use these MessageParam objects internally in Message.
* Narrow down the return type of MessageSpecifier::getParams() (it
was just `array`, allowing any type in the array). Narrow down the
types for Message::params() and MessageValue::params() to match.
* Deprecate MediaWiki\Message\Converter. As a replacement add
MessageValue::newFromSpecifier(), which is analogous to
Message::newFromSpecifier(), but without weird legacy edge cases.
* Make StatusValue::getMessages() return MessageValues. Remove code
that converted between Message and MessageValue, no longer needed.
* Update many type declarations and comments to use MessageSpecifier
instead of MessageValue, as well as a couple of tests that depended
on implementation details.
Bug: T358779
Change-Id: I625a48a6ecd3fad5c2ed76b23343a0fef91e1b83
get_debug_type() does the same thing but better (spelling type names
in the same way as in type declarations, and including names of
object classes and resource types). It was added in PHP 8, but the
symfony/polyfill-php80 package provides it while we still support 7.4.
Also remove uses of get_class() and get_resource_type() where the new
method already provides the same information.
For reference:
https://www.php.net/manual/en/function.get-debug-type.phphttps://www.php.net/manual/en/function.gettype.php
In this commit I'm only changing code where it looks like the result
is used only for some king of debug, log, or test output. This
probably won't break anything important, but I'm not sure whether
anything might depend on the exact values.
Change-Id: I7c1f0a8f669228643e86f8e511c0e26a2edb2948
In change I625a48a6ecd3fad5c2ed76b23343a0fef91e1b83 I am planning to
make Wikimedia\Message\MessageValue use it, and we try to pretend that
it is a library separate from MediaWiki, so it makes sense to move
MessageSpecifier to the same namespace under Wikimedia\.
Bug: T353458
Change-Id: I9ff4ff7beb098b60c92f564591937c7d789c6684
We have some code that expects that if you disassemble a
MessageSpecifier using its getKey() and getParams() methods,
then assemble a new MessageSpecifier using the return values,
you will get (at least approximately) the same message.
This was not the case with RawMessage, even though it implements
the MessageSpecifier interface, because its "keys" are not real
message keys, and this operation would mess it up.
Override the MessageSpecifier methods on RawMessage so that they're
compatible with how everyone expects a MessageSpecifier to work.
Add some tests for OutputPage, Message\Converter and Status
to verify some scenarios that would previously have failed.
Depends-On: I41991989515b4791bc1746f26bd404bf4f17dbdb
Depends-On: I612361dd20ff8aad4c0069f1c5af78e3e13b9692
Change-Id: Iddd14efa8b9536277c372257d5a7be135f26a540
In PHP 8, but not in PHP 7.4, every class with a __toString() function
implicitly implements the Stringable interface. Therefore, the
behavior of checks like "instanceof Stringable" differs between these
PHP versions when such classes are involved. Make every such class
implement the interface so that the behavior will be consistent.
The PHP 7.4 fallback for the Stringable interface is provided by
symfony/polyfill-php80.
Change-Id: I3f0330c2555c7d3bf99b654ed3c0b0303e257ea1
Normally two Message objects can be compared with `==`, and they will
compare equal if they have the same key, parameters and internal state
such as the selected language.
However, if you call `setContext()` on a Message, it will never
compare equal to any other Message object, because a unique closure
is stored in the `userLangCallback` property.
Most implementations of MessageLocalizer::msg() use `setContext()`,
so filtering out duplicate Message objects in StatusValue usually
didn't work. Luckily most uses of StatusValue use string message keys.
Change-Id: Id22075bf73d37fd139c2ef7d80c69eeb462a7b68
StatusValue::replaceMessage() doesn't really work if given a
MessageSpecifier, and doesn't work at all if given a MessageValue.
StatusValue::hasMessage() and ::hasMessagesExcept() ignore the message
parameters when searching if given a MessageSpecifier or MessageValue.
Therefore, deprecate passing anything other than strings representing
message keys to these methods.
Change-Id: Icb4effc6c5319c12ba4ebeab447a0cef54f8e255
The parameters have always been ignored, so this is usually a mistake.
Depends-On: Ic12241bd3029bc1b0e7a0023689a2be35ccd30a8
Change-Id: I0675e557bb93a1c990fa923c50b9f6ee8a9836c8
An array of MessageSpecifier objects is easier to deal with than the
"legacy error array" format, which is an array of whatever wfMessage()
accepts, which can be a bunch of different things.
Deprecate some existing getters.
Change-Id: Ibc4ce11594cf36ce7b2495d2636ee080d3443b04
Mixing different binary boolean operators within an expression
without using parentheses to clarify precedence is not allowed (T358966)
Change-Id: I24ca752d5dac7c948fdbcabf721f6f0aef8a466f
Custom Status or StatusValue subclasses can be useful to make the
contained value easier to work with – see e.g. PageUpdateStatus with its
custom factory newEmpty() and the accessors getNewRevision(),
wasPageCreated() etc. Let’s bless this practice by marking StatusValue
as stable to extend; Status is left untouched, because we generally want
to encourage use of StatusValue, not Status, these days. (Note that both
classes are already extended in some extensions, namely MediaModeration,
ReportIncident and SecurePoll.) Several protected fields by the class
which are not meant for other subclasses are marked @internal.
Bug: T358492
Change-Id: I6690fbbb13624ce650d45ab2a872ba38f1dd90a2
Use modern array destructuring and such to make the code – so I
hope – much more readable.
Also fix a mistake in the Status test setup. This caused the mocked
Message::getParams() to return an array with string keys. This is
impossible in non-mocked scenarios. There is an array_values() call
in the Message constructor that doesn't allow string keys.
Change-Id: Ief09feb06c60d3ffbfa95fa8ef56b4a9829da680
This allows extensions and hooks to pass around additional data
about the operation result arbitrarily to supplement value and errors.
When two StatusValue instances are to be merged, it's responsibility
of the caller to ensure either only one has this extra data or none,
but never both (since the type is unrestricted). If necessary, the
caller should merge them before invoking StatusValue::merge.
Bug: T326479
Change-Id: Ibe3f1f8b81bcfcb18551d3ca4cda464e4bdbcbce
Use mb_str_split and mb_substr to improve the chances that the fancy
table lines will line up, and to avoid corrupting multibyte characters
at boundaries. Remove max lengths in the sprintf format.
I'm not sure if this is the ideal output format, but I don't have the
heart to replace it.
Change-Id: Iff9ba98a12490938fcfefdeaebd5f1d82cd0ce7b
Motivation:
* Avoid code duplication.
* Hopefully make it easier to read.
* Also order stuff from cheap to expensive, if possible.
Change-Id: I575e3f2027ce60a0d0885be5b9bd3e07bc035eee
Various variables are left from ealier refactor are now unused
and can be removed to make the code easier to read
Change-Id: Id51770af1f08e85c7e7a02234a2cd2ab5b47ee7a
This allows us to use MessageValue in more places. In particular, it improves code re-use
between REST handlers (which use MessageValue) and old style API modules
(which use Status a lot).
Change-Id: I14f1d4444b725273675dd229d716ac6396752c90
StatusValue::toString generates tabular output. This output should
contain the type of each entry (error or warning). The index number is
not relevant and can be omitted.
Example output:
<OK, collected 2 message(s) on the way, no value set>
+----------+---------------------------+--------------------------------------+
| warning | foo | Lorem ipsum dolor sit amet, consecte |
| | | tur adipisici elit, sed eiusmod temp |
| | | or incidunt ut labore et do... |
| error | bar | [ [ a, b, c ], ABCDEFGHIJKLMNOPQRSTU |
| | | VWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABC |
| | | DEFGHIJKLMNOPQRSTUVWXYZ ABC... |
+----------+---------------------------+--------------------------------------+
Change-Id: Ia86159da2020518062e3fadc7b40da935342357f
Status and Message behave differently when given a list of message
parameters. Since the errors generated by PermissionManager is intended
to be used by Message, we need to update UserAuthority to do that.
Fixed StatusValue::replaceMessage to support MessageSpecifier objects
like StatusValue::hasMessage does. This is so that the block message
formatting in ApiBase does not break.
Bug: T306494
Change-Id: I26405c680839b4679709e750d6d54e699c1efa66
This ensures that assertions work in a uniform way,
and provides meaningful messages in cause of failure.
Change-Id: Ic01715b9a55444d3df6b5d4097e78cb8ac082b3e
Don't just cut off the message key at 25 characters, it makes
debugging very annoying. But do cut off the parameter at some
reasonable length, it could be arbitrarily large.
Change-Id: I8a2665434d6370477eb36a6827eb634e230d280a
This is micro-optimization of closure code to avoid binding the closure
to $this where it is not needed.
Created by I25a17fb22b6b669e817317a0f45051ae9c608208
Change-Id: I0ffc6200f6c6693d78a3151cb8cea7dce7c21653
This annotates classes that can safely be instantiated by
extensions, per the Stable Interface Policy.
Bug: T247862
Change-Id: Ia280f559874fc0750265ddeb7f831e65fd7d7d6a
e.g. nested messages, Message::plaintextParam(), and so on.
I'm not inclined to do too much here, since long term we should replace
Message with MessageValue and that will likely require reworking or
replacing StatusValue too.
Bug: T245155
Change-Id: Ie727de19162467574815853d2584c472a9171240
Status::wrap creates a new status object with most of its fields
references to the wrapped StatusValue. (This seems like a bad idea
but fixing it would potentially introduce subtle behavior changes
in a lot of code, so it is not attempted at this time.) When
splitting such a Status object by error type, the cloning causes
the error arrays of the new Status objects to be references to the
old one so writing them will result in a mess.
Change-Id: I9801647c39578a76be66f6e8c3c06c352660ca1e
Uses new PHP 5.6 syntax like ...parameter unpacking and
calling anything looking like a callback to make the code more readable.
There are much more occurrences but this commit is intentionally limited
to an easily reviewable size.
In one occurrence, a simple conditional instead of trickery was much more readable.
This patch finishes all the easy stuf in the core, the remainder is either unobvious
or would result in smaller readability gains. It will be carefully dealt with in
further commits.
Change-Id: I79a16c48bfb98b75e5b99f2f6f4fa07b3ae02c5b
These comments do not add anything. I argue they are worse than having
no comments, because I have to read them first to understand they
actually don't explain anything. Removing them makes room for actual
improvements in the future (if needed).
Change-Id: Iee70aad681b3385e9af282d5581c10addbb91ac4
I was bored. What? Don't look at me that way.
I mostly targetted mixed tabs and spaces, but others were not spared.
Note that some of the whitespace changes are inside HTML output,
extended regexps or SQL snippets.
Change-Id: Ie206cc946459f6befcfc2d520e35ad3ea3c0f1e0