* The 'daemonized' flag must be set to true in $wgJobTypeConf for any redis
job queues. This means that mediawiki/services/jobrunner service has to
be installed and running for any such queues to work.
+* $wgAutopromoteOnce no longer supports the 'view' event. For keeping some
+ compatibility, any 'view' event triggers will still trigger on 'edit'.
=== New features in 1.25 ===
* (T64861) Updated plural rules to CLDR 26. Includes incompatible changes
* @endcode
* Where event is either:
* - 'onEdit' (when user edits)
- * - 'onView' (when user views the wiki)
*
* Criteria has the same format as $wgAutopromote
*
*/
$wgAutopromoteOnce = array(
'onEdit' => array(),
- 'onView' => array()
);
/**
* @return string Raw HTML
*/
public static function linkButton( $contents, $attrs, $modifiers = array() ) {
- return Html::element( 'a',
+ return self::element( 'a',
self::buttonAttributes( $attrs, $modifiers ),
$contents
);
public static function submitButton( $contents, $attrs, $modifiers = array() ) {
$attrs['type'] = 'submit';
$attrs['value'] = $contents;
- return Html::element( 'input', self::buttonAttributes( $attrs, $modifiers ) );
+ return self::element( 'input', self::buttonAttributes( $attrs, $modifiers ) );
}
/**
$attribs['value'] = $value;
$attribs['name'] = $name;
if ( in_array( $type, array( 'text', 'search', 'email', 'password', 'number' ) ) ) {
- $attribs = Html::getTextInputAttributes( $attribs );
+ $attribs = self::getTextInputAttributes( $attribs );
}
return self::element( 'input', $attribs );
}
} else {
$spacedValue = $value;
}
- return self::element( 'textarea', Html::getTextInputAttributes( $attribs ), $spacedValue );
+ return self::element( 'textarea', self::getTextInputAttributes( $attribs ), $spacedValue );
}
/**
} elseif ( is_int( $nsId ) ) {
$nsName = $wgContLang->convertNamespace( $nsId );
}
- $optionsHtml[] = Html::element(
+ $optionsHtml[] = self::element(
'option', array(
'disabled' => in_array( $nsId, $params['disable'] ),
'value' => $nsId,
$ret = '';
if ( isset( $params['label'] ) ) {
- $ret .= Html::element(
+ $ret .= self::element(
'label', array(
'for' => isset( $selectAttribs['id'] ) ? $selectAttribs['id'] : null,
), $params['label']
}
// Wrap options in a <select>
- $ret .= Html::openElement( 'select', $selectAttribs )
+ $ret .= self::openElement( 'select', $selectAttribs )
. "\n"
. implode( "\n", $optionsHtml )
. "\n"
- . Html::closeElement( 'select' );
+ . self::closeElement( 'select' );
return $ret;
}
$attribs['version'] = $wgHtml5Version;
}
- $html = Html::openElement( 'html', $attribs );
+ $html = self::openElement( 'html', $attribs );
if ( $html ) {
$html .= "\n";
* @return string
*/
static function infoBox( $text, $icon, $alt, $class = '' ) {
- $s = Html::openElement( 'div', array( 'class' => "mw-infobox $class" ) );
+ $s = self::openElement( 'div', array( 'class' => "mw-infobox $class" ) );
- $s .= Html::openElement( 'div', array( 'class' => 'mw-infobox-left' ) ) .
- Html::element( 'img',
+ $s .= self::openElement( 'div', array( 'class' => 'mw-infobox-left' ) ) .
+ self::element( 'img',
array(
'src' => $icon,
'alt' => $alt,
)
) .
- Html::closeElement( 'div' );
+ self::closeElement( 'div' );
- $s .= Html::openElement( 'div', array( 'class' => 'mw-infobox-right' ) ) .
+ $s .= self::openElement( 'div', array( 'class' => 'mw-infobox-right' ) ) .
$text .
- Html::closeElement( 'div' );
- $s .= Html::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
+ self::closeElement( 'div' );
+ $s .= self::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
- $s .= Html::closeElement( 'div' );
+ $s .= self::closeElement( 'div' );
- $s .= Html::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
+ $s .= self::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
return $s;
}
* @return array Array to be passed to DatabaseBase::buildLike() or false on error
*/
public static function makeLikeArray( $filterEntry, $protocol = 'http://' ) {
- $db = wfGetDB( DB_MASTER );
+ $db = wfGetDB( DB_SLAVE );
$target = $protocol . $filterEntry;
$bits = wfParseUrl( $target );
throw new PermissionsError( 'read', $permErrors );
}
- $pageView = false; // was an article or special page viewed?
-
// Interwiki redirects
if ( $title->isExternal() ) {
$rdfrom = $request->getVal( 'rdfrom' );
}
// Special pages
} elseif ( NS_SPECIAL == $title->getNamespace() ) {
- $pageView = true;
// Actions that need to be made when we have a special pages
SpecialPageFactory::executePath( $title, $this->context );
} else {
// may be a redirect to another article or URL.
$article = $this->initializeArticle();
if ( is_object( $article ) ) {
- $pageView = true;
$this->performAction( $article, $requestTitle );
} elseif ( is_string( $article ) ) {
$output->redirect( $article );
. " returned neither an object nor a URL" );
}
}
-
- if ( $pageView ) {
- // Promote user to any groups they meet the criteria for
- $user->addAutopromoteOnceGroups( 'onView' );
- }
-
}
/**
if ( $this->mQuickTouched === null ) {
$key = wfMemcKey( 'user-quicktouched', 'id', $this->mId );
$timestamp = $wgMemc->get( $key );
- if ( !$timestamp ) {
+ if ( $timestamp ) {
+ $this->mQuickTouched = $timestamp;
+ } else {
# Set the timestamp to get HTTP 304 cache hits
$this->touch();
}
* @param int|null $expire Unix timestamp (in seconds) when the cookie should expire.
* 0 (the default) causes it to expire $wgCookieExpiration seconds from now.
* null causes it to be a session cookie.
- * @param array|null $options Assoc of additional cookie options:
+ * @param array $options Assoc of additional cookie options:
* prefix: string, name prefix ($wgCookiePrefix)
* domain: string, cookie domain ($wgCookieDomain)
* path: string, cookie path ($wgCookiePath)
* 'prefix', 'domain', and 'secure'
* @since 1.22 Replaced $prefix, $domain, and $forceSecure with $options
*/
- public function setcookie( $name, $value, $expire = 0, $options = null ) {
+ public function setcookie( $name, $value, $expire = 0, $options = array() ) {
global $wgCookiePath, $wgCookiePrefix, $wgCookieDomain;
global $wgCookieSecure, $wgCookieExpiration, $wgCookieHttpOnly;
* @param string $name The name of the cookie.
* @param string $value The value to be stored in the cookie.
* @param int|null $expire Ignored in this faux subclass.
- * @param array|null $options Ignored in this faux subclass.
+ * @param array $options Ignored in this faux subclass.
*/
- public function setcookie( $name, $value, $expire = 0, $options = null ) {
+ public function setcookie( $name, $value, $expire = 0, $options = array() ) {
$this->cookies[$name] = $value;
}
$result_array['wikitext'] = array();
ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
}
- if ( !is_null( $params['summary'] ) ) {
+ if ( !is_null( $params['summary'] ) ||
+ ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
+ ) {
$result_array['parsedsummary'] = array();
- ApiResult::setContent(
- $result_array['parsedsummary'],
- Linker::formatComment( $params['summary'], $titleObj )
- );
+ ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
}
$result->addValue( null, $this->getModuleName(), $result_array );
ApiResult::setContent( $result_array['text'], $p_result->getText() );
}
- if ( !is_null( $params['summary'] ) ) {
+ if ( !is_null( $params['summary'] ) ||
+ ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
+ ) {
$result_array['parsedsummary'] = array();
- ApiResult::setContent(
- $result_array['parsedsummary'],
- Linker::formatComment( $params['summary'], $titleObj )
- );
+ ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
}
if ( isset( $prop['langlinks'] ) ) {
return $section;
}
+ /**
+ * This mimicks the behavior of EditPage in formatting a summary
+ *
+ * @param Title $title of the page being parsed
+ * @param Array $params the API parameters of the request
+ * @return Content|bool
+ */
+ private function formatSummary( $title, $params ) {
+ global $wgParser;
+ $summary = !is_null( $params['summary'] ) ? $params['summary'] : '';
+ $sectionTitle = !is_null( $params['sectiontitle'] ) ? $params['sectiontitle'] : '';
+
+ if ( $this->section === 'new' && ( $sectionTitle === '' || $summary === '' ) ) {
+ if( $sectionTitle !== '' ) {
+ $summary = $params['sectiontitle'];
+ }
+ if ( $summary !== '' ) {
+ $summary = wfMessage( 'newsectionsummary' )->rawParams( $wgParser->stripSectionName( $summary ) )
+ ->inContentLanguage()->text();
+ }
+ }
+ return Linker::formatComment( $summary, $title, $this->section === 'new' );
+ }
+
private function formatLangLinks( $links ) {
$result = array();
foreach ( $links as $link ) {
*
* @param string $message
* @param array $context
+ * @return string Interpolated message
*/
public static function interpolate( $message, array $context ) {
if ( strpos( $message, '{' ) !== false ) {
* - HOST: IPv4, IPv6 or hostname
* - PORT: server port
* - PREFIX: optional (but recommended) prefix telling udp2log how to route
- * the log event
+ * the log event. The special prefix "{channel}" will use the log event's
+ * channel as the prefix value.
*
* When not targeting a udp2log stream this class will act as a drop-in
* replacement for Monolog's StreamHandler.
// Clean it up for the multiplexer
if ( $this->prefix !== '' ) {
- $text = preg_replace( '/^/m', "{$this->prefix} ", $text );
+ $leader = ( $this->prefix === '{channel}' ) ?
+ $record['channel'] : $this->prefix;
+ $text = preg_replace( '/^/m', "{$leader} ", $text );
// Limit to 64KB
if ( strlen( $text ) > 65506 ) {
// Promote user to any groups they meet the criteria for
$dbw->onTransactionIdle( function () use ( $user ) {
$user->addAutopromoteOnceGroups( 'onEdit' );
+ $user->addAutopromoteOnceGroups( 'onView' ); // b/c
} );
return $status;
/**
* @param ScopedCallback $section
*/
- public function scopedProfileOut( ScopedCallback &$section ) {
+ public function scopedProfileOut( ScopedCallback &$section = null ) {
$section = null;
}
*/
class ProfilerStub extends Profiler {
public function scopedProfileIn( $section ) {
- return new ScopedCallback( null ); // no-op
+ return null; // no-op
}
public function getFunctionStats() {
<?php
echo Html::submitButton(
$this->getMsg( $this->data['loggedin'] ? 'createacct-another-submit' : 'createacct-submit' ),
- $attrs = array(
+ array(
'id' => 'wpCreateaccount',
'name' => 'wpCreateaccount',
'tabindex' => $tabIndex++
'scripts' => array(
'resources/src/mediawiki/mediawiki.confirmCloseWindow.js',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'mediawiki.debug' => array(
'scripts' => array(
public function getProperty() {
return $this->property;
}
+
+ protected function whatSecondArg( $a, $b = false ) {
+ return $b;
+ }
}
$classReflection = new ReflectionClass( $this->object );
$methodReflection = $classReflection->getMethod( $method );
$methodReflection->setAccessible( true );
- return $methodReflection->invoke( $this->object, $args );
+ return $methodReflection->invokeArgs( $this->object, $args );
}
public function __set( $name, $value ) {
$this->assertSame( 2, $this->wrapped->property );
$this->assertSame( 2, $this->raw->getProperty() );
}
+
+ function testCallMethodTwoArgs() {
+ $this->assertSame( 'two', $this->wrapped->whatSecondArg( 'one', 'two' ) );
+ }
}