r76198 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r76197‎ | r76198 | r76199 >
Date:16:29, 6 November 2010
Author:demon
Status:deferred
Tags:
Comment:
Came across this extension by chance and decided to give it a code style update. TBH: I'm not even sure it works with trunk MW right now. Plus a whole bunch of calling non static methods statically
Modified paths:
  • /trunk/extensions/NSFileRepo/NSFileRepo.php (modified) (history)
  • /trunk/extensions/NSFileRepo/NSFileRepo_body.php (added) (history)

Diff [purge]

Index: trunk/extensions/NSFileRepo/NSFileRepo_body.php
@@ -0,0 +1,429 @@
 2+<?php
 3+
 4+/**
 5+ * Class definitions for NSFileRepo
 6+ */
 7+
 8+class NSLocalRepo extends LocalRepo {
 9+ var $fileFactory = array( 'NSLocalFile', 'newFromTitle' );
 10+ var $oldFileFactory = array( 'NSOldLocalFile', 'newFromTitle' );
 11+ var $fileFromRowFactory = array( 'NSLocalFile', 'newFromRow' );
 12+ var $oldFileFromRowFactory = array( 'NSOldLocalFile', 'newFromRow' );
 13+
 14+ static function getHashPathForLevel( $name, $levels ) {
 15+ global $wgContLang;
 16+ $bits = explode( ':',$name );
 17+ $filename = $bits[ count( $bits ) - 1 ];
 18+ $path = parent::getHashPathForLevel( $filename, $levels );
 19+ return count( $bits ) > 1 ?
 20+ $wgContLang->getNsIndex( $bits[0] ) .'/'. $path : $path;
 21+ }
 22+
 23+ /**
 24+ * Get a relative path including trailing slash, e.g. f/fa/
 25+ * If the repo is not hashed, returns an empty string
 26+ * This is needed because self:: will call parent if not included - exact same as in FSRepo
 27+ */
 28+ function getHashPath( $name ) {
 29+ return self::getHashPathForLevel( $name, $this->hashLevels );
 30+ }
 31+
 32+ /**
 33+ * Pick a random name in the temp zone and store a file to it.
 34+ * @param string $originalName The base name of the file as specified
 35+ * by the user. The file extension will be maintained.
 36+ * @param string $srcPath The current location of the file.
 37+ * @return FileRepoStatus object with the URL in the value.
 38+ */
 39+ function storeTemp( $originalName, $srcPath ) {
 40+ $date = gmdate( "YmdHis" );
 41+ $hashPath = $this->getHashPath( $originalName );
 42+ $filename = $this->getFileNameStripped( $originalName );
 43+ $dstRel = "$hashPath$date!$filename";
 44+ $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $filename );
 45+ $result = $this->store( $srcPath, 'temp', $dstRel );
 46+ $result->value = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;
 47+ return $result;
 48+ }
 49+
 50+ function getFileNameStripped($suffix) {
 51+ return(NSLocalFile::getFileNameStripped($suffix));
 52+ }
 53+}
 54+
 55+class NSLocalFile extends LocalFile {
 56+ /**
 57+ * Get the path of the file relative to the public zone root
 58+ */
 59+ function getRel() {
 60+ return $this->getHashPath() . $this->getFileNameStripped( $this->getName() );
 61+ }
 62+
 63+ /**
 64+ * Get urlencoded relative path of the file
 65+ */
 66+ function getUrlRel() {
 67+ return $this->getHashPath() .
 68+ rawurlencode( $this->getFileNameStripped( $this->getName() ) );
 69+ }
 70+
 71+ /** Get the URL of the thumbnail directory, or a particular file if $suffix is specified */
 72+ function getThumbUrl( $suffix = false ) {
 73+ $path = $this->repo->getZoneUrl('thumb') . '/' . $this->getUrlRel();
 74+ if ( $suffix !== false ) {
 75+ $path .= '/' . rawurlencode( $this->getFileNameStripped( $suffix ) );
 76+ }
 77+ return $path;
 78+ }
 79+
 80+
 81+ /** Return the file name of a thumbnail with the specified parameters */
 82+ function thumbName( $params ) {
 83+ if ( !$this->getHandler() ) {
 84+ return null;
 85+ }
 86+ $extension = $this->getExtension();
 87+ list( $thumbExt, $thumbMime ) = $this->handler->getThumbType( $extension, $this->getMimeType() );
 88+/* This is the part that changed from LocalFile */
 89+ $thumbName = $this->handler->makeParamString( $params ) . '-' . $this->getFileNameStripped( $this->getName() );
 90+/* End of changes */
 91+ if ( $thumbExt != $extension ) {
 92+ $thumbName .= ".$thumbExt";
 93+ }
 94+ $bits = explode( ':',$this->getName() );
 95+ if ( count($bits) > 1 ) $thumbName = $bits[0] . ":" . $thumbName;
 96+ return $thumbName;
 97+ }
 98+
 99+
 100+ /** Get the path of the thumbnail directory, or a particular file if $suffix is specified */
 101+ function getThumbPath( $suffix = false ) {
 102+ $path = $this->repo->getZonePath('thumb') . '/' . $this->getRel();
 103+ if ( $suffix !== false ) {
 104+ $path .= '/' . $this->getFileNameStripped( $suffix );
 105+ }
 106+ return $path;
 107+ }
 108+
 109+ /** Get the relative path for an archive file */
 110+ function getArchiveRel( $suffix = false ) {
 111+ $path = 'archive/' . $this->getHashPath();
 112+ if ( $suffix === false ) {
 113+ $path = substr( $path, 0, -1 );
 114+ } else {
 115+ $path .= $this->getFileNameStripped( $suffix );
 116+ }
 117+ return $path;
 118+ }
 119+
 120+ /** Get the URL of the archive directory, or a particular file if $suffix is specified */
 121+ function getArchiveUrl( $suffix = false ) {
 122+ $path = $this->repo->getZoneUrl( 'public' ) . '/archive/' . $this->getHashPath();
 123+ if ( $suffix === false ) {
 124+ $path = substr( $path, 0, -1 );
 125+ } else {
 126+ $path .= rawurlencode( $this->getFileNameStripped( $suffix ) );
 127+ }
 128+ return $path;
 129+ }
 130+
 131+ /** Get the virtual URL for an archive file or directory */
 132+ function getArchiveVirtualUrl( $suffix = false ) {
 133+ $path = $this->repo->getVirtualUrl() . '/public/archive/' . $this->getHashPath();
 134+ if ( $suffix === false ) {
 135+ $path = substr( $path, 0, -1 );
 136+ } else {
 137+ $path .= rawurlencode( $this->getFileNameStripped( $suffix ) );
 138+ }
 139+ return $path;
 140+ }
 141+
 142+ /** Get the virtual URL for a thumbnail file or directory */
 143+ function getThumbVirtualUrl( $suffix = false ) {
 144+ $path = $this->repo->getVirtualUrl() . '/thumb/' . $this->getUrlRel();
 145+ if ( $suffix !== false ) {
 146+ $path .= '/' . rawurlencode( $this->getFileNameStripped( $suffix ) );
 147+ }
 148+ return $path;
 149+ }
 150+
 151+ /** Get the virtual URL for the file itself */
 152+ function getVirtualUrl( $suffix = false ) {
 153+ $path = $this->repo->getVirtualUrl() . '/public/' . $this->getUrlRel();
 154+ if ( $suffix !== false ) {
 155+ $path .= '/' . rawurlencode( $this->getFileNameStripped( $suffix ) );
 156+ }
 157+ return $path;
 158+ }
 159+
 160+ /** Strip namespace (if any) from file name */
 161+ function getFileNameStripped($suffix) {
 162+ $bits = explode( ':', $suffix );
 163+ return $bits[ count( $bits ) -1 ];
 164+ }
 165+
 166+ /**
 167+ * This function overrides the LocalFile because the archive name should not contain the namespace in the
 168+ * filename. Otherwise the function would have worked. This only affects reuploads
 169+ *
 170+ * Move or copy a file to its public location. If a file exists at the
 171+ * destination, move it to an archive. Returns the archive name on success
 172+ * or an empty string if it was a new file, and a wikitext-formatted
 173+ * WikiError object on failure.
 174+ *
 175+ * The archive name should be passed through to recordUpload for database
 176+ * registration.
 177+ *
 178+ * @param string $sourcePath Local filesystem path to the source image
 179+ * @param integer $flags A bitwise combination of:
 180+ * File::DELETE_SOURCE Delete the source file, i.e. move
 181+ * rather than copy
 182+ * @return FileRepoStatus object. On success, the value member contains the
 183+ * archive name, or an empty string if it was a new file.
 184+ */
 185+ function publish( $srcPath, $flags = 0 ) {
 186+ $this->lock();
 187+ $dstRel = $this->getRel();
 188+ /* This is the part that changed from LocalFile */
 189+ $archiveName = gmdate( 'YmdHis' ) . '!' .
 190+ $this->getFileNameStripped( $this->getName() );
 191+ /* End of changes */
 192+ $archiveRel = 'archive/' . $this->getHashPath() . $archiveName;
 193+ $flags = $flags & File::DELETE_SOURCE ? LocalRepo::DELETE_SOURCE : 0;
 194+ $status = $this->repo->publish( $srcPath, $dstRel, $archiveRel, $flags );
 195+ if ( $status->value == 'new' ) {
 196+ $status->value = '';
 197+ } else {
 198+ $status->value = $archiveName;
 199+ }
 200+ $this->unlock();
 201+ return $status;
 202+ }
 203+
 204+ /**
 205+ * The only thing changed here is that the array needs to strip the NS from the file name for the has (oldname is already fixed)
 206+ * Add the old versions of the image to the batch
 207+ */
 208+ function addOlds() {
 209+ $archiveBase = 'archive';
 210+ $this->olds = array();
 211+ $this->oldCount = 0;
 212+
 213+ $result = $this->db->select( 'oldimage',
 214+ array( 'oi_archive_name', 'oi_deleted' ),
 215+ array( 'oi_name' => $this->oldName ),
 216+ __METHOD__
 217+ );
 218+ foreach( $result as $row ) {
 219+ $oldName = $row->oi_archive_name;
 220+ $bits = explode( '!', $oldName, 2 );
 221+ if( count( $bits ) != 2 ) {
 222+ wfDebug( "Invalid old file name: $oldName \n" );
 223+ continue;
 224+ }
 225+ list( $timestamp, $filename ) = $bits;
 226+ if( $this->oldName != $filename ) {
 227+ wfDebug( "Invalid old file name: $oldName \n" );
 228+ continue;
 229+ }
 230+ $this->oldCount++;
 231+ // Do we want to add those to oldCount?
 232+ if( $row->oi_deleted & File::DELETED_FILE ) {
 233+ continue;
 234+ }
 235+ $this->olds[] = array(
 236+ "{$archiveBase}/{$this->oldHash}{$oldName}",
 237+ /* This is the part that changed from LocalFile */
 238+ "{$archiveBase}/{$this->newHash}{$timestamp}!" .
 239+ $this->getFileNameStripped( $this->newName )
 240+ /* End of changes */
 241+ );
 242+ }
 243+ $this->db->freeResult( $result );
 244+ }
 245+
 246+ /**
 247+ * The only thing changed here is to strip NS from the file name
 248+ * Delete cached transformed files
 249+ */
 250+ function purgeThumbnails() {
 251+ global $wgUseSquid;
 252+ // Delete thumbnails
 253+ $files = $this->getThumbnails();
 254+ $dir = $this->getThumbPath();
 255+ $urls = array();
 256+ foreach ( $files as $file ) {
 257+ # Check that the base file name is part of the thumb name
 258+ # This is a basic sanity check to avoid erasing unrelated directories
 259+
 260+ /* This is the part that changed from LocalFile */
 261+ if ( strpos( $file, $this->getFileNameStripped($this->getName()) ) !== false ) {
 262+ /* End of changes */
 263+ $url = $this->getThumbUrl( $file );
 264+ $urls[] = $url;
 265+ wfSuppressWarnings();
 266+ unlink( "$dir/$file" );
 267+ wfRestoreWarnings();
 268+ }
 269+ }
 270+
 271+ // Purge the squid
 272+ if ( $wgUseSquid ) {
 273+ SquidUpdate::purge( $urls );
 274+ }
 275+ }
 276+
 277+ /**
 278+ * Replaces hard coded OldLocalFile::newFromRow to use $this->repo->oldFileFromRowFactory configuration
 279+ * This may not be necessary in the future if LocalFile is patched to allow configuration
 280+ */
 281+
 282+ function getHistory( $limit = null, $start = null, $end = null, $inc = true ) {
 283+ $dbr = $this->repo->getSlaveDB();
 284+ $tables = array( 'oldimage' );
 285+ $fields = OldLocalFile::selectFields();
 286+ $conds = $opts = $join_conds = array();
 287+ $eq = $inc ? '=' : '';
 288+ $conds[] = "oi_name = " . $dbr->addQuotes( $this->title->getDBkey() );
 289+ if( $start ) {
 290+ $conds[] = "oi_timestamp <$eq " . $dbr->addQuotes( $dbr->timestamp( $start ) );
 291+ }
 292+ if( $end ) {
 293+ $conds[] = "oi_timestamp >$eq " . $dbr->addQuotes( $dbr->timestamp( $end ) );
 294+ }
 295+ if( $limit ) {
 296+ $opts['LIMIT'] = $limit;
 297+ }
 298+ // Search backwards for time > x queries
 299+ $order = ( !$start && $end !== null ) ? 'ASC' : 'DESC';
 300+ $opts['ORDER BY'] = "oi_timestamp $order";
 301+ $opts['USE INDEX'] = array( 'oldimage' => 'oi_name_timestamp' );
 302+
 303+ wfRunHooks( 'LocalFile::getHistory', array( &$this, &$tables, &$fields,
 304+ &$conds, &$opts, &$join_conds ) );
 305+
 306+ $res = $dbr->select( $tables, $fields, $conds, __METHOD__, $opts, $join_conds );
 307+ $r = array();
 308+ foreach( $res as $row ) {
 309+ /* This is the part that changed from LocalFile */
 310+ if ( $this->repo->oldFileFromRowFactory ) {
 311+ $r[] = call_user_func( $this->repo->oldFileFromRowFactory, $row, $this->repo );
 312+ } else {
 313+ $r[] = OldLocalFile::newFromRow( $row, $this->repo );
 314+ }
 315+ /* End of changes */
 316+ }
 317+ if( $order == 'ASC' ) {
 318+ $r = array_reverse( $r ); // make sure it ends up descending
 319+ }
 320+ return $r;
 321+ }
 322+
 323+
 324+
 325+ /** Instantiating this class using "self"
 326+ * If you're reading this, you're problably wondering why on earth are the following static functions, which are copied
 327+ * verbatim from the original extended class "LocalFIle" included here?
 328+ * The answer is that "self", will instantiate the class the code is physically in, not the class extended from it.
 329+ * Without the inclusion of these methods in "NSLocalFile, "self" would instantiate a "LocalFile" class, not the
 330+ * "NSLocalFile" class we want it to. Since there are only two methods within the "LocalFile" class that use "self",
 331+ * I just copied that code into the new "NSLocalFile" extended class, and the copied code will instantiate the "NSLocalFIle"
 332+ * class instead of the "LocalFile" class (at least in PHP 5.2.4)
 333+ */
 334+
 335+ /**
 336+ * Create a NSLocalFile from a title
 337+ * Do not call this except from inside a repo class.
 338+ *
 339+ * Note: $unused param is only here to avoid an E_STRICT
 340+ */
 341+ static function newFromTitle( $title, $repo, $unused = null ) {
 342+ return new self( $title, $repo );
 343+ }
 344+ /**
 345+ * Create a NSLocalFile from a title
 346+ * Do not call this except from inside a repo class.
 347+ */
 348+
 349+ static function newFromRow( $row, $repo ) {
 350+ $title = Title::makeTitle( NS_FILE, $row->img_name );
 351+ $file = new self( $title, $repo );
 352+ $file->loadFromRow( $row );
 353+ return $file;
 354+ }
 355+}
 356+
 357+class NSOldLocalFile extends OldLocalFile {
 358+
 359+ function getRel() {
 360+ return 'archive/' . $this->getHashPath() .
 361+ $this->getFileNameStripped( $this->getArchiveName() );
 362+ }
 363+ function getUrlRel() {
 364+ return 'archive/' . $this->getHashPath() .
 365+ urlencode( $this->getFileNameStripped( $this->getArchiveName() ) );
 366+ }
 367+ function publish( $srcPath, $flags = 0 ) {
 368+ return NSLocalFile::publish( $srcPath, $flags );
 369+ }
 370+ function getThumbUrl( $suffix = false ) {
 371+ return NSLocalFile::getThumbUrl( $suffix );
 372+ }
 373+ function thumbName( $params ) {
 374+ return NSLocalFile::thumbName( $params );
 375+ }
 376+ function getThumbPath( $suffix = false ) {
 377+ return NSLocalFile::getThumbPath( $suffix );
 378+ }
 379+ function getArchiveRel( $suffix = false ) {
 380+ return NSLocalFile::getArchiveRel( $suffix );
 381+ }
 382+ function getArchiveUrl( $suffix = false ) {
 383+ return NSLocalFile::getArchiveUrl( $suffix );
 384+ }
 385+ function getArchiveVirtualUrl( $suffix = false ) {
 386+ return NSLocalFile::getArchiveVirtualUrl( $suffix );
 387+ }
 388+ function getThumbVirtualUrl( $suffix = false ) {
 389+ return NSLocalFile::getArchiveVirtualUrl( $suffix );
 390+ }
 391+ function getVirtualUrl( $suffix = false ) {
 392+ return NSLocalFile::getVirtualUrl( $suffix );
 393+ }
 394+ function getFileNameStripped($suffix) {
 395+ return NSLocalFile::getFileNameStripped( $suffix );
 396+ }
 397+ function addOlds() {
 398+ return NSLocalFile::addOlds();
 399+ }
 400+ function purgeThumbnails() {
 401+ return NSLocalFile::purgeThumbnails();
 402+ }
 403+ /**
 404+ * Replaces hard coded OldLocalFile::newFromRow to use $this->repo->oldFileFromRowFactory configuration
 405+ * This may not be necessary in the future if LocalFile is patched to allow configuration
 406+ */
 407+ function getHistory( $limit = null, $start = null, $end = null, $inc = true ) {
 408+ return NSLocalFile::getHistory( $limit, $start , $end, $inc );
 409+ }
 410+
 411+ /** See comment above about Instantiating this class using "self" */
 412+
 413+ static function newFromTitle( $title, $repo, $time = null ) {
 414+ # The null default value is only here to avoid an E_STRICT
 415+ if( $time === null )
 416+ throw new MWException( __METHOD__.' got null for $time parameter' );
 417+ return new self( $title, $repo, $time, null );
 418+ }
 419+
 420+ static function newFromArchiveName( $title, $repo, $archiveName ) {
 421+ return new self( $title, $repo, null, $archiveName );
 422+ }
 423+
 424+ static function newFromRow( $row, $repo ) {
 425+ $title = Title::makeTitle( NS_FILE, $row->oi_name );
 426+ $file = new self( $title, $repo, null, $row->oi_archive_name );
 427+ $file->loadFromRow( $row, 'oi_' );
 428+ return $file;
 429+ }
 430+}
