Merge "Http::getProxy() method to get proxy configuration"
[lhc/web/wiklou.git] / includes / page / WikiFilePage.php
1 <?php
2 /**
3 * Special handling for file pages.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 */
22
23 /**
24 * Special handling for file pages
25 *
26 * @ingroup Media
27 */
28 class WikiFilePage extends WikiPage {
29 /**
30 * @var File
31 */
32 protected $mFile = false;
33 protected $mRepo = null;
34 protected $mFileLoaded = false;
35 protected $mDupes = null;
36
37 public function __construct( $title ) {
38 parent::__construct( $title );
39 $this->mDupes = null;
40 $this->mRepo = null;
41 }
42
43 /**
44 * @param File $file
45 */
46 public function setFile( $file ) {
47 $this->mFile = $file;
48 $this->mFileLoaded = true;
49 }
50
51 /**
52 * @return bool
53 */
54 protected function loadFile() {
55 if ( $this->mFileLoaded ) {
56 return true;
57 }
58 $this->mFileLoaded = true;
59
60 $this->mFile = wfFindFile( $this->mTitle );
61 if ( !$this->mFile ) {
62 $this->mFile = wfLocalFile( $this->mTitle ); // always a File
63 }
64 $this->mRepo = $this->mFile->getRepo();
65 return true;
66 }
67
68 /**
69 * @return mixed|null|Title
70 */
71 public function getRedirectTarget() {
72 $this->loadFile();
73 if ( $this->mFile->isLocal() ) {
74 return parent::getRedirectTarget();
75 }
76 // Foreign image page
77 $from = $this->mFile->getRedirected();
78 $to = $this->mFile->getName();
79 if ( $from == $to ) {
80 return null;
81 }
82 $this->mRedirectTarget = Title::makeTitle( NS_FILE, $to );
83 return $this->mRedirectTarget;
84 }
85
86 /**
87 * @return bool|mixed|Title
88 */
89 public function followRedirect() {
90 $this->loadFile();
91 if ( $this->mFile->isLocal() ) {
92 return parent::followRedirect();
93 }
94 $from = $this->mFile->getRedirected();
95 $to = $this->mFile->getName();
96 if ( $from == $to ) {
97 return false;
98 }
99 return Title::makeTitle( NS_FILE, $to );
100 }
101
102 /**
103 * @return bool
104 */
105 public function isRedirect() {
106 $this->loadFile();
107 if ( $this->mFile->isLocal() ) {
108 return parent::isRedirect();
109 }
110
111 return (bool)$this->mFile->getRedirected();
112 }
113
114 /**
115 * @return bool
116 */
117 public function isLocal() {
118 $this->loadFile();
119 return $this->mFile->isLocal();
120 }
121
122 /**
123 * @return bool|File
124 */
125 public function getFile() {
126 $this->loadFile();
127 return $this->mFile;
128 }
129
130 /**
131 * @return array|null
132 */
133 public function getDuplicates() {
134 $this->loadFile();
135 if ( !is_null( $this->mDupes ) ) {
136 return $this->mDupes;
137 }
138 $hash = $this->mFile->getSha1();
139 if ( !( $hash ) ) {
140 $this->mDupes = [];
141 return $this->mDupes;
142 }
143 $dupes = RepoGroup::singleton()->findBySha1( $hash );
144 // Remove duplicates with self and non matching file sizes
145 $self = $this->mFile->getRepoName() . ':' . $this->mFile->getName();
146 $size = $this->mFile->getSize();
147
148 /**
149 * @var $file File
150 */
151 foreach ( $dupes as $index => $file ) {
152 $key = $file->getRepoName() . ':' . $file->getName();
153 if ( $key == $self ) {
154 unset( $dupes[$index] );
155 }
156 if ( $file->getSize() != $size ) {
157 unset( $dupes[$index] );
158 }
159 }
160 $this->mDupes = $dupes;
161 return $this->mDupes;
162 }
163
164 /**
165 * Override handling of action=purge
166 * @return bool
167 */
168 public function doPurge() {
169 $this->loadFile();
170 if ( $this->mFile->exists() ) {
171 wfDebug( 'ImagePage::doPurge purging ' . $this->mFile->getName() . "\n" );
172 DeferredUpdates::addUpdate( new HTMLCacheUpdate( $this->mTitle, 'imagelinks' ) );
173 $this->mFile->upgradeRow();
174 $this->mFile->purgeCache( [ 'forThumbRefresh' => true ] );
175 } else {
176 wfDebug( 'ImagePage::doPurge no image for '
177 . $this->mFile->getName() . "; limiting purge to cache only\n" );
178 // even if the file supposedly doesn't exist, force any cached information
179 // to be updated (in case the cached information is wrong)
180 $this->mFile->purgeCache( [ 'forThumbRefresh' => true ] );
181 }
182 if ( $this->mRepo ) {
183 // Purge redirect cache
184 $this->mRepo->invalidateImageRedirect( $this->mTitle );
185 }
186 return parent::doPurge();
187 }
188
189 /**
190 * Get the categories this file is a member of on the wiki where it was uploaded.
191 * For local files, this is the same as getCategories().
192 * For foreign API files (InstantCommons), this is not supported currently.
193 * Results will include hidden categories.
194 *
195 * @return TitleArray|Title[]
196 * @since 1.23
197 */
198 public function getForeignCategories() {
199 $this->loadFile();
200 $title = $this->mTitle;
201 $file = $this->mFile;
202
203 if ( !$file instanceof LocalFile ) {
204 wfDebug( __CLASS__ . '::' . __METHOD__ . " is not supported for this file\n" );
205 return TitleArray::newFromResult( new FakeResultWrapper( [] ) );
206 }
207
208 /** @var LocalRepo $repo */
209 $repo = $file->getRepo();
210 $dbr = $repo->getSlaveDB();
211
212 $res = $dbr->select(
213 [ 'page', 'categorylinks' ],
214 [
215 'page_title' => 'cl_to',
216 'page_namespace' => NS_CATEGORY,
217 ],
218 [
219 'page_namespace' => $title->getNamespace(),
220 'page_title' => $title->getDBkey(),
221 ],
222 __METHOD__,
223 [],
224 [ 'categorylinks' => [ 'INNER JOIN', 'page_id = cl_from' ] ]
225 );
226
227 return TitleArray::newFromResult( $res );
228 }
229 }