There is native support for all of this now in PHP, thanks to changes
and additions that have been made in later versions. There should be no
need any more to ever use call_user_func() or call_user_func_array().
Reviewing this should be fairly easy: Because this patch touches
exclusivly tests, but no production code, there is no such thing as
"insufficent test coverage". As long as CI goes green, this should be
fine.
Change-Id: Ib9690103687734bb5a85d3dab0e5642a07087bbc
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.
General principles:
* Use DI if it is already used. We're not changing the way state is
managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
is a service, it's a more generic interface, it is the only
thing that provides isRegistered() which is needed in some cases,
and a HookRunner can be efficiently constructed from it
(confirmed by benchmark). Because HookContainer is needed
for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
SpecialPage and ApiBase have getHookContainer() and getHookRunner()
methods in the base class, and classes that extend that base class
are not expected to know or care where the base class gets its
HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
getHookRunner() methods, getting them from the global service
container. The point of this is to ease migration to DI by ensuring
that call sites ask their local friendly base class rather than
getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
methods did not seem warranted, there is a private HookRunner property
which is accessed directly. Very rarely (two cases), there is a
protected property, for consistency with code that conventionally
assumes protected=private, but in cases where the class might actually
be overridden, a protected accessor is preferred over a protected
property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
global code. In a few cases it was used for objects with broken
construction schemes, out of horror or laziness.
Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore
Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router
setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine
Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
I find this …->{…} curly bracket syntax surprising and confusing,
and try to avoid it as hard as I can. And that's indeed very, very
easy here. Note this really creates the exact same \stdClass object.
Change-Id: I612184be877b2aa404db9829a827cfcec2d253cf
This data is the same as the 'credits' data that is already compiled,
cached and made available via ExtensionRegistry.
Similar to various other configuration variables previously, the
$wgExtensionCredits variable is now also required to only be used
for providing input to the system (e.g. from LocalSettings.php,
or from legacy extension PHP entry points). It is no longer
supported to use this variable to reliably read out a full view
of all extension credits (specifically those registered via
extension.json).
Doing so had the downside of adding processing cost to every
web request, as well as taking one the single largest portion
of the ExtensionRegistry APCu cache key, which in PHP7+ incurs
a linear cost for every string value, string key, of every
(sub)array in this huge structure; and does to on every request
just in case something reads from $wgExtensionCredits.
The new method to access this information reliably is owned
by SpecialVersion for now (could be moved elsewhere). This
also makes the merging logic more testable and incurs it on-demand
rather than upfront.
Details:
* Move 'type' internally from NOT_ATTRIBS to CREDIT_ATTRIBS.
These two arrays behave identically for most purposes (they are
both used to mean "don't export this as a global attribute").
By placing it in CREDIT_ATTRIBS it becomes complete and makes
it easy to refer to in docs. Previously, extractCredits()
read the 'type' key outside the loop for CREDIT_ATTRIBS.
* Remove redundant code in ApiBase.php, that is now more obviously
redundant. Looks like a left-over or merge conflict mistake
from when ExtensionRegistry was first introduced.
Bug: T187154
Change-Id: I6d66c58fbe57c530f9a43cae504b0d6aa4ffcd0d
Introduces $wgWatchlistExpiryMaxDuration which is used instead of given
expiry if the given exceeds it. This is done in the storage layer. The
reasoning is to control the size of the watchlist_expiry table. Hence,
the max duration does not apply to indefinite expiries (since that would
mean now row in watchlist_expiry).
The frontend is responsible for disallowing expiries greater than the
max, if it choses to do so.
APIs should now pass in $wgWatchlistExpiryMaxDuration as the PARAM_MAX
setting for the 'expiry' type. They should also set PARAM_USE_MAX so
that the maximum value is used if it is exceeded.
Other APIs that watch pages will be updated in separate patches
(see T248512 and T248514).
Bug: T249672
Change-Id: I811c444c36c1da1470f2d6e185404b6121a263eb
This converts user options management to a separate
service for use in DI context.
User options are accessed quite early on in installation
process and full-on options management depends on the
database. Prior we have protected from accessing the DB
by setting a hacky $wgUser with 0 id, and relying on the
implementation that it doesn't go into the database to
get the default user options. Now we can't really do that
since DBLoadBalancer is required to instantiate the options
manager. Instead, we redefine the options manager with
a DefaultOptionsManager, that only provides access to
default options and doesn't require DB access.
UserOptionsManager uses PreferencesFactory, however
injecting it will produce a cyclic dependency. The problem
is that we separate options to different kinds, which are
inferred from the PreferencesFactory declaration for those
options (e.g. if it's a radio button in the UI declaration,
the option is of multiselect kind). This is plain wrong,
the dependency should be wise versa. This will be addressed
separately, since it's requires larger refactoring. For now
the PreferencesFactory is obtained on demand. This will be
addressed in a followup.
Bug: T248527
Change-Id: I74917c5eaec184d188911a319895b941ed55ee87
Only support passing RevisionRecord or int, remove use of
Revision::newFromId
Bug: T249021
Bug: T249561
Change-Id: Id4a8f64f239d0664865056887fe0a11c7e468d5f
Disabling tidy has been deprecated since 1.33. This cleans up the code
paths which still used untidy output.
Bug: T198214
Change-Id: I821ef3b8f59b272d983583d407b2f0794fe1e791
Added timestamp props to ApiComparePages.php with value setting only
occuring when getTimestamp() does not return null. Added Appropriate
tests to ApiComparePagesTest.php
Bug: T247686
Change-Id: I15523d11741786f3c5d572a6cff79aef787af78f
This commit also changes ApiWatch to make use of the new parameter type.
Other APIs will be updated to use it in a separate patch (T248196).
In doing this, we are for the first using logic within a TypeDef outside
the API. This seems acceptable given TypeDefs chiefly appear to serve as
a validation method, with otherwise no particular logic tied to the
concept of APIs.
wfIsInfinity() now uses ExpiryDef::INFINITY_VALS
Bug: T248508
Change-Id: If8f0df059eafb73ec9f39cc076b3a9ce2412d60a
This has long been somewhat confusing, and it's more likely a client
will wind up looping due to a cookie handling bug than that the session
loss is a transient failure on the server side.
Bug: T249526
Change-Id: I3430eb4cb1b6d85d6869c3d78709236f04da10a3
With this commit, the action=watch API accepts an 'expiry' parameter,
analagous to the expiry accepted by action=userrights, action=block,
etc.
Bug: T245078
Change-Id: If37a772253082529cb290027da87098c1e6bf98c
Also fix PHPUnit 9 warning in PNGMetadataExtractorTest about $delta.
This should fix all of the integration test warning spam.
Bug: T244095
Change-Id: I0e2a76d5df2685ae5ad1498864e0b5f9db60c0cc
The old way of providing a callable to SkinFactory::register is
still supported. Those callables expected the skin name as their
first argument. Coincidentally, so does the constructor of Skin.
Some skins might not define any constructor parameters at all,
which is acceptable to PHP, as it will just discard the argument.
The registration using $wgValidSkinNames has not been changed,
and skins that want to define services to be injected will still
need to manually register their skin to the skin factory.
CodeSearch did not indicate any extensions or skins manually
constructing a SkinFactory in tests, but for posterity, the old
way of creating a SkinFactory for testing can be replaced with
new SkinFactory( new ObjectFactory(
$this->createMock( ContainerInterface::class )
) );
Note that the constructor for SkinFactory for internal use only,
in accordance with the Stable interface policy.
You should use MediaWikiServices::getInstance()->getSkinFactory
instead.
Bug: T244466
Change-Id: I8ba9d869bddd9b6124e47697b789d752c0620b02
These are not configuration but business logic, similar to the
canonical names that are in NamespaceInfo.php, these must always
exist and cannot be altered or unset.
They were previously unconditionally assigned during all requests
in Setup.php and passed down as "site configuration".
Changes:
* Move them to MessagesEn.php where they can be cached and
processed the same way as other core-provided aliases.
Document and confirm with tests that this is a mergeable
attribute that follows the language chain.
* Remove the duplicated code in a few places that was reading
this variable + Language::getNamespaceAliases(), to instead
just call the latter and move the logic there, centralised,
and tested.
In doing so I noticed that these were applied in an
inconsistent order. Sometimes the config won, sometimes not.
There's no obvious right or wrong way here, but I've chosen
to standardise on the way that Language::getNamespaceIds() did
it, which is that config wins. This because that method seems
to be most widely used of the three (it decides how URLs and
titles are parsed), and thus the one I least want to change
the behaviour of.
* Document that $wgNamespaceAliases may only be used to
define (extra) aliases, it is and never was a way to access
the complete list of aliases.
Bug: T189966
Change-Id: Ibb14181aba8c1b509264ed40523e9ab4000fd71a
This adds a baserevid parameter for detecting edit conflicts, as an
alternative to the less precise basetimestamp parameter. This is
introduced for parity with and use by the new REST api.
Bug: T230843
Bug: T34037
Change-Id: Id7565018f66860b5c2ba688777508db1b88700ae
* Avoid partial assertions using array subsets.
Instead, explicitly ignore the keys we want to ignore,
and then assert the array in full.
This way, newly added properties are explicitly detected
by the test, and it also automatically means that no bad
properties can be added. For example, properties like 'new',
'minor' and 'bot' express their meaning by sheer existence
and must never be tolerated to exist.
This was motivated by the many assertArraySubset() deprecation
warnings that were making the CI build output very noisy,
and thus it was difficult to quickly find real problems.
- For testNamespaceParam() I added rcprop=title, as it was
only asserting those keys. The alternative was to repeat
all the assertions for the overall output, which other tests
already did.
* Avoid using User::getName() or Title::getPrefixedText()
in the asserted expected value. Be explicit. This also
makes the test run considerably faster.
* Use 'tablesUsed' the way we normally do in MediaWiki unit
tests, by declaring the class member. (We never use
TestCase constructors.)
* Remove use of harcoded DB truncation for 'recentchanges'.
MediaWikiIntegrationTestCase does this already, which is what
`@group Database` and `tablesUsed` are for.
* Remove use of mutable TestUser, the user is never mutated.
This allows the internal registry to re-use the same instance.
* Remove use of assertArrayHasKey() where it only checked
something the test would immediately assert on the next line.
We already have PHPUnit configured in general to assert and
fail directly upon any undefined key access.
* Use sample names like Foo, Bar and Quux which are easier
to remember and distinguish than overly long and similar
titles with some word or number added at the end of them.
Change-Id: I8133e1199e3b1d053be7053795172891ad2bf48b