Property changes on: trunk/extensions/NSFileRepo/NSFileRepo_body.php
___________________________________________________________________
Added: svn:eol-style
1431 + native
Index: trunk/extensions/NSFileRepo/NSFileRepo.php
@@ -21,16 +21,18 @@
2222 * It must be included(required) after Lockdown! Also, $wgHashedUploadDirectory must be true and cannot be changed once repository has files in it
2323 */
2424
25 -if (!defined('MEDIAWIKI')) die('Not an entry point.');
 25+if ( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.' );
2626 if (!function_exists('lockdownUserCan')) die('You MUST load Extension Lockdown before NSFileRepo (http://www.mediawiki.org/wiki/Extension:Lockdown).');
2727
2828 $wgImgAuthPublicTest = false; // Must be set to false if you want to use more restrictive than general ['*']['read']
2929 $wgIllegalFileChars = isset($wgIllegalFileChars) ? $wgIllegalFileChars : ""; // For MW Versions <1.16
3030 $wgIllegalFileChars = str_replace(":","",$wgIllegalFileChars); // Remove the default illegal char ':' - need it to determine NS
3131
 32+$dir = dirname( __FILE__ ) . '/';
 33+
3234 # Internationalisation file
33 -$wgExtensionMessagesFiles['NSFileRepo'] = dirname(__FILE__) .'/NSFileRepo.i18n.php';
34 -$wgExtensionMessagesFiles['img_auth'] = dirname(__FILE__) .'/img_auth.i18n.php';
 35+$wgExtensionMessagesFiles['NSFileRepo'] = $dir . 'NSFileRepo.i18n.php';
 36+$wgExtensionMessagesFiles['img_auth'] = $dir . 'img_auth.i18n.php';
3537
3638 $wgExtensionFunctions[] = 'NSFileRepoSetup';
3739 $wgExtensionCredits['media'][] = array(
@@ -43,483 +45,80 @@
4446 );
4547
4648 /**
47 - * Set up hooks for NSFileRepo
 49+ * Classes
4850 */
 51+$wgAutoloadClasses['NSLocalRepo'] = $dir . 'NSFileRepo_body.php';
 52+$wgAutoloadClasses['NSLocalFile'] = $dir . 'NSFileRepo_body.php';
 53+$wgAutoloadClasses['NSOldLocalFile'] = $dir . 'NSFileRepo_body.php';
4954
50 -$wgHooks['UploadForm:BeforeProcessing'][] = 'NSFileRepoNSCheck';
5155 /**
52 -Note, this must be AFTER lockdown has been included - thus assuming that the user has access to files in general + files at this particular namespace.
53 -*/
 56+ * Set up hooks for NSFileRepo
 57+ */
 58+$wgHooks['UploadForm:BeforeProcessing'][] = 'NSFileRepoNSCheck';
 59+// Note, this must be AFTER lockdown has been included - thus assuming that the
 60+// user has access to files in general + files at this particular namespace.
5461 $wgHooks['userCan'][] = 'NSFileRepolockdownUserCan';
5562 $wgHooks['ImgAuthBeforeStream'][] = 'NSFileRepoImgAuthCheck';
5663
57 -class NSLocalRepo extends LocalRepo {
58 - var $fileFactory = array( 'NSLocalFile', 'newFromTitle' );
59 - var $oldFileFactory = array( 'NSOldLocalFile', 'newFromTitle' );
60 - var $fileFromRowFactory = array( 'NSLocalFile', 'newFromRow' );
61 - var $oldFileFromRowFactory = array( 'NSOldLocalFile', 'newFromRow' );
62 -
63 - static function getHashPathForLevel( $name, $levels ) {
64 - global $wgContLang;
65 - $bits=explode(':',$name);
66 - $filename = $bits[count($bits)-1];
67 - $path = parent::getHashPathForLevel( $filename, $levels );
68 - return ((count($bits) > 1) ? $wgContLang->getNsIndex($bits[0]).'/'.$path : $path);
69 - }
70 - /**
71 - * Get a relative path including trailing slash, e.g. f/fa/
72 - * If the repo is not hashed, returns an empty string
73 - * This is needed because self:: will call parent if not included - exact same as in FSRepo
74 - */
75 - function getHashPath( $name ) {
76 - return self::getHashPathForLevel( $name, $this->hashLevels );
77 - }
78 - /**
79 - * Pick a random name in the temp zone and store a file to it.
80 - * @param string $originalName The base name of the file as specified
81 - * by the user. The file extension will be maintained.
82 - * @param string $srcPath The current location of the file.
83 - * @return FileRepoStatus object with the URL in the value.
84 - */
85 - function storeTemp( $originalName, $srcPath ) {
86 - $date = gmdate( "YmdHis" );
87 - $hashPath = $this->getHashPath( $originalName );
88 - $filename = $this->getFileNameStripped($originalName);
89 - $dstRel = "$hashPath$date!$filename";
90 - $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $filename );
91 - $result = $this->store( $srcPath, 'temp', $dstRel );
92 - $result->value = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;
93 - return $result;
94 - }
95 - function getFileNameStripped($suffix) {
96 - return(NSLocalFile::getFileNameStripped($suffix));
97 - }
98 -}
99 -
100 -class NSLocalFile extends LocalFile
101 -{
102 - /**
103 - * Get the path of the file relative to the public zone root
104 - */
105 - function getRel() {
106 - return $this->getHashPath() . $this->getFileNameStripped($this->getName());
107 - }
108 -
109 - /**
110 - * Get urlencoded relative path of the file
111 - */
112 - function getUrlRel() {
113 - return $this->getHashPath() . rawurlencode( $this->getFileNameStripped($this->getName()));
114 - }
115 -
116 - /** Get the URL of the thumbnail directory, or a particular file if $suffix is specified */
117 - function getThumbUrl( $suffix = false ) {
118 - $path = $this->repo->getZoneUrl('thumb') . '/' . $this->getUrlRel();
119 - if ( $suffix !== false ) {
120 - $path .= '/' . rawurlencode( $this->getFileNameStripped($suffix) );
121 - }
122 - return $path;
123 - }
124 -
125 -
126 - /** Return the file name of a thumbnail with the specified parameters */
127 - function thumbName( $params ) {
128 - if ( !$this->getHandler() ) {
129 - return null;
130 - }
131 - $extension = $this->getExtension();
132 - list( $thumbExt, $thumbMime ) = $this->handler->getThumbType( $extension, $this->getMimeType() );
133 -/* This is the part that changed from LocalFile */
134 - $thumbName = $this->handler->makeParamString( $params ) . '-' . $this->getFileNameStripped($this->getName());
135 -/* End of changes */
136 - if ( $thumbExt != $extension ) {
137 - $thumbName .= ".$thumbExt";
138 - }
139 - $bits=explode(':',$this->getName());
140 - if (count($bits) > 1) $thumbName = $bits[0].":".$thumbName;
141 - return $thumbName;
142 - }
143 -
144 -
145 - /** Get the path of the thumbnail directory, or a particular file if $suffix is specified */
146 - function getThumbPath( $suffix = false ) {
147 - $path = $this->repo->getZonePath('thumb') . '/' . $this->getRel();
148 - if ( $suffix !== false ) {
149 - $path .= '/' . $this->getFileNameStripped($suffix);
150 - }
151 - return $path;
152 - }
153 -
154 - /** Get the relative path for an archive file */
155 - function getArchiveRel( $suffix = false ) {
156 - $path = 'archive/' . $this->getHashPath();
157 - if ( $suffix === false ) {
158 - $path = substr( $path, 0, -1 );
159 - } else {
160 - $path .= $this->getFileNameStripped($suffix);
161 - }
162 - return $path;
163 - }
164 -
165 - /** Get the URL of the archive directory, or a particular file if $suffix is specified */
166 - function getArchiveUrl( $suffix = false ) {
167 - $path = $this->repo->getZoneUrl('public') . '/archive/' . $this->getHashPath();
168 - if ( $suffix === false ) {
169 - $path = substr( $path, 0, -1 );
170 - } else {
171 - $path .= rawurlencode( $this->getFileNameStripped($suffix) );
172 - }
173 - return $path;
174 - }
175 -
176 - /** Get the virtual URL for an archive file or directory */
177 - function getArchiveVirtualUrl( $suffix = false ) {
178 - $path = $this->repo->getVirtualUrl() . '/public/archive/' . $this->getHashPath();
179 - if ( $suffix === false ) {
180 - $path = substr( $path, 0, -1 );
181 - } else {
182 - $path .= rawurlencode( $this->getFileNameStripped($suffix) );
183 - }
184 - return $path;
185 - }
186 -
187 - /** Get the virtual URL for a thumbnail file or directory */
188 - function getThumbVirtualUrl( $suffix = false ) {
189 - $path = $this->repo->getVirtualUrl() . '/thumb/' . $this->getUrlRel();
190 - if ( $suffix !== false ) {
191 - $path .= '/' . rawurlencode( $this->getFileNameStripped($suffix) );
192 - }
193 - return $path;
194 - }
195 -
196 - /** Get the virtual URL for the file itself */
197 - function getVirtualUrl( $suffix = false ) {
198 - $path = $this->repo->getVirtualUrl() . '/public/' . $this->getUrlRel();
199 - if ( $suffix !== false ) {
200 - $path .= '/' . rawurlencode( $this->getFileNameStripped($suffix) );
201 - }
202 - return $path;
203 - }
204 -
205 - /** Strip namespace (if any) from file name */
206 - function getFileNameStripped($suffix) {
207 - $bits=explode(':',$suffix);
208 - return $bits[count($bits)-1];
209 - }
210 -
211 - /**
212 - * This function overrides the LocalFile because the archive name should not contain the namespace in the
213 - * filename. Otherwise the function would have worked. This only affects reuploads
214 - *
215 - * Move or copy a file to its public location. If a file exists at the
216 - * destination, move it to an archive. Returns the archive name on success
217 - * or an empty string if it was a new file, and a wikitext-formatted
218 - * WikiError object on failure.
219 - *
220 - * The archive name should be passed through to recordUpload for database
221 - * registration.
222 - *
223 - * @param string $sourcePath Local filesystem path to the source image
224 - * @param integer $flags A bitwise combination of:
225 - * File::DELETE_SOURCE Delete the source file, i.e. move
226 - * rather than copy
227 - * @return FileRepoStatus object. On success, the value member contains the
228 - * archive name, or an empty string if it was a new file.
229 - */
230 - function publish( $srcPath, $flags = 0 ) {
231 - $this->lock();
232 - $dstRel = $this->getRel();
233 -/* This is the part that changed from LocalFile */
234 - $archiveName = gmdate( 'YmdHis' ) . '!'.$this->getFileNameStripped($this->getName());
235 -/* End of changes */
236 - $archiveRel = 'archive/' . $this->getHashPath() . $archiveName;
237 - $flags = $flags & File::DELETE_SOURCE ? LocalRepo::DELETE_SOURCE : 0;
238 - $status = $this->repo->publish( $srcPath, $dstRel, $archiveRel, $flags );
239 - if ( $status->value == 'new' ) {
240 - $status->value = '';
241 - } else {
242 - $status->value = $archiveName;
243 - }
244 - $this->unlock();
245 - return $status;
246 - }
247 -
248 - /**
249 - * The only thing changed here is that the array needs to strip the NS from the file name for the has (oldname is already fixed)
250 - * Add the old versions of the image to the batch
251 - */
252 - function addOlds() {
253 - $archiveBase = 'archive';
254 - $this->olds = array();
255 - $this->oldCount = 0;
256 -
257 - $result = $this->db->select( 'oldimage',
258 - array( 'oi_archive_name', 'oi_deleted' ),
259 - array( 'oi_name' => $this->oldName ),
260 - __METHOD__
261 - );
262 - while( $row = $this->db->fetchObject( $result ) ) {
263 - $oldName = $row->oi_archive_name;
264 - $bits = explode( '!', $oldName, 2 );
265 - if( count( $bits ) != 2 ) {
266 - wfDebug( "Invalid old file name: $oldName \n" );
267 - continue;
268 - }
269 - list( $timestamp, $filename ) = $bits;
270 - if( $this->oldName != $filename ) {
271 - wfDebug( "Invalid old file name: $oldName \n" );
272 - continue;
273 - }
274 - $this->oldCount++;
275 - // Do we want to add those to oldCount?
276 - if( $row->oi_deleted & File::DELETED_FILE ) {
277 - continue;
278 - }
279 - $this->olds[] = array(
280 - "{$archiveBase}/{$this->oldHash}{$oldName}",
281 -/* This is the part that changed from LocalFile */
282 - "{$archiveBase}/{$this->newHash}{$timestamp}!".$this->getFileNameStripped($this->newName)
283 -/* End of changes */
284 - );
285 - }
286 - $this->db->freeResult( $result );
287 - }
288 -
289 - /**
290 - * The only thing changed here is to strip NS from the file name
291 - * Delete cached transformed files
292 - */
293 -
294 - function purgeThumbnails() {
295 - global $wgUseSquid;
296 - // Delete thumbnails
297 - $files = $this->getThumbnails();
298 - $dir = $this->getThumbPath();
299 - $urls = array();
300 - foreach ( $files as $file ) {
301 - # Check that the base file name is part of the thumb name
302 - # This is a basic sanity check to avoid erasing unrelated directories
303 -
304 -/* This is the part that changed from LocalFile */
305 - if ( strpos( $file, $this->getFileNameStripped($this->getName()) ) !== false ) {
306 -/* End of changes */
307 - $url = $this->getThumbUrl( $file );
308 - $urls[] = $url;
309 - @unlink( "$dir/$file" );
310 - }
311 - }
312 -
313 - // Purge the squid
314 - if ( $wgUseSquid ) {
315 - SquidUpdate::purge( $urls );
316 - }
317 - }
318 -
319 - /**
320 - * Replaces hard coded OldLocalFile::newFromRow to use $this->repo->oldFileFromRowFactory configuration
321 - * This may not be necessary in the future if LocalFile is patched to allow configuration
322 - */
323 -
324 - function getHistory( $limit = null, $start = null, $end = null, $inc = true ) {
325 - $dbr = $this->repo->getSlaveDB();
326 - $tables = array( 'oldimage' );
327 - $fields = OldLocalFile::selectFields();
328 - $conds = $opts = $join_conds = array();
329 - $eq = $inc ? '=' : '';
330 - $conds[] = "oi_name = " . $dbr->addQuotes( $this->title->getDBkey() );
331 - if( $start ) {
332 - $conds[] = "oi_timestamp <$eq " . $dbr->addQuotes( $dbr->timestamp( $start ) );
333 - }
334 - if( $end ) {
335 - $conds[] = "oi_timestamp >$eq " . $dbr->addQuotes( $dbr->timestamp( $end ) );
336 - }
337 - if( $limit ) {
338 - $opts['LIMIT'] = $limit;
339 - }
340 - // Search backwards for time > x queries
341 - $order = ( !$start && $end !== null ) ? 'ASC' : 'DESC';
342 - $opts['ORDER BY'] = "oi_timestamp $order";
343 - $opts['USE INDEX'] = array( 'oldimage' => 'oi_name_timestamp' );
344 -
345 - wfRunHooks( 'LocalFile::getHistory', array( &$this, &$tables, &$fields,
346 - &$conds, &$opts, &$join_conds ) );
347 -
348 - $res = $dbr->select( $tables, $fields, $conds, __METHOD__, $opts, $join_conds );
349 - $r = array();
350 - while( $row = $dbr->fetchObject( $res ) ) {
351 -/* This is the part that changed from LocalFile */
352 - if ( $this->repo->oldFileFromRowFactory ) {
353 - $r[] = call_user_func( $this->repo->oldFileFromRowFactory, $row, $this->repo );
354 - } else {
355 - $r[] = OldLocalFile::newFromRow( $row, $this->repo );
356 - }
357 -/* End of changes */
358 - }
359 - if( $order == 'ASC' ) {
360 - $r = array_reverse( $r ); // make sure it ends up descending
361 - }
362 - return $r;
363 - }
364 -
365 -
366 -
367 - /** Instantiating this class using "self"
368 - * If you're reading this, you're problably wondering why on earth are the following static functions, which are copied
369 - * verbatim from the original extended class "LocalFIle" included here?
370 - * The answer is that "self", will instantiate the class the code is physically in, not the class extended from it.
371 - * Without the inclusion of these methods in "NSLocalFile, "self" would instantiate a "LocalFile" class, not the
372 - * "NSLocalFile" class we want it to. Since there are only two methods within the "LocalFile" class that use "self",
373 - * I just copied that code into the new "NSLocalFile" extended class, and the copied code will instantiate the "NSLocalFIle"
374 - * class instead of the "LocalFile" class (at least in PHP 5.2.4)
375 - */
376 -
377 - /**
378 - * Create a NSLocalFile from a title
379 - * Do not call this except from inside a repo class.
380 - *
381 - * Note: $unused param is only here to avoid an E_STRICT
382 - */
383 - static function newFromTitle( $title, $repo, $unused = null ) {
384 - return new self( $title, $repo );
385 - }
386 - /**
387 - * Create a NSLocalFile from a title
388 - * Do not call this except from inside a repo class.
389 - */
390 -
391 - static function newFromRow( $row, $repo ) {
392 - $title = Title::makeTitle( NS_IMAGE, $row->img_name );
393 - $file = new self( $title, $repo );
394 - $file->loadFromRow( $row );
395 - return $file;
396 - }
397 -}
398 -class NSOldLocalFile extends OldLocalFile
399 -{
400 -
401 - function getRel() {
402 - return 'archive/' . $this->getHashPath() . $this->getFileNameStripped($this->getArchiveName());
403 - }
404 - function getUrlRel() {
405 - return 'archive/' . $this->getHashPath() . urlencode( $this->getFileNameStripped($this->getArchiveName()) );
406 - }
407 - function publish( $srcPath, $flags = 0 ) {
408 - return NSLocalFile::publish( $srcPath, $flags );
409 - }
410 - function getThumbUrl( $suffix = false ) {
411 - return(NSLocalFile::getThumbUrl( $suffix ) );
412 - }
413 - function thumbName( $params ) {
414 - return(NSLocalFile::thumbName( $params ));
415 - }
416 - function getThumbPath( $suffix = false ) {
417 - return(NSLocalFile::getThumbPath( $suffix ));
418 - }
419 - function getArchiveRel( $suffix = false ) {
420 - return(NSLocalFile::getArchiveRel( $suffix ));
421 - }
422 - function getArchiveUrl( $suffix = false ) {
423 - return(NSLocalFile::getArchiveUrl( $suffix ));
424 - }
425 - function getArchiveVirtualUrl( $suffix = false ) {
426 - return(NSLocalFile::getArchiveVirtualUrl( $suffix ));
427 - }
428 - function getThumbVirtualUrl( $suffix = false ) {
429 - return(NSLocalFile::getArchiveVirtualUrl( $suffix ));
430 - }
431 - function getVirtualUrl( $suffix = false ) {
432 - return(NSLocalFile::getVirtualUrl( $suffix ));
433 - }
434 - function getFileNameStripped($suffix) {
435 - return(NSLocalFile::getFileNameStripped($suffix));
436 - }
437 - function addOlds() {
438 - return(NSLocalFile::addOlds());
439 - }
440 - function purgeThumbnails() {
441 - return(NSLocalFile::purgeThumbnails());
442 - }
443 - /**
444 - * Replaces hard coded OldLocalFile::newFromRow to use $this->repo->oldFileFromRowFactory configuration
445 - * This may not be necessary in the future if LocalFile is patched to allow configuration
446 - */
447 - function getHistory( $limit = null, $start = null, $end = null, $inc = true ) {
448 - return(NSLocalFile::getHistory( $limit, $start , $end, $inc) );
449 - }
450 -
451 - /** See comment above about Instantiating this class using "self" */
452 -
453 - static function newFromTitle( $title, $repo, $time = null ) {
454 - # The null default value is only here to avoid an E_STRICT
455 - if( $time === null )
456 - throw new MWException( __METHOD__.' got null for $time parameter' );
457 - return new self( $title, $repo, $time, null );
458 - }
459 -
460 - static function newFromArchiveName( $title, $repo, $archiveName ) {
461 - return new self( $title, $repo, null, $archiveName );
462 - }
463 -
464 - static function newFromRow( $row, $repo ) {
465 - $title = Title::makeTitle( NS_IMAGE, $row->oi_name );
466 - $file = new self( $title, $repo, null, $row->oi_archive_name );
467 - $file->loadFromRow( $row, 'oi_' );
468 - return $file;
469 - }
470 -}
471 -
47264 /**
47365 * Initial setup, add .i18n. messages from $IP/extensions/DiscussionThreading/DiscussionThreading.i18n.php
47466 */
47567 function NSFileRepoSetup() {
476 - global $wgLocalFileRepo,$wgVersion;
477 - $xversion = explode(".",$wgVersion);
478 - if ($xversion[0] <= "1" && $xversion[1] < "16") wfLoadExtensionMessages( 'img_auth' ); // loads img_auth messages for versions <1.16
 68+ global $wgLocalFileRepo, $wgVersion;
 69+ // loads img_auth messages for versions <1.16
 70+ if( version_compare( $wgVersion, '1.16' ) ) {
 71+ wfLoadExtensionMessages( 'img_auth' );
 72+ }
47973 wfLoadExtensionMessages( 'NSFileRepo' );
48074 $wgLocalFileRepo['class'] = "NSLocalRepo";
48175 RepoGroup::destroySingleton();
48276 }
 77+
