diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2008-08-15 01:29:47 +0200 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2008-08-15 01:29:47 +0200 |
commit | 370e83bb0dfd0c70de268c93bf07ad5ee0897192 (patch) | |
tree | 491674f4c242e4d6ba0d04eafa305174c35a3391 /includes/ImagePage.php | |
parent | f4debf0f12d0524d2b2427c55ea3f16b680fad97 (diff) |
Update auf 1.13.0
Diffstat (limited to 'includes/ImagePage.php')
-rw-r--r-- | includes/ImagePage.php | 647 |
1 files changed, 475 insertions, 172 deletions
diff --git a/includes/ImagePage.php b/includes/ImagePage.php index 573bc4d7..30fcf13e 100644 --- a/includes/ImagePage.php +++ b/includes/ImagePage.php @@ -1,34 +1,46 @@ <?php -/** - */ -/** - * - */ if( !defined( 'MEDIAWIKI' ) ) die( 1 ); /** * Special handling for image description pages * - * @addtogroup Media + * @ingroup Media */ class ImagePage extends Article { - /* private */ var $img; // Image object this page is shown for + /* private */ var $img; // Image object + /* private */ var $displayImg; /* private */ var $repo; + /* private */ var $fileLoaded; var $mExtraDescription = false; + var $dupes; - function __construct( $title, $time = false ) { + function __construct( $title ) { parent::__construct( $title ); - $this->img = wfFindFile( $this->mTitle, $time ); + $this->dupes = null; + $this->repo = null; + } + + protected function loadFile() { + if ( $this->fileLoaded ) { + return true; + } + $this->fileLoaded = true; + + $this->displayImg = $this->img = false; + wfRunHooks( 'ImagePageFindFile', array( $this, &$this->img, &$this->displayImg ) ); if ( !$this->img ) { - $this->img = wfLocalFile( $this->mTitle ); - $this->current = $this->img; - } else { - $this->current = $time ? wfLocalFile( $this->mTitle ) : $this->img; + $this->img = wfFindFile( $this->mTitle ); + if ( !$this->img ) { + $this->img = wfLocalFile( $this->mTitle ); + } + } + if ( !$this->displayImg ) { + $this->displayImg = $this->img; } - $this->repo = $this->img->repo; + $this->repo = $this->img->getRepo(); } /** @@ -38,11 +50,28 @@ class ImagePage extends Article { function render() { global $wgOut; $wgOut->setArticleBodyOnly( true ); - $wgOut->addSecondaryWikitext( $this->getContent() ); + parent::view(); } function view() { global $wgOut, $wgShowEXIF, $wgRequest, $wgUser; + $this->loadFile(); + + if ( $this->mTitle->getNamespace() == NS_IMAGE && $this->img->getRedirected() ) { + if ( $this->mTitle->getDBkey() == $this->img->getName() ) { + // mTitle is the same as the redirect target so ask Article + // to perform the redirect for us. + return Article::view(); + } else { + // mTitle is not the same as the redirect target so it is + // probably the redirect page itself. Fake the redirect symbol + $wgOut->setPageTitle( $this->mTitle->getPrefixedText() ); + $this->viewRedirect( Title::makeTitle( NS_IMAGE, $this->img->getName() ), + /* $appendSubtitle */ true, /* $forceKnown */ true ); + $this->viewUpdates(); + return; + } + } $diff = $wgRequest->getVal( 'diff' ); $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) ); @@ -50,16 +79,16 @@ class ImagePage extends Article { if ( $this->mTitle->getNamespace() != NS_IMAGE || ( isset( $diff ) && $diffOnly ) ) return Article::view(); - if ($wgShowEXIF && $this->img->exists()) { - // FIXME: bad interface, see note on MediaHandler::formatMetadata(). - $formattedMetadata = $this->img->formatMetadata(); + if ( $wgShowEXIF && $this->displayImg->exists() ) { + // FIXME: bad interface, see note on MediaHandler::formatMetadata(). + $formattedMetadata = $this->displayImg->formatMetadata(); $showmeta = $formattedMetadata !== false; } else { $showmeta = false; } - if ($this->img->exists()) - $wgOut->addHTML($this->showTOC($showmeta)); + if ( $this->displayImg->exists() ) + $wgOut->addHTML( $this->showTOC($showmeta) ); $this->openShowImage(); @@ -81,10 +110,23 @@ class ImagePage extends Article { $wgOut->addWikiText( $fol ); } $wgOut->addHTML( '<div id="shared-image-desc">' . $this->mExtraDescription . '</div>' ); + } else { + $this->checkSharedConflict(); } $this->closeShowImage(); $this->imageHistory(); + // TODO: Cleanup the following + + $wgOut->addHTML( Xml::element( 'h2', + array( 'id' => 'filelinks' ), + wfMsg( 'imagelinks' ) ) . "\n" ); + $this->imageDupes(); + // TODO: We may want to find local images redirecting to a foreign + // file: "The following local files redirect to this file" + if ( $this->img->isLocal() ) { + $this->imageRedirects(); + } $this->imageLinks(); if ( $showmeta ) { @@ -93,11 +135,83 @@ class ImagePage extends Article { $collapse = htmlspecialchars( wfEscapeJsString( wfMsg( 'metadata-collapse' ) ) ); $wgOut->addHTML( Xml::element( 'h2', array( 'id' => 'metadata' ), wfMsg( 'metadata' ) ). "\n" ); $wgOut->addWikiText( $this->makeMetadataTable( $formattedMetadata ) ); + $wgOut->addScriptFile( 'metadata.js' ); $wgOut->addHTML( - "<script type=\"text/javascript\" src=\"$wgStylePath/common/metadata.js?$wgStyleVersion\"></script>\n" . "<script type=\"text/javascript\">attachMetadataToggle('mw_metadata', '$expand', '$collapse');</script>\n" ); } } + + public function getRedirectTarget() { + $this->loadFile(); + if ( $this->img->isLocal() ) { + return parent::getRedirectTarget(); + } + // Foreign image page + $from = $this->img->getRedirected(); + $to = $this->img->getName(); + if ( $from == $to ) { + return null; + } + return $this->mRedirectTarget = Title::makeTitle( NS_IMAGE, $to ); + } + public function followRedirect() { + $this->loadFile(); + if ( $this->img->isLocal() ) { + return parent::followRedirect(); + } + $from = $this->img->getRedirected(); + $to = $this->img->getName(); + if ( $from == $to ) { + return false; + } + return Title::makeTitle( NS_IMAGE, $to ); + } + public function isRedirect( $text = false ) { + $this->loadFile(); + if ( $this->img->isLocal() ) + return parent::isRedirect( $text ); + + return (bool)$this->img->getRedirected(); + } + + public function isLocal() { + $this->loadFile(); + return $this->img->isLocal(); + } + + public function getFile() { + $this->loadFile(); + return $this->img; + } + + public function getDisplayedFile() { + $this->loadFile(); + return $this->displayImg; + } + + public function getDuplicates() { + $this->loadFile(); + if ( !is_null($this->dupes) ) { + return $this->dupes; + } + if ( !( $hash = $this->img->getSha1() ) ) { + return $this->dupes = array(); + } + $dupes = RepoGroup::singleton()->findBySha1( $hash ); + // Remove duplicates with self and non matching file sizes + $self = $this->img->getRepoName().':'.$this->img->getName(); + $size = $this->img->getSize(); + foreach ( $dupes as $index => $file ) { + $key = $file->getRepoName().':'.$file->getName(); + if ( $key == $self ) + unset( $dupes[$index] ); + if ( $file->getSize() != $size ) + unset( $dupes[$index] ); + } + return $this->dupes = $dupes; + + } + /** * Create the TOC @@ -121,7 +235,7 @@ class ImagePage extends Article { /** * Make a table with metadata to be shown in the output page. * - * FIXME: bad interface, see note on MediaHandler::formatMetadata(). + * FIXME: bad interface, see note on MediaHandler::formatMetadata(). * * @access private * @@ -148,11 +262,12 @@ class ImagePage extends Article { /** * Overloading Article's getContent method. - * + * * Omit noarticletext if sharedupload; text will be fetched from the * shared upload server if possible. */ function getContent() { + $this->loadFile(); if( $this->img && !$this->img->isLocal() && 0 == $this->getID() ) { return ''; } @@ -162,7 +277,9 @@ class ImagePage extends Article { function openShowImage() { global $wgOut, $wgUser, $wgImageLimits, $wgRequest, $wgLang, $wgContLang; - $full_url = $this->img->getURL(); + $this->loadFile(); + + $full_url = $this->displayImg->getURL(); $linkAttribs = false; $sizeSel = intval( $wgUser->getOption( 'imagesize') ); if( !isset( $wgImageLimits[$sizeSel] ) ) { @@ -181,7 +298,7 @@ class ImagePage extends Article { $sk = $wgUser->getSkin(); $dirmark = $wgContLang->getDirMark(); - if ( $this->img->exists() ) { + if ( $this->displayImg->exists() ) { # image $page = $wgRequest->getIntOrNull( 'page' ); if ( is_null( $page ) ) { @@ -190,22 +307,22 @@ class ImagePage extends Article { } else { $params = array( 'page' => $page ); } - $width_orig = $this->img->getWidth(); + $width_orig = $this->displayImg->getWidth(); $width = $width_orig; - $height_orig = $this->img->getHeight(); + $height_orig = $this->displayImg->getHeight(); $height = $height_orig; - $mime = $this->img->getMimeType(); + $mime = $this->displayImg->getMimeType(); $showLink = false; $linkAttribs = array( 'href' => $full_url ); - $longDesc = $this->img->getLongDesc(); + $longDesc = $this->displayImg->getLongDesc(); wfRunHooks( 'ImageOpenShowImageInlineBefore', array( &$this , &$wgOut ) ) ; - if ( $this->img->allowInlineDisplay() ) { + if ( $this->displayImg->allowInlineDisplay() ) { # image # "Download high res version" link below the image - #$msgsize = wfMsgHtml('file-info-size', $width_orig, $height_orig, $sk->formatSize( $this->img->getSize() ), $mime ); + #$msgsize = wfMsgHtml('file-info-size', $width_orig, $height_orig, $sk->formatSize( $this->displayImg->getSize() ), $mime ); # We'll show a thumbnail of this image if ( $width > $maxWidth || $height > $maxHeight ) { # Calculate the thumbnail size. @@ -226,43 +343,43 @@ class ImagePage extends Article { array( 'parseinline' ), $wgLang->formatNum( $width ), $wgLang->formatNum( $height ) ); } else { # Image is small enough to show full size on image page - $msgbig = htmlspecialchars( $this->img->getName() ); + $msgbig = htmlspecialchars( $this->displayImg->getName() ); $msgsmall = wfMsgExt( 'file-nohires', array( 'parseinline' ) ); } $params['width'] = $width; - $thumbnail = $this->img->transform( $params ); + $thumbnail = $this->displayImg->transform( $params ); $anchorclose = "<br />"; - if( $this->img->mustRender() ) { + if( $this->displayImg->mustRender() ) { $showLink = true; } else { - $anchorclose .= + $anchorclose .= $msgsmall . '<br />' . Xml::tags( 'a', $linkAttribs, $msgbig ) . "$dirmark " . $longDesc; } - if ( $this->img->isMultipage() ) { + if ( $this->displayImg->isMultipage() ) { $wgOut->addHTML( '<table class="multipageimage"><tr><td>' ); } if ( $thumbnail ) { - $options = array( - 'alt' => $this->img->getTitle()->getPrefixedText(), + $options = array( + 'alt' => $this->displayImg->getTitle()->getPrefixedText(), 'file-link' => true, ); - $wgOut->addHTML( '<div class="fullImageLink" id="file">' . + $wgOut->addHTML( '<div class="fullImageLink" id="file">' . $thumbnail->toHtml( $options ) . $anchorclose . '</div>' ); } - if ( $this->img->isMultipage() ) { - $count = $this->img->pageCount(); + if ( $this->displayImg->isMultipage() ) { + $count = $this->displayImg->pageCount(); if ( $page > 1 ) { $label = $wgOut->parse( wfMsg( 'imgmultipageprev' ), false ); $link = $sk->makeKnownLinkObj( $this->mTitle, $label, 'page='. ($page-1) ); - $thumb1 = $sk->makeThumbLinkObj( $this->mTitle, $this->img, $link, $label, 'none', + $thumb1 = $sk->makeThumbLinkObj( $this->mTitle, $this->displayImg, $link, $label, 'none', array( 'page' => $page - 1 ) ); } else { $thumb1 = ''; @@ -271,34 +388,42 @@ class ImagePage extends Article { if ( $page < $count ) { $label = wfMsg( 'imgmultipagenext' ); $link = $sk->makeKnownLinkObj( $this->mTitle, $label, 'page='. ($page+1) ); - $thumb2 = $sk->makeThumbLinkObj( $this->mTitle, $this->img, $link, $label, 'none', + $thumb2 = $sk->makeThumbLinkObj( $this->mTitle, $this->displayImg, $link, $label, 'none', array( 'page' => $page + 1 ) ); } else { $thumb2 = ''; } global $wgScript; - $select = '<form name="pageselector" action="' . - htmlspecialchars( $wgScript ) . - '" method="get" onchange="document.pageselector.submit();">' . - Xml::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ); - $select .= $wgOut->parse( wfMsg( 'imgmultigotopre' ), false ) . - ' <select id="pageselector" name="page">'; + + $formParams = array( + 'name' => 'pageselector', + 'action' => $wgScript, + 'onchange' => 'document.pageselector.submit();', + ); + + $option = array(); for ( $i=1; $i <= $count; $i++ ) { - $select .= Xml::option( $wgLang->formatNum( $i ), $i, - $i == $page ); + $options[] = Xml::option( $wgLang->formatNum($i), $i, $i == $page ); } - $select .= '</select>' . $wgOut->parse( wfMsg( 'imgmultigotopost' ), false ) . - '<input type="submit" value="' . - htmlspecialchars( wfMsg( 'imgmultigo' ) ) . '"></form>'; - - $wgOut->addHTML( '</td><td><div class="multipageimagenavbox">' . - "$select<hr />$thumb1\n$thumb2<br clear=\"all\" /></div></td></tr></table>" ); + $select = Xml::tags( 'select', + array( 'id' => 'pageselector', 'name' => 'page' ), + implode( "\n", $options ) ); + + $wgOut->addHTML( + '</td><td><div class="multipageimagenavbox">' . + Xml::openElement( 'form', $formParams ) . + Xml::hidden( 'title', $this->getTitle()->getPrefixedDbKey() ) . + wfMsgExt( 'imgmultigoto', array( 'parseinline', 'replaceafter' ), $select ) . + Xml::submitButton( wfMsg( 'imgmultigo' ) ) . + Xml::closeElement( 'form' ) . + "<hr />$thumb1\n$thumb2<br clear=\"all\" /></div></td></tr></table>" + ); } } else { #if direct link is allowed but it's not a renderable image, show an icon. - if ($this->img->isSafeFile()) { - $icon= $this->img->iconThumb(); + if ( $this->displayImg->isSafeFile() ) { + $icon= $this->displayImg->iconThumb(); $wgOut->addHTML( '<div class="fullImageLink" id="file">' . $icon->toHtml( array( 'desc-link' => true ) ) . @@ -310,9 +435,9 @@ class ImagePage extends Article { if ($showLink) { - $filename = wfEscapeWikiText( $this->img->getName() ); + $filename = wfEscapeWikiText( $this->displayImg->getName() ); - if (!$this->img->isSafeFile()) { + if ( !$this->displayImg->isSafeFile() ) { $warning = wfMsgNoTrans( 'mediawarning' ); $wgOut->addWikiText( <<<EOT <div class="fullMedia"> @@ -333,7 +458,7 @@ EOT } } - if(!$this->img->isLocal()) { + if( !$this->displayImg->isLocal() ) { $this->printSharedImageText(); } } else { @@ -341,31 +466,90 @@ EOT $title = SpecialPage::getTitleFor( 'Upload' ); $link = $sk->makeKnownLinkObj($title, wfMsgHtml('noimage-linktext'), - 'wpDestFile=' . urlencode( $this->img->getName() ) ); + 'wpDestFile=' . urlencode( $this->displayImg->getName() ) ); $wgOut->addHTML( wfMsgWikiHtml( 'noimage', $link ) ); } } + /** + * Show a notice that the file is from a shared repository + */ function printSharedImageText() { global $wgOut, $wgUser; + $this->loadFile(); + $descUrl = $this->img->getDescriptionUrl(); $descText = $this->img->getDescriptionText(); - $s = "<div class='sharedUploadNotice'>" . wfMsgWikiHtml("sharedupload"); - if ( $descUrl && !$descText) { + $s = "<div class='sharedUploadNotice'>" . wfMsgWikiHtml( 'sharedupload' ); + if ( $descUrl ) { $sk = $wgUser->getSkin(); - $link = $sk->makeExternalLink( $descUrl, wfMsg('shareduploadwiki-linktext') ); - $s .= " " . wfMsgWikiHtml('shareduploadwiki', $link); + $link = $sk->makeExternalLink( $descUrl, wfMsg( 'shareduploadwiki-linktext' ) ); + $msg = ( $descText ) ? 'shareduploadwiki-desc' : 'shareduploadwiki'; + $msg = wfMsgExt( $msg, array( 'parseinline', 'replaceafter' ), $link ); + if ( $msg != '-' ) { + # Show message only if not voided by local sysops + $s .= $msg; + } } $s .= "</div>"; - $wgOut->addHTML($s); + $wgOut->addHTML( $s ); if ( $descText ) { $this->mExtraDescription = $descText; } } + /* + * Check for files with the same name on the foreign repos. + */ + function checkSharedConflict() { + global $wgOut, $wgUser; + + $repoGroup = RepoGroup::singleton(); + if( !$repoGroup->hasForeignRepos() ) { + return; + } + + $this->loadFile(); + if( !$this->img->isLocal() ) { + return; + } + + $this->dupFile = null; + $repoGroup->forEachForeignRepo( array( $this, 'checkSharedConflictCallback' ) ); + + if( !$this->dupFile ) + return; + $dupfile = $this->dupFile; + $same = ( + ($this->img->getSha1() == $dupfile->getSha1()) && + ($this->img->getSize() == $dupfile->getSize()) + ); + + $sk = $wgUser->getSkin(); + $descUrl = $dupfile->getDescriptionUrl(); + if( $same ) { + $link = $sk->makeExternalLink( $descUrl, wfMsg( 'shareduploadduplicate-linktext' ) ); + $wgOut->addHTML( '<div id="shared-image-dup">' . wfMsgWikiHtml( 'shareduploadduplicate', $link ) . '</div>' ); + } else { + $link = $sk->makeExternalLink( $descUrl, wfMsg( 'shareduploadconflict-linktext' ) ); + $wgOut->addHTML( '<div id="shared-image-conflict">' . wfMsgWikiHtml( 'shareduploadconflict', $link ) . '</div>' ); + } + } + + function checkSharedConflictCallback( $repo ) { + $this->loadFile(); + $dupfile = $repo->newFile( $this->img->getTitle() ); + if( $dupfile && $dupfile->exists() ) { + $this->dupFile = $dupfile; + return $dupfile->exists(); + } + return false; + } + function getUploadUrl() { + $this->loadFile(); $uploadTitle = SpecialPage::getTitleFor( 'Upload' ); return $uploadTitle->getFullUrl( 'wpDestFile=' . urlencode( $this->img->getName() ) ); } @@ -377,23 +561,28 @@ EOT function uploadLinksBox() { global $wgUser, $wgOut; + $this->loadFile(); if( !$this->img->isLocal() ) return; $sk = $wgUser->getSkin(); - + $wgOut->addHtml( '<br /><ul>' ); - + # "Upload a new version of this file" link if( UploadForm::userCanReUpload($wgUser,$this->img->name) ) { $ulink = $sk->makeExternalLink( $this->getUploadUrl(), wfMsg( 'uploadnewversion-linktext' ) ); $wgOut->addHtml( "<li><div class='plainlinks'>{$ulink}</div></li>" ); } - + + # Link to Special:FileDuplicateSearch + $dupeLink = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'FileDuplicateSearch', $this->mTitle->getDBkey() ), wfMsgHtml( 'imagepage-searchdupe' ) ); + $wgOut->addHtml( "<li>{$dupeLink}</li>" ); + # External editing link $elink = $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'edit-externally' ), 'action=edit&externaledit=true&mode=file' ); $wgOut->addHtml( '<li>' . $elink . '<div>' . wfMsgWikiHtml( 'edit-externally-help' ) . '</div></li>' ); - + $wgOut->addHtml( '</ul>' ); } @@ -409,29 +598,20 @@ EOT */ function imageHistory() { - global $wgUser, $wgOut, $wgUseExternalEditor; - - $sk = $wgUser->getSkin(); + global $wgOut, $wgUseExternalEditor; + $this->loadFile(); if ( $this->img->exists() ) { - $list = new ImageHistoryList( $sk, $this->current ); - $file = $this->current; + $list = new ImageHistoryList( $this ); + $file = $this->img; $dims = $file->getDimensionsString(); - $s = $list->beginImageHistoryList() . - $list->imageHistoryLine( true, wfTimestamp(TS_MW, $file->getTimestamp()), - $this->mTitle->getDBkey(), $file->getUser('id'), - $file->getUser('text'), $file->getSize(), $file->getDescription(), - $dims - ); - + $s = $list->beginImageHistoryList(); + $s .= $list->imageHistoryLine( true, $file ); + // old image versions $hist = $this->img->getHistory(); foreach( $hist as $file ) { $dims = $file->getDimensionsString(); - $s .= $list->imageHistoryLine( false, wfTimestamp(TS_MW, $file->getTimestamp()), - $file->getArchiveName(), $file->getUser('id'), - $file->getUser('text'), $file->getSize(), $file->getDescription(), - $dims - ); + $s .= $list->imageHistoryLine( false, $file ); } $s .= $list->endImageHistoryList(); } else { $s=''; } @@ -451,37 +631,97 @@ EOT { global $wgUser, $wgOut; - $wgOut->addHTML( Xml::element( 'h2', array( 'id' => 'filelinks' ), wfMsg( 'imagelinks' ) ) . "\n" ); + $limit = 100; $dbr = wfGetDB( DB_SLAVE ); - $page = $dbr->tableName( 'page' ); - $imagelinks = $dbr->tableName( 'imagelinks' ); - $sql = "SELECT page_namespace,page_title FROM $imagelinks,$page WHERE il_to=" . - $dbr->addQuotes( $this->mTitle->getDBkey() ) . " AND il_from=page_id"; - $sql = $dbr->limitResult($sql, 500, 0); - $res = $dbr->query( $sql, "ImagePage::imageLinks" ); - - if ( 0 == $dbr->numRows( $res ) ) { - $wgOut->addHtml( '<p>' . wfMsg( "nolinkstoimage" ) . "</p>\n" ); + $res = $dbr->select( + array( 'imagelinks', 'page' ), + array( 'page_namespace', 'page_title' ), + array( 'il_to' => $this->mTitle->getDBkey(), 'il_from = page_id' ), + __METHOD__, + array( 'LIMIT' => $limit + 1) + ); + $count = $dbr->numRows( $res ); + if ( $count == 0 ) { + $wgOut->addHTML( "<div id='mw-imagepage-nolinkstoimage'>\n" ); + $wgOut->addWikiMsg( 'nolinkstoimage' ); + $wgOut->addHTML( "</div>\n" ); return; } - $wgOut->addHTML( '<p>' . wfMsg( 'linkstoimage' ) . "</p>\n<ul>" ); + $wgOut->addHTML( "<div id='mw-imagepage-section-linkstoimage'>\n" ); + $wgOut->addWikiMsg( 'linkstoimage', $count ); + $wgOut->addHTML( "<ul class='mw-imagepage-linktoimage'>\n" ); + + $sk = $wgUser->getSkin(); + $count = 0; + while ( $s = $res->fetchObject() ) { + $count++; + if ( $count <= $limit ) { + // We have not yet reached the extra one that tells us there is more to fetch + $name = Title::makeTitle( $s->page_namespace, $s->page_title ); + $link = $sk->makeKnownLinkObj( $name, "" ); + $wgOut->addHTML( "<li>{$link}</li>\n" ); + } + } + $wgOut->addHTML( "</ul></div>\n" ); + $res->free(); + + // Add a links to [[Special:Whatlinkshere]] + if ( $count > $limit ) + $wgOut->addWikiMsg( 'morelinkstoimage', $this->mTitle->getPrefixedDBkey() ); + } + + function imageRedirects() + { + global $wgUser, $wgOut; + + $redirects = $this->getTitle()->getRedirectsHere( NS_IMAGE ); + if ( count( $redirects ) == 0 ) return; + + $wgOut->addHTML( "<div id='mw-imagepage-section-redirectstofile'>\n" ); + $wgOut->addWikiMsg( 'redirectstofile', count( $redirects ) ); + $wgOut->addHTML( "<ul class='mw-imagepage-redirectstofile'>\n" ); + + $sk = $wgUser->getSkin(); + foreach ( $redirects as $title ) { + $link = $sk->makeKnownLinkObj( $title, "", "redirect=no" ); + $wgOut->addHTML( "<li>{$link}</li>\n" ); + } + $wgOut->addHTML( "</ul></div>\n" ); + + } + + function imageDupes() { + global $wgOut, $wgUser; + + $this->loadFile(); + + $dupes = $this->getDuplicates(); + if ( count( $dupes ) == 0 ) return; + + $wgOut->addHTML( "<div id='mw-imagepage-section-duplicates'>\n" ); + $wgOut->addWikiMsg( 'duplicatesoffile', count( $dupes ) ); + $wgOut->addHTML( "<ul class='mw-imagepage-duplicates'>\n" ); $sk = $wgUser->getSkin(); - while ( $s = $dbr->fetchObject( $res ) ) { - $name = Title::MakeTitle( $s->page_namespace, $s->page_title ); - $link = $sk->makeKnownLinkObj( $name, "" ); + foreach ( $dupes as $file ) { + if ( $file->isLocal() ) + $link = $sk->makeKnownLinkObj( $file->getTitle(), "" ); + else + $link = $sk->makeExternalLink( $file->getDescriptionUrl(), + $file->getTitle()->getPrefixedText() ); $wgOut->addHTML( "<li>{$link}</li>\n" ); } - $wgOut->addHTML( "</ul>\n" ); + $wgOut->addHTML( "</ul></div>\n" ); } /** * Delete the file, or an earlier version of it */ public function delete() { - if( !$this->img->exists() || !$this->img->isLocal() ) { + $this->loadFile(); + if( !$this->img->exists() || !$this->img->isLocal() || $this->img->getRedirected() ) { // Standard article deletion Article::delete(); return; @@ -494,14 +734,16 @@ EOT * Revert the file to an earlier version */ public function revert() { + $this->loadFile(); $reverter = new FileRevertForm( $this->img ); $reverter->execute(); } - + /** * Override handling of action=purge */ function doPurge() { + $this->loadFile(); if( $this->img->exists() ) { wfDebug( "ImagePage::doPurge purging " . $this->img->getName() . "\n" ); $update = new HTMLCacheUpdate( $this->mTitle, 'imagelinks' ); @@ -531,16 +773,31 @@ EOT /** * Builds the image revision log shown on image pages * - * @addtogroup Media + * @ingroup Media */ class ImageHistoryList { - protected $img, $skin, $title, $repo; + protected $imagePage, $img, $skin, $title, $repo; + + public function __construct( $imagePage ) { + global $wgUser; + $this->skin = $wgUser->getSkin(); + $this->current = $imagePage->getFile(); + $this->img = $imagePage->getDisplayedFile(); + $this->title = $imagePage->getTitle(); + $this->imagePage = $imagePage; + } + + function getImagePage() { + return $this->imagePage; + } - public function __construct( $skin, $img ) { - $this->skin = $skin; - $this->img = $img; - $this->title = $img->getTitle(); + function getSkin() { + return $this->skin; + } + + function getFile() { + return $this->img; } public function beginImageHistoryList() { @@ -549,12 +806,11 @@ class ImageHistoryList { . $wgOut->parse( wfMsgNoTrans( 'filehist-help' ) ) . Xml::openElement( 'table', array( 'class' => 'filehistory' ) ) . "\n" . '<tr><td></td>' - . ( $this->img->isLocal() && $wgUser->isAllowed( 'delete' ) ? '<td></td>' : '' ) + . ( $this->current->isLocal() && ($wgUser->isAllowed('delete') || $wgUser->isAllowed('deleterevision') ) ? '<td></td>' : '' ) . '<th>' . wfMsgHtml( 'filehist-datetime' ) . '</th>' - . '<th>' . wfMsgHtml( 'filehist-user' ) . '</th>' . '<th>' . wfMsgHtml( 'filehist-dimensions' ) . '</th>' - . '<th class="mw-imagepage-filesize">' . wfMsgHtml( 'filehist-filesize' ) . '</th>' - . '<th>' . wfMsgHtml( 'filehist-comment' ) . '</th>' + . '<th>' . wfMsgHtml( 'filehist-user' ) . '</th>' + . '<th>' . wfMsgHtml( 'filehist-comment' ) . '</th>' . "</tr>\n"; } @@ -562,36 +818,57 @@ class ImageHistoryList { return "</table>\n"; } - /** - * Create one row of file history - * - * @param bool $iscur is this the current file version? - * @param string $timestamp timestamp of file version - * @param string $img filename - * @param int $user ID of uploading user - * @param string $usertext username of uploading user - * @param int $size size of file version - * @param string $description description of file version - * @param string $dims dimensions of file version - * @return string a HTML formatted table row - */ - public function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description, $dims ) { - global $wgUser, $wgLang, $wgContLang; - $local = $this->img->isLocal(); - $row = ''; + public function imageHistoryLine( $iscur, $file ) { + global $wgUser, $wgLang, $wgContLang, $wgTitle; + + $timestamp = wfTimestamp(TS_MW, $file->getTimestamp()); + $img = $iscur ? $file->getName() : $file->getArchiveName(); + $user = $file->getUser('id'); + $usertext = $file->getUser('text'); + $size = $file->getSize(); + $description = $file->getDescription(); + $dims = $file->getDimensionsString(); + $sha1 = $file->getSha1(); + + $local = $this->current->isLocal(); + $row = $css = $selected = ''; // Deletion link - if( $local && $wgUser->isAllowed( 'delete' ) ) { + if( $local && ($wgUser->isAllowed('delete') || $wgUser->isAllowed('deleterevision') ) ) { $row .= '<td>'; - $q = array(); - $q[] = 'action=delete'; - if( !$iscur ) - $q[] = 'oldimage=' . urlencode( $img ); - $row .= $this->skin->makeKnownLinkObj( - $this->title, - wfMsgHtml( $iscur ? 'filehist-deleteall' : 'filehist-deleteone' ), - implode( '&', $q ) - ); + # Link to remove from history + if( $wgUser->isAllowed( 'delete' ) ) { + $q = array(); + $q[] = 'action=delete'; + if( !$iscur ) + $q[] = 'oldimage=' . urlencode( $img ); + $row .= $this->skin->makeKnownLinkObj( + $this->title, + wfMsgHtml( $iscur ? 'filehist-deleteall' : 'filehist-deleteone' ), + implode( '&', $q ) + ); + } + # Link to hide content + if( $wgUser->isAllowed( 'deleterevision' ) ) { + if( $wgUser->isAllowed('delete') ) { + $row .= '<br/>'; + } + $revdel = SpecialPage::getTitleFor( 'Revisiondelete' ); + // If file is top revision or locked from this user, don't link + if( $iscur || !$file->userCan(File::DELETED_RESTRICTED) ) { + $del = wfMsgHtml( 'rev-delundel' ); + } else { + // If the file was hidden, link to sha-1 + list($ts,$name) = explode('!',$img,2); + $del = $this->skin->makeKnownLinkObj( $revdel, wfMsg( 'rev-delundel' ), + 'target=' . urlencode( $wgTitle->getPrefixedText() ) . + '&oldimage=' . urlencode( $ts ) ); + // Bolden oversighted content + if( $file->isDeleted(File::DELETED_RESTRICTED) ) + $del = "<strong>$del</strong>"; + } + $row .= "<tt style='white-space: nowrap;'><small>$del</small></tt>"; + } $row .= '</td>'; } @@ -600,47 +877,73 @@ class ImageHistoryList { if( $iscur ) { $row .= wfMsgHtml( 'filehist-current' ); } elseif( $local && $wgUser->isLoggedIn() && $this->title->userCan( 'edit' ) ) { - $q = array(); - $q[] = 'action=revert'; - $q[] = 'oldimage=' . urlencode( $img ); - $q[] = 'wpEditToken=' . urlencode( $wgUser->editToken( $img ) ); - $row .= $this->skin->makeKnownLinkObj( - $this->title, - wfMsgHtml( 'filehist-revert' ), - implode( '&', $q ) - ); + if( $file->isDeleted(File::DELETED_FILE) ) { + $row .= wfMsgHtml('filehist-revert'); + } else { + $q = array(); + $q[] = 'action=revert'; + $q[] = 'oldimage=' . urlencode( $img ); + $q[] = 'wpEditToken=' . urlencode( $wgUser->editToken( $img ) ); + $row .= $this->skin->makeKnownLinkObj( $this->title, + wfMsgHtml( 'filehist-revert' ), + implode( '&', $q ) ); + } } $row .= '</td>'; // Date/time and image link - $row .= '<td>'; - $url = $iscur ? $this->img->getUrl() : $this->img->getArchiveUrl( $img ); - $row .= Xml::element( - 'a', - array( 'href' => $url ), - $wgLang->timeAndDate( $timestamp, true ) - ); - $row .= '</td>'; + if( $file->getTimestamp() === $this->img->getTimestamp() ) { + $selected = "class='filehistory-selected'"; + } + $row .= "<td $selected style='white-space: nowrap;'>"; + if( !$file->userCan(File::DELETED_FILE) ) { + # Don't link to unviewable files + $row .= '<span class="history-deleted">' . $wgLang->timeAndDate( $timestamp, true ) . '</span>'; + } else if( $file->isDeleted(File::DELETED_FILE) ) { + $revdel = SpecialPage::getTitleFor( 'Revisiondelete' ); + # Make a link to review the image + $url = $this->skin->makeKnownLinkObj( $revdel, $wgLang->timeAndDate( $timestamp, true ), + "target=".$wgTitle->getPrefixedText()."&file=$sha1.".$this->current->getExtension() ); + $row .= '<span class="history-deleted">'.$url.'</span>'; + } else { + $url = $iscur ? $this->current->getUrl() : $this->current->getArchiveUrl( $img ); + $row .= Xml::element( 'a', array( 'href' => $url ), $wgLang->timeAndDate( $timestamp, true ) ); + } + + $row .= "</td><td>"; + + // Image dimensions + $row .= htmlspecialchars( $dims ); + + // File size + $row .= " <span style='white-space: nowrap;'>(" . $this->skin->formatSize( $size ) . ')</span>'; // Uploading user - $row .= '<td>'; + $row .= '</td><td>'; if( $local ) { - $row .= $this->skin->userLink( $user, $usertext ) . $this->skin->userToolLinks( $user, $usertext ); + // Hide deleted usernames + if( $file->isDeleted(File::DELETED_USER) ) { + $row .= '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>'; + } else { + $row .= $this->skin->userLink( $user, $usertext ) . " <span style='white-space: nowrap;'>" . + $this->skin->userToolLinks( $user, $usertext ) . "</span>"; + } } else { $row .= htmlspecialchars( $usertext ); } - $row .= '</td>'; + $row .= '</td><td>'; - // Image dimensions - $row .= '<td>' . htmlspecialchars( $dims ) . '</td>'; - - // File size - $row .= '<td class="mw-imagepage-filesize">' . $this->skin->formatSize( $size ) . '</td>'; + // Don't show deleted descriptions + if ( $file->isDeleted(File::DELETED_COMMENT) ) { + $row .= '<span class="history-deleted">' . wfMsgHtml('rev-deleted-comment') . '</span>'; + } else { + $row .= $this->skin->commentBlock( $description, $this->title ); + } + $row .= '</td>'; - // Comment - $row .= '<td>' . $this->skin->formatComment( $description, $this->title ) . '</td>'; + wfRunHooks( 'ImagePageFileHistoryLine', array( $this, $file, &$row, &$rowClass ) ); + $classAttr = $rowClass ? " class='$rowClass'" : ""; - return "<tr>{$row}</tr>\n"; + return "<tr{$classAttr}>{$row}</tr>\n"; } - } |