MediaWiki  master
BadFileLookup.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use BagOStuff;
11 use RepoGroup;
12 
15  private $listCallback;
16 
18  private $cache;
19 
21  private $repoGroup;
22 
24  private $titleParser;
25 
27  private $badFiles;
28 
30  private $hookRunner;
31 
41  public function __construct(
42  callable $listCallback,
43  BagOStuff $cache,
44  RepoGroup $repoGroup,
45  TitleParser $titleParser,
46  HookContainer $hookContainer
47  ) {
48  $this->listCallback = $listCallback;
49  $this->cache = $cache;
50  $this->repoGroup = $repoGroup;
51  $this->titleParser = $titleParser;
52  $this->hookRunner = new HookRunner( $hookContainer );
53  }
54 
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?
74  if ( $file ) {
75  $name = $file->getTitle()->getDBkey();
76  }
77 
78  // Run the extension hook
79  $bad = false;
80  if ( !$this->hookRunner->onBadImage( $name, $bad ) ) {
81  return (bool)$bad;
82  }
83 
84  if ( $this->badFiles === null ) {
85  $list = ( $this->listCallback )();
86  $key = $this->cache->makeKey( 'bad-image-list', sha1( $list ) );
87  $this->badFiles = $this->cache->getWithSetCallback(
88  $key,
89  BagOStuff::TTL_DAY,
90  function () use ( $list ) {
91  return $this->buildBadFilesList( $list );
92  }
93  );
94  }
95 
96  return isset( $this->badFiles[$name] ) && ( !$contextTitle ||
97  !isset( $this->badFiles[$name][$contextTitle->getNamespace()][$contextTitle->getDBkey()] ) );
98  }
99 
104  private function buildBadFilesList( string $list ): array {
105  $ret = [];
106  $lines = explode( "\n", $list );
107  foreach ( $lines as $line ) {
108  // List items only
109  if ( substr( $line, 0, 1 ) !== '*' ) {
110  continue;
111  }
112 
113  // Find all links
114  $m = [];
115  // XXX What is the ':?' doing in the regex? Why not let the TitleParser strip it?
116  if ( !preg_match_all( '/\[\[:?(.*?)\]\]/', $line, $m ) ) {
117  continue;
118  }
119 
120  $fileDBkey = null;
121  $exceptions = [];
122  foreach ( $m[1] as $i => $titleText ) {
123  try {
124  $title = $this->titleParser->parseTitle( $titleText );
125  } catch ( MalformedTitleException $e ) {
126  continue;
127  }
128  if ( $i == 0 ) {
129  $fileDBkey = $title->getDBkey();
130  } else {
131  $exceptions[$title->getNamespace()][$title->getDBkey()] = true;
132  }
133  }
134 
135  if ( $fileDBkey !== null ) {
136  $ret[$fileDBkey] = $exceptions;
137  }
138  }
139  return $ret;
140  }
141 }
142 
146 class_alias( BadFileLookup::class, 'MediaWiki\\BadFileLookup' );
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:85
Title string false $title
Definition: File.php:120
string null $name
The name of a file from its title object.
Definition: File.php:144
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:568
isBadFile( $name, LinkTarget $contextTitle=null)
Determine if a file exists on the 'bad image list'.
__construct(callable $listCallback, BagOStuff $cache, RepoGroup $repoGroup, TitleParser $titleParser, HookContainer $hookContainer)
Do not call directly.
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
Prioritized list of file repositories.
Definition: RepoGroup.php:30
Represents the target of a wiki link.
Definition: LinkTarget.php:30
A title parser service for MediaWiki.
Definition: TitleParser.php:35
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
if(!file_exists( $CREDITS)) $lines