48378 /*
48479 * Check for Namespace in Title Line
48580 */
486 -function NSFileRepoNSCheck($UploadForm) {
487 - $title = Title::newFromText($UploadForm->mDesiredDestName);
488 - if ($title->mNamespace < 100) {
489 - $UploadForm->mDesiredDestName = preg_replace ( "/:/", '-', $UploadForm->mDesiredDestName);
 81+function NSFileRepoNSCheck( $uploadForm ) {
 82+ $title = Title::newFromText($uploadForm->mDesiredDestName);
 83+ if ( $title->getNamespace() < 100 ) {
 84+ $uploadForm->mDesiredDestName = preg_replace( "/:/", '-', $uploadForm->mDesiredDestName );
49085 } else {
491 - $bits=explode(':',$UploadForm->mDesiredDestName);
492 - $ns = array_shift($bits);
493 - $UploadForm->mDesiredDestName = $ns.":".implode("-",$bits);
 86+ $bits = explode( ':', $uploadForm->mDesiredDestName );
 87+ $ns = array_shift( $bits );
 88+ $uploadForm->mDesiredDestName = $ns.":" . implode( "-", $bits );
49489 }
495 - return (true);
 90+ return true;
49691 }
49792
498 -// If Extension:Lockdown has been activated (recommend), check individual namespace protection
499 -
500 -function NSFileRepolockdownUserCan($title, $user, $action, &$result) {
 93+/**
 94+ * If Extension:Lockdown has been activated (recommend), check individual namespace protection
 95+ */
 96+function NSFileRepolockdownUserCan( $title, $user, $action, &$result) {
50197 global $wgWhitelistRead;
502 - if (in_array($title->getPrefixedText(), $wgWhitelistRead)) return true;
503 - if (function_exists('lockdownUserCan')){
504 - if($title->getNamespace() == NS_IMAGE) {
505 - $ntitle = Title::newFromText($title->mDbkeyform);
506 - return ($ntitle->mNamespace < 100) ? true : lockdownUserCan($ntitle, $user, $action, $result);
 98+ if ( in_array( $title->getPrefixedText(), $wgWhitelistRead ) ) {
 99+ return true;
 100+ } elseif( function_exists( 'lockdownUserCan' ) ) {
 101+ if( $title->getNamespace() == NS_FILE ) {
 102+ $ntitle = Title::newFromText( $title->mDbkeyform );
 103+ return ( $ntitle->getNamespace() < 100 ) ?
 104+ true : lockdownUserCan( $ntitle, $user, $action, $result );
507105 }
508106 }
509107 return true;
510108 }
511109
512 -function NSFileRepoImgAuthCheck($title, $path, $name, $result) {
 110+function NSFileRepoImgAuthCheck( $title, $path, $name, $result ) {
513111 global $wgContLang;
514112
515 -# See if stored in a NS path
516 -
 113+ # See if stored in a NS path
517114 $subdirs = explode('/',$path);
518115 $x = (!is_numeric($subdirs[1]) && ($subdirs[1] == "archive" || $subdirs[1] == "deleted" || $subdirs[1] == "thumb")) ? 2 : 1;
519116 $x = ($x == 2 && $subdirs[1] == "thumb" && $subdirs[2] == "archive") ? 3 : $x;
520 - if (strlen($subdirs[$x]) >= 3 && is_numeric($subdirs[$x]) && $subdirs[$x] >= 100) {
521 - $title = Title::makeTitleSafe( NS_IMAGE, $wgContLang->getNsText($subdirs[$x]).":".$name );
 117+ if ( strlen( $subdirs[$x] ) >= 3 && is_numeric( $subdirs[$x] )
 118+ && $subdirs[$x] >= 100 )
 119+ {
 120+ $title = Title::makeTitleSafe( NS_FILE, $wgContLang->getNsText( $subdirs[$x] ) . ":" . $name );
522121 if( !$title instanceof Title ) {
523 - $result = array('img-auth-accessdenied','img-auth-badtitle',$name);
 122+ $result = array( 'img-auth-accessdenied', 'img-auth-badtitle', $name );
524123 return false;
525124 }
526125 }

Status & tagging log