6 use MalformedTitleException
;
7 use MediaWiki\HookContainer\HookContainer
;
8 use MediaWiki\HookContainer\HookRunner
;
9 use MediaWiki\Linker\LinkTarget
;
14 /** @var callable Returns contents of bad file list (see comment for isBadFile()) */
15 private $listCallback;
17 /** @var BagOStuff Cache of parsed bad image list */
23 /** @var TitleParser */
26 /** @var array|null Parsed bad file list */
29 /** @var HookRunner */
33 * Do not call directly. Use MediaWikiServices.
35 * @param callable $listCallback Callback that returns wikitext of a bad file list
36 * @param BagOStuff $cache For caching parsed versions of the bad file list
37 * @param RepoGroup $repoGroup
38 * @param TitleParser $titleParser
39 * @param HookContainer $hookContainer
41 public function __construct(
42 callable
$listCallback,
45 TitleParser
$titleParser,
46 HookContainer
$hookContainer
48 $this->listCallback
= $listCallback;
49 $this->cache
= $cache;
50 $this->repoGroup
= $repoGroup;
51 $this->titleParser
= $titleParser;
52 $this->hookRunner
= new HookRunner( $hookContainer );
56 * Determine if a file exists on the 'bad image list'.
58 * The format of MediaWiki:Bad_image_list is as follows:
59 * * Only list items (lines starting with "*") are considered
60 * * The first link on a line must be a link to a bad file
61 * * Any subsequent links on the same line are considered to be exceptions,
62 * i.e. articles where the file may occur inline.
64 * @param string $name The file name to check
65 * @param LinkTarget|null $contextTitle The page on which the file occurs, if known
68 public function isBadFile( $name, LinkTarget
$contextTitle = null ) {
69 // Handle redirects; callers almost always hit RepoGroup::findFile() anyway,
70 // so just use that method because it has a fast process cache.
71 $file = $this->repoGroup
->findFile( $name );
72 // XXX If we don't find the file we also don't replace spaces by underscores or otherwise
73 // validate or normalize the title, is this right?
75 $name = $file->getTitle()->getDBkey();
78 // Run the extension hook
80 if ( !$this->hookRunner
->onBadImage( $name, $bad ) ) {
84 if ( $this->badFiles
=== null ) {
85 // Not used before in this request, try the cache
86 $list = ( $this->listCallback
)();
87 $key = $this->cache
->makeKey( 'bad-image-list', sha1( $list ) );
88 $this->badFiles
= $this->cache
->get( $key ) ?
: null;
91 if ( $this->badFiles
=== null ) {
92 // Cache miss, build the list now
94 $lines = explode( "\n", $list );
95 foreach ( $lines as $line ) {
97 if ( substr( $line, 0, 1 ) !== '*' ) {
103 // XXX What is the ':?' doing in the regex? Why not let the TitleParser strip it?
104 if ( !preg_match_all( '/\[\[:?(.*?)\]\]/', $line, $m ) ) {
110 foreach ( $m[1] as $i => $titleText ) {
112 $title = $this->titleParser
->parseTitle( $titleText );
113 } catch ( MalformedTitleException
$e ) {
117 $fileDBkey = $title->getDBkey();
119 $exceptions[$title->getNamespace()][$title->getDBkey()] = true;
123 if ( $fileDBkey !== null ) {
124 $this->badFiles
[$fileDBkey] = $exceptions;
127 $this->cache
->set( $key, $this->badFiles
, 24 * 60 * 60 );
130 return isset( $this->badFiles
[$name] ) && ( !$contextTitle ||
131 !isset( $this->badFiles
[$name][$contextTitle->getNamespace()]
132 [$contextTitle->getDBkey()] ) );