9use MediaWiki\Cache\LinkBatchFactory;
14use MediaWiki\Languages\LanguageConverterFactory;
36 private $filename =
'';
43 private LinkBatchFactory $linkBatchFactory;
49 LinkBatchFactory $linkBatchFactory,
52 LanguageConverterFactory $languageConverterFactory
54 parent::__construct(
'FileDuplicateSearch' );
55 $this->linkBatchFactory = $linkBatchFactory;
56 $this->repoGroup = $repoGroup;
57 $this->searchEngineFactory = $searchEngineFactory;
58 $this->languageConverter = $languageConverterFactory->getLanguageConverter( $this->
getContentLanguage() );
66 private function getDupes() {
67 return $this->repoGroup->findBySha1( $this->hash );
73 private function showList( $dupes ) {
75 $html[] =
"<ol class='special'>";
77 foreach ( $dupes as $dupe ) {
78 $line = $this->formatResult( $dupe );
79 $html[] =
"<li>" . $line .
"</li>";
83 $this->
getOutput()->addHTML( implode(
"\n", $html ) );
91 $this->filename = $par ?? $this->
getRequest()->getText(
'filename' );
94 $title = Title::newFromText( $this->filename,
NS_FILE );
95 if ( $title && $title->getText() !=
'' ) {
96 $this->file = $this->repoGroup->findFile( $title );
101 # Create the input form
105 'name' =>
'filename',
106 'label-message' =>
'fileduplicatesearch-filename',
109 'default' => $this->filename,
112 $htmlForm = HTMLForm::factory(
'ooui', $formFields, $this->
getContext() );
114 $htmlForm->setMethod(
'get' );
115 $htmlForm->setSubmitTextMsg( $this->
msg(
'fileduplicatesearch-submit' ) );
119 $htmlForm->prepareForm()->displayForm(
false );
122 $this->hash = $this->file->getSha1();
123 } elseif ( $this->filename !==
'' ) {
125 "<p class='mw-fileduplicatesearch-noresults'>\n$1\n</p>",
130 if ( $this->hash !=
'' ) {
131 # Show a thumbnail of the file
134 $thumb = $img->transform( [
'width' => 120,
'height' => 120 ] );
136 $out->addModuleStyles(
'mediawiki.special' );
137 $out->addHTML(
'<div id="mw-fileduplicatesearch-icon">' .
138 $thumb->toHtml( [
'desc-link' =>
false ] ) .
'<br />' .
139 $this->msg(
'fileduplicatesearch-info' )
140 ->numParams( $img->getWidth(), $img->getHeight() )
141 ->sizeParams( $img->getSize() )
142 ->params( $img->getMimeType() )->parseAsBlock() .
147 $dupes = $this->getDupes();
148 $numRows = count( $dupes );
150 # Show a short summary
151 if ( $numRows == 1 ) {
153 "<p class='mw-fileduplicatesearch-result-1'>\n$1\n</p>",
156 } elseif ( $numRows ) {
158 "<p class='mw-fileduplicatesearch-result-n'>\n$1\n</p>",
164 $this->doBatchLookups( $dupes );
165 $this->showList( $dupes );
172 private function doBatchLookups( $list ) {
173 $batch = $this->linkBatchFactory->newLinkBatch()->setCaller( __METHOD__ );
174 foreach ( $list as $file ) {
175 $batch->addObj( $file->getTitle() );
176 if ( $file->isLocal() ) {
177 $uploader = $file->getUploader( File::FOR_THIS_USER, $this->
getAuthority() );
179 $batch->addUser( $uploader );
191 private function formatResult( $result ) {
193 $nt = $result->getTitle();
194 $text = $this->languageConverter->convert( $nt->getText() );
195 $plink = $linkRenderer->makeLink(
200 $uploader = $result->getUploader( File::FOR_THIS_USER, $this->
getAuthority() );
201 if ( $result->isLocal() && $uploader ) {
202 $user = Linker::userLink( $uploader->getId(), $uploader->getName() );
203 $user .=
'<span style="white-space: nowrap;">';
204 $user .= Linker::userToolLinks( $uploader->getId(), $uploader->getName() );
206 } elseif ( $uploader ) {
207 $user = htmlspecialchars( $uploader->getName() );
209 $user =
'<span class="history-deleted">'
210 . $this->
msg(
'rev-deleted-user' )->escaped() .
'</span>';
213 $time = htmlspecialchars( $this->
getLanguage()->userTimeAndDate(
214 $result->getTimestamp(), $this->getUser() ) );
216 return "$plink . . $user . . $time";
228 $title = Title::newFromText( $search,
NS_FILE );
229 if ( !$title || $title->getNamespace() !==
NS_FILE ) {
233 $searchEngine = $this->searchEngineFactory->create();
234 $searchEngine->setLimitOffset( $limit, $offset );
236 $searchEngine->setNamespaces( [
NS_FILE ] );
237 $result = $searchEngine->defaultPrefixSearch( $search );
239 return array_map(
static function (
Title $t ) {
241 return $t->getText();
252class_alias( SpecialFileDuplicateSearch::class,
'SpecialFileDuplicateSearch' );
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getPageTitle( $subpage=false)
Get a self-referential title object.
getContext()
Gets the context this SpecialPage is executed in.
getRequest()
Get the WebRequest being used for this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getAuthority()
Shortcut to get the Authority executing this instance.
getContentLanguage()
Shortcut to get content language.
getLanguage()
Shortcut to get user's language.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...