return $tmp;
}
}
+
+ /**
+ * PHP on Windows will detect C:\Windows\Temp as not writable even though PHP can write to it
+ * so create a directory within that called 'mwtmp' with a suffix of the user running the
+ * current process.
+ * The user is included as if various scripts are run by different users they will likely
+ * not be able to access each others temporary files.
+ */
+ if ( wfIsWindows() ) {
+ $tmp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mwtmp' . '-' . get_current_user();
+ if ( !file_exists( $tmp ) ) {
+ mkdir( $tmp );
+ }
+ if ( file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
+ return $tmp;
+ }
+ }
+
throw new MWException( 'No writable temporary directory could be found. ' .
'Please set $wgTmpDirectory to a writable directory.' );
}
return MediaWikiServices::getInstance()->getTitleFormatter();
}
+ /**
+ * @access protected
+ */
function __construct() {
}
* or WatchedItemStore::loadWatchedItem()
*/
public static function fromUserTitle( $user, $title, $checkRights = User::CHECK_USER_RIGHTS ) {
- // wfDeprecated( __METHOD__, '1.27' );
+ wfDeprecated( __METHOD__, '1.27' );
return new self( $user, $title, self::DEPRECATED_USAGE_TIMESTAMP, (bool)$checkRights );
}
* @deprecated since 1.27 Use WatchedItemStore::resetNotificationTimestamp()
*/
public function resetNotificationTimestamp( $force = '', $oldid = 0 ) {
- // wfDeprecated( __METHOD__, '1.27' );
+ wfDeprecated( __METHOD__, '1.27' );
if ( $this->checkRights && !$this->user->isAllowed( 'editmywatchlist' ) ) {
return;
}
* @deprecated since 1.27 Use WatchedItemStore::addWatchBatch()
*/
public static function batchAddWatch( array $items ) {
- // wfDeprecated( __METHOD__, '1.27' );
+ wfDeprecated( __METHOD__, '1.27' );
if ( !$items ) {
return false;
}
* @return bool
*/
public function addWatch() {
- // wfDeprecated( __METHOD__, '1.27' );
+ wfDeprecated( __METHOD__, '1.27' );
$this->user->addWatch( $this->getTitle(), $this->checkRights );
return true;
}
* @return bool
*/
public function removeWatch() {
- // wfDeprecated( __METHOD__, '1.27' );
+ wfDeprecated( __METHOD__, '1.27' );
if ( $this->checkRights && !$this->user->isAllowed( 'editmywatchlist' ) ) {
return false;
}
* @return bool
*/
public function isWatched() {
- // wfDeprecated( __METHOD__, '1.27' );
+ wfDeprecated( __METHOD__, '1.27' );
return $this->user->isWatched( $this->getTitle(), $this->checkRights );
}
* @deprecated since 1.27 Use WatchedItemStore::duplicateAllAssociatedEntries()
*/
public static function duplicateEntries( Title $oldTitle, Title $newTitle ) {
- // wfDeprecated( __METHOD__, '1.27' );
+ wfDeprecated( __METHOD__, '1.27' );
$store = MediaWikiServices::getInstance()->getWatchedItemStore();
$store->duplicateAllAssociatedEntries( $oldTitle, $newTitle );
}
/**
* @since 1.16.3
+ * @return array
*/
public function getFirstLetterData() {
- if ( $this->firstLetterData !== null ) {
- return $this->firstLetterData;
- }
-
- $cache = ObjectCache::getLocalServerInstance( CACHE_ANYTHING );
- $cacheKey = $cache->makeKey(
- 'first-letters',
- $this->locale,
- $this->digitTransformLanguage->getCode(),
- self::getICUVersion()
- );
- $cacheEntry = $cache->get( $cacheKey );
-
- if ( $cacheEntry && isset( $cacheEntry['version'] )
- && $cacheEntry['version'] == self::FIRST_LETTER_VERSION
- ) {
- $this->firstLetterData = $cacheEntry;
- return $this->firstLetterData;
+ if ( $this->firstLetterData === null ) {
+ $cache = ObjectCache::getLocalServerInstance( CACHE_ANYTHING );
+ $cacheKey = $cache->makeKey(
+ 'first-letters',
+ $this->locale,
+ $this->digitTransformLanguage->getCode(),
+ self::getICUVersion(),
+ self::FIRST_LETTER_VERSION
+ );
+ $this->firstLetterData = $cache->getWithSetCallback( $cacheKey, $cache::TTL_WEEK, function () {
+ return $this->fetchFirstLetterData();
+ } );
}
+ return $this->firstLetterData;
+ }
+ /**
+ * @return array
+ * @throws MWException
+ */
+ private function fetchFirstLetterData() {
// Generate data from serialized data file
-
if ( isset( self::$tailoringFirstLetters[$this->locale] ) ) {
- $letters = wfGetPrecompiledData( "first-letters-root.ser" );
+ $letters = wfGetPrecompiledData( 'first-letters-root.ser' );
// Append additional characters
$letters = array_merge( $letters, self::$tailoringFirstLetters[$this->locale] );
// Remove unnecessary ones, if any
$data = [
'chars' => array_values( $letterMap ),
'keys' => array_keys( $letterMap ),
- 'version' => self::FIRST_LETTER_VERSION,
];
// Reduce memory usage before caching
unset( $letterMap );
- // Save to cache
- $this->firstLetterData = $data;
- $cache->set( $cacheKey, $data, $cache::TTL_WEEK );
return $data;
}
* @since 1.16.3
*/
public function getLetterByIndex( $index ) {
- if ( $this->firstLetterData === null ) {
- $this->getFirstLetterData();
- }
- return $this->firstLetterData['chars'][$index];
+ return $this->getFirstLetterData()['chars'][$index];
}
/**
* @since 1.16.3
*/
public function getSortKeyByLetterIndex( $index ) {
- if ( $this->firstLetterData === null ) {
- $this->getFirstLetterData();
- }
- return $this->firstLetterData['keys'][$index];
+ return $this->getFirstLetterData()['keys'][$index];
}
/**
* @since 1.16.3
*/
public function getFirstLetterCount() {
- if ( $this->firstLetterData === null ) {
- $this->getFirstLetterData();
- }
- return count( $this->firstLetterData['chars'] );
+ return count( $this->getFirstLetterData()['chars'] );
}
/**
*/
public function getNamespace();
+ /**
+ * Convenience function to test if it is in the namespace
+ *
+ * @param int $ns
+ * @return bool
+ */
+ public function inNamespace( $ns );
+
/**
* Get the link fragment (i.e. the bit after the #) in text form.
*
* @return mixed
*/
protected function unserialize( $data ) {
- return ctype_digit( $data ) ? intval( $data ) : unserialize( $data );
+ $int = intval( $data );
+ return $data === (string)$int ? $int : unserialize( $data );
}
/**
* Get the possibly-cached User object for the specified username
*
* @since 1.25
- * @return User|bool false if a valid object cannot be created
+ * @return User
*/
public function getUserObj() {
if ( $this->userObj === null ) {
$username = $this->getUser();
if ( $username ) {
- $this->userObj = User::newFromName( $username );
+ // Use provided username if valid, fallback to anonymous user
+ $this->userObj = User::newFromName( $username ) ?: new User;
} else {
- $this->userObj = new User; // Anonymous user
+ // Anonymous user
+ $this->userObj = new User;
}
}
}
$user = $context->getUserObj();
- if ( !$user || $user->isAnon() ) {
+ if ( $user->isAnon() ) {
return [];
}
}
$user = $context->getUserObj();
- if ( !$user || $user->isAnon() ) {
+ if ( $user->isAnon() ) {
return [];
}
return $this->namespace;
}
+ /**
+ * @since 1.27
+ * @param int $ns
+ * @return bool
+ */
+ public function inNamespace( $ns ) {
+ return $this->namespace == $ns;
+ }
+
/**
* @return string
*/
*/
class UpdateCollation extends Maintenance {
const BATCH_SIZE = 100; // Number of rows to process in one batch
- const SYNC_INTERVAL = 20; // Wait for slaves after this many batches
+ const SYNC_INTERVAL = 5; // Wait for slaves after this many batches
public $sizeHistogram = [];
$table = $( '#mw_metadata' ),
$tbody = $table.find( 'tbody' );
- if ( !$tbody.length || !$tbody.find( '.collapsable' ).length ) {
+ if ( !$tbody.find( '.collapsable' ).length ) {
return;
}
// @codingStandardsIgnoreEnd
}
+ public static function provideLinkBeginHook() {
+ // @codingStandardsIgnoreStart Generic.Files.LineLength
+ return [
+ // Modify $html
+ [
+ function( $dummy, $title, &$html, &$attribs, &$query, &$options, &$ret ) {
+ $html = 'foobar';
+ },
+ '<a href="/wiki/Special:BlankPage" title="Special:BlankPage">foobar</a>'
+ ],
+ // Modify $attribs
+ [
+ function( $dummy, $title, &$html, &$attribs, &$query, &$options, &$ret ) {
+ $attribs['bar'] = 'baz';
+ },
+ '<a href="/wiki/Special:BlankPage" title="Special:BlankPage" bar="baz">Special:BlankPage</a>'
+ ],
+ // Modify $query
+ [
+ function( $dummy, $title, &$html, &$attribs, &$query, &$options, &$ret ) {
+ $query['bar'] = 'baz';
+ },
+ '<a href="/w/index.php?title=Special:BlankPage&bar=baz" title="Special:BlankPage">Special:BlankPage</a>'
+ ],
+ // Force HTTP $options
+ [
+ function( $dummy, $title, &$html, &$attribs, &$query, &$options, &$ret ) {
+ $options = [ 'http' ];
+ },
+ '<a href="http://example.org/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>'
+ ],
+ // Force 'forcearticlepath' in $options
+ [
+ function( $dummy, $title, &$html, &$attribs, &$query, &$options, &$ret ) {
+ $options = [ 'forcearticlepath' ];
+ $query['foo'] = 'bar';
+ },
+ '<a href="/wiki/Special:BlankPage?foo=bar" title="Special:BlankPage">Special:BlankPage</a>'
+ ],
+ // Abort early
+ [
+ function( $dummy, $title, &$html, &$attribs, &$query, &$options, &$ret ) {
+ $ret = 'foobar';
+ return false;
+ },
+ 'foobar'
+ ],
+ ];
+ // @codingStandardsIgnoreEnd
+ }
+
+ /**
+ * @dataProvider provideLinkBeginHook
+ */
+ public function testLinkBeginHook( $callback, $expected ) {
+ $this->setMwGlobals( [
+ 'wgArticlePath' => '/wiki/$1',
+ 'wgWellFormedXml' => true,
+ 'wgServer' => '//example.org',
+ 'wgCanonicalServer' => 'http://example.org',
+ 'wgScriptPath' => '/w',
+ 'wgScript' => '/w/index.php',
+ ] );
+
+ $this->setMwGlobals( 'wgHooks', [ 'LinkBegin' => [ $callback ] ] );
+ $title = SpecialPage::getTitleFor( 'Blankpage' );
+ $out = Linker::link( $title );
+ $this->assertEquals( $expected, $out );
+ }
+
public static function provideLinkEndHook() {
return [
// Override $html
parent::setUp();
self::$users['WatchedItemIntegrationTestUser']
= new TestUser( 'WatchedItemIntegrationTestUser' );
+
+ $this->hideDeprecated( 'WatchedItem::fromUserTitle' );
+ $this->hideDeprecated( 'WatchedItem::addWatch' );
+ $this->hideDeprecated( 'WatchedItem::removeWatch' );
+ $this->hideDeprecated( 'WatchedItem::isWatched' );
+ $this->hideDeprecated( 'WatchedItem::resetNotificationTimestamp' );
+ $this->hideDeprecated( 'WatchedItem::duplicateEntries' );
+ $this->hideDeprecated( 'WatchedItem::batchAddWatch' );
}
private function getUser() {
}
public function testWatchAndUnWatchItem() {
+
$user = $this->getUser();
$title = Title::newFromText( 'WatchedItemIntegrationTestPage' );
// Cleanup after previous tests
$title = new TitleValue( $ns, $text, $fragment, $interwiki );
$this->assertEquals( $ns, $title->getNamespace() );
+ $this->assertTrue( $title->inNamespace( $ns ) );
$this->assertEquals( $text, $title->getText() );
$this->assertEquals( $fragment, $title->getFragment() );
$this->assertEquals( $hasFragment, $title->hasFragment() );