* @param int $botMax Maximum value for sysops/bots
* @param bool $enforceLimits Whether to enforce (die) if value is outside limits
*/
- protected function validateLimit( $paramName, &$value, $min, $max, $botMax = null, $enforceLimits = false ) {
+ protected function validateLimit( $paramName, &$value, $min, $max, $botMax = null,
+ $enforceLimits = false
+ ) {
if ( !is_null( $min ) && $value < $min ) {
$msg = $this->encodeParamName( $paramName ) . " may not be less than $min (set to $value)";
$this->warnOrDie( $msg, $enforceLimits );
'createaccount-title',
'createaccount-text'
) );
- } elseif ( $this->getConfig()->get( 'EmailAuthentication' ) && Sanitizer::validateEmail( $user->getEmail() ) ) {
+ } elseif ( $this->getConfig()->get( 'EmailAuthentication' ) &&
+ Sanitizer::validateEmail( $user->getEmail() )
+ ) {
// Send out an email authentication message if needed
$status->merge( $user->sendConfirmationMail() );
}
}
$msg = wfMessage( 'Contributions' )->inContentLanguage()->text();
- $feedTitle = $config->get( 'Sitename' ) . ' - ' . $msg . ' [' . $config->get( 'LanguageCode' ) . ']';
+ $feedTitle = $config->get( 'Sitename' ) . ' - ' . $msg .
+ ' [' . $config->get( 'LanguageCode' ) . ']';
$feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL();
$target = $params['user'] == 'newbies'
break;
default:
- $this->dieUsage( __METHOD__ . ': Unknown value for \'formatversion\'', 'unknownformatversion' );
+ $this->dieUsage( __METHOD__ .
+ ': Unknown value for \'formatversion\'', 'unknownformatversion' );
}
}
$data = $this->getResult()->getResultData( null, $transform );
$submodules[] = $manager->getModule( $name );
}
}
- $help['submodules'] .= self::getHelpInternal( $context, $submodules, $suboptions, $haveModules );
+ $help['submodules'] .= self::getHelpInternal(
+ $context,
+ $submodules,
+ $suboptions,
+ $haveModules
+ );
$numSubmodules = count( $submodules );
}
$response->header( "Access-Control-Allow-Origin: $originHeader" );
$response->header( 'Access-Control-Allow-Credentials: true' );
- $response->header( "Timing-Allow-Origin: $originHeader" ); # http://www.w3.org/TR/resource-timing/#timing-allow-origin
+ // http://www.w3.org/TR/resource-timing/#timing-allow-origin
+ $response->header( "Timing-Allow-Origin: $originHeader" );
if ( !$preflight ) {
- $response->header( 'Access-Control-Expose-Headers: MediaWiki-API-Error, Retry-After, X-Database-Lag' );
+ $response->header(
+ 'Access-Control-Expose-Headers: MediaWiki-API-Error, Retry-After, X-Database-Lag'
+ );
}
}
)
) {
$this->dieUsage(
- "The '{$module->encodeParamName( 'token' )}' parameter was found in the query string, but must be in the POST body",
+ "The '{$module->encodeParamName( 'token' )}' parameter was " .
+ 'found in the query string, but must be in the POST body',
'mustposttoken'
);
}
$instance = call_user_func( $factory, $this->mParent, $name );
if ( !$instance instanceof $class ) {
- throw new MWException( "The factory function for module $name did not return an instance of $class!" );
+ throw new MWException(
+ "The factory function for module $name did not return an instance of $class!"
+ );
}
} else {
// create instance from class name
private $mGoodTitles = array();
private $mMissingPages = array(); // [ns][dbkey] => fake page_id
private $mMissingTitles = array();
- private $mInvalidTitles = array(); // [fake_page_id] => array( 'title' => $title, 'invalidreason' => $reason )
+ /** @var array [fake_page_id] => array( 'title' => $title, 'invalidreason' => $reason ) */
+ private $mInvalidTitles = array();
private $mMissingPageIDs = array();
private $mRedirectTitles = array();
private $mSpecialTitles = array();
ApiBase::PARAM_DFLT => 'timestamp|url',
ApiBase::PARAM_ISMULTI => true,
ApiBase::PARAM_HELP_MSG => 'apihelp-query+imageinfo-param-prop',
- ApiBase::PARAM_HELP_MSG_PER_VALUE => ApiQueryImageInfo::getPropertyMessages( $this->propertyFilter ),
+ ApiBase::PARAM_HELP_MSG_PER_VALUE =>
+ ApiQueryImageInfo::getPropertyMessages( $this->propertyFilter ),
),
'prefix' => null,
'minsize' => array(
$this->addFields( 'ipb_deleted' );
if ( $showBlockInfo ) {
- $this->addFields( array( 'ipb_id', 'ipb_by', 'ipb_by_text', 'ipb_reason', 'ipb_expiry', 'ipb_timestamp' ) );
+ $this->addFields( array(
+ 'ipb_id',
+ 'ipb_by',
+ 'ipb_by_text',
+ 'ipb_reason',
+ 'ipb_expiry',
+ 'ipb_timestamp'
+ ) );
}
// Don't show hidden names
// in the actual normalised version, only if we can actually normalise them,
// so we use the functions scope to throw away the normalisations.
if ( !$h->normaliseParams( $image, $finalParams ) ) {
- $this->dieUsage( "Could not normalise image parameters for " . $image->getName(), "urlparamnormal" );
+ $this->dieUsage( 'Could not normalise image parameters for ' .
+ $image->getName(), 'urlparamnormal' );
}
}
*/
private function getAllowedLogActions() {
$config = $this->getConfig();
- return array_keys( array_merge( $config->get( 'LogActions' ), $config->get( 'LogActionsHandlers' ) ) );
+ return array_keys( array_merge(
+ $config->get( 'LogActions' ),
+ $config->get( 'LogActionsHandlers' )
+ ) );
}
public function getCacheMode( $params ) {
$end = null;
}
- list( $left, $continue ) = $this->runQuery( $resultPageSet, $params['limit'], $start, $startId, $end );
+ list( $left, $continue ) =
+ $this->runQuery( $resultPageSet, $params['limit'], $start, $startId, $end );
if ( $end === null && $continue === null ) {
// Wrap around. We do this even if $left === 0 for continuation
// (saving a DB query in this rare case probably isn't worth the
$vals['ratelimits'] = $this->getRateLimits();
}
- if ( isset( $this->prop['realname'] ) && !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) ) ) {
+ if ( isset( $this->prop['realname'] ) &&
+ !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) )
+ ) {
$vals['realname'] = $user->getRealName();
}
$this->mParams = $this->extractRequestParams();
$request = $this->getMain()->getRequest();
// Check if async mode is actually supported (jobs done in cli mode)
- $this->mParams['async'] = ( $this->mParams['async'] && $this->getConfig()->get( 'EnableAsyncUploads' ) );
+ $this->mParams['async'] = ( $this->mParams['async'] &&
+ $this->getConfig()->get( 'EnableAsyncUploads' ) );
// Add the uploaded file to the params array
$this->mParams['file'] = $request->getFileName( 'file' );
$this->mParams['chunk'] = $request->getFileName( 'chunk' );
switch ( $exceptionType ) {
case 'UploadStashFileNotFoundException':
- $this->dieUsage( 'Could not find the file in the stash: ' . $e->getMessage(), 'stashedfilenotfound' );
+ $this->dieUsage(
+ 'Could not find the file in the stash: ' . $e->getMessage(),
+ 'stashedfilenotfound'
+ );
break;
case 'UploadStashBadPathException':
- $this->dieUsage( 'File key of improper format or otherwise invalid: ' . $e->getMessage(), 'stashpathinvalid' );
+ $this->dieUsage(
+ 'File key of improper format or otherwise invalid: ' . $e->getMessage(),
+ 'stashpathinvalid'
+ );
break;
case 'UploadStashFileException':
- $this->dieUsage( 'Could not store upload in the stash: ' . $e->getMessage(), 'stashfilestorage' );
+ $this->dieUsage(
+ 'Could not store upload in the stash: ' . $e->getMessage(),
+ 'stashfilestorage'
+ );
break;
case 'UploadStashZeroLengthFileException':
- $this->dieUsage( 'File is of zero length, and could not be stored in the stash: ' . $e->getMessage(), 'stashzerolength' );
+ $this->dieUsage(
+ 'File is of zero length, and could not be stored in the stash: ' .
+ $e->getMessage(),
+ 'stashzerolength'
+ );
break;
case 'UploadStashNotLoggedInException':
$this->dieUsage( 'Not logged in: ' . $e->getMessage(), 'stashnotloggedin' );
$saveSuccess = $this->saveToCaches( $cache, 'all', $code );
if ( !$saveSuccess ) {
- # Cache save has failed.
- # There are two main scenarios where this could be a problem:
- #
- # - The cache is more than the maximum size (typically
- # 1MB compressed).
- #
- # - Memcached has no space remaining in the relevant slab
- # class. This is unlikely with recent versions of
- # memcached.
- #
- # Either way, if there is a local cache, nothing bad will
- # happen. If there is no local cache, disabling the message
- # cache for all requests avoids incurring a loadFromDB()
- # overhead on every request, and thus saves the wiki from
- # complete downtime under moderate traffic conditions.
+ /**
+ * Cache save has failed.
+ *
+ * There are two main scenarios where this could be a problem:
+ * - The cache is more than the maximum size (typically 1MB compressed).
+ * - Memcached has no space remaining in the relevant slab class. This is
+ * unlikely with recent versions of memcached.
+ *
+ * Either way, if there is a local cache, nothing bad will happen. If there
+ * is no local cache, disabling the message cache for all requests avoids
+ * incurring a loadFromDB() overhead on every request, and thus saves the
+ * wiki from complete downtime under moderate traffic conditions.
+ */
if ( !$wgUseLocalMessageCache ) {
$this->mMemc->set( $statusKey, 'error', 60 * 5 );
$where[] = 'could not save cache, disabled globally for 5 minutes';
# Strip all remaining non-search characters
$text = preg_replace( "/[^{$lc}]+/", " ", $text );
- # Handle 's, s'
- #
- # $text = preg_replace( "/([{$lc}]+)'s /", "\\1 \\1's ", $text );
- # $text = preg_replace( "/([{$lc}]+)s' /", "\\1s ", $text );
- #
- # These tail-anchored regexps are insanely slow. The worst case comes
- # when Japanese or Chinese text (ie, no word spacing) is written on
- # a wiki configured for Western UTF-8 mode. The Unicode characters are
- # expanded to hex codes and the "words" are very long paragraph-length
- # monstrosities. On a large page the above regexps may take over 20
- # seconds *each* on a 1GHz-level processor.
- #
- # Following are reversed versions which are consistently fast
- # (about 3 milliseconds on 1GHz-level processor).
- #
+ /**
+ * Handle 's, s'
+ *
+ * $text = preg_replace( "/([{$lc}]+)'s /", "\\1 \\1's ", $text );
+ * $text = preg_replace( "/([{$lc}]+)s' /", "\\1s ", $text );
+ *
+ * These tail-anchored regexps are insanely slow. The worst case comes
+ * when Japanese or Chinese text (ie, no word spacing) is written on
+ * a wiki configured for Western UTF-8 mode. The Unicode characters are
+ * expanded to hex codes and the "words" are very long paragraph-length
+ * monstrosities. On a large page the above regexps may take over 20
+ * seconds *each* on a 1GHz-level processor.
+ *
+ * Following are reversed versions which are consistently fast
+ * (about 3 milliseconds on 1GHz-level processor).
+ */
$text = strrev( preg_replace( "/ s'([{$lc}]+)/", " s'\\1 \\1", strrev( $text ) ) );
$text = strrev( preg_replace( "/ 's([{$lc}]+)/", " s\\1", strrev( $text ) ) );
}
if ( !is_null( $this->articleUrl ) ) {
# "http://example.com/wiki/$1"
- #
# We use "Image:" as the canonical namespace for
# compatibility across all MediaWiki versions.
return str_replace( '$1',
}
if ( !is_null( $this->scriptDirUrl ) ) {
# "http://example.com/w"
- #
# We use "Image:" as the canonical namespace for
# compatibility across all MediaWiki versions,
# and just sort of hope index.php is right. ;)
// Lock the filearchive rows so that the files don't get deleted by a cleanup operation
// We acquire this lock by running the inserts now, before the file operations.
- //
// This potentially has poor lock contention characteristics -- an alternative
// scheme would be to insert stub filearchive entries with no fa_name and commit
// them in a separate transaction, then run the file ops, then update the fa_name fields.
$attr['id'] = $this->mID;
$attr['name'] = $this->mName;
- $attr += $this->getAttributes( array( 'disabled', 'tabindex' ), array( 'tabindex' => 'tabIndex' ) );
+ $attr += $this->getAttributes(
+ array( 'disabled', 'tabindex' ),
+ array( 'tabindex' => 'tabIndex' )
+ );
if ( $this->mClass !== '' ) {
$attr['classes'] = array( $this->mClass );
$html = Xml::fieldset( $legend, $html );
}
- return Html::rawElement( 'form', $this->getFormAttributes() + array( 'class' => 'visualClear' ), $html );
+ return Html::rawElement(
+ 'form',
+ $this->getFormAttributes() + array( 'class' => 'visualClear' ),
+ $html
+ );
}
/**
* Returns the given attributes from the parameters
*
* @param array $list List of attributes to get
- * @param array $mappings Optional - Key/value map of attribute names to use instead of the ones passed in
+ * @param array $mappings Optional - Key/value map of attribute names to use
+ * instead of the ones passed in.
* @return array Attributes
*/
public function getAttributes( array $list, array $mappings = null ) {
}
$text = $title->getPrefixedText();
- if ( $this->mParams['namespace'] !== false && !$title->inNamespace( $this->mParams['namespace'] ) ) {
+ if ( $this->mParams['namespace'] !== false &&
+ !$title->inNamespace( $this->mParams['namespace'] )
+ ) {
return $this->msg( 'htmlform-title-badnamespace', $this->mParams['namespace'], $text )->parse();
}
*/
protected $displayFormat = 'ooui';
- public static function loadInputFromParameters( $fieldname, $descriptor, HTMLForm $parent = null ) {
+ public static function loadInputFromParameters( $fieldname, $descriptor,
+ HTMLForm $parent = null
+ ) {
$field = parent::loadInputFromParameters( $fieldname, $descriptor, $parent );
$field->setShowEmptyLabel( false );
return $field;
return true;
}
- public static function loadInputFromParameters( $fieldname, $descriptor, HTMLForm $parent = null ) {
+ public static function loadInputFromParameters( $fieldname, $descriptor,
+ HTMLForm $parent = null
+ ) {
$field = parent::loadInputFromParameters( $fieldname, $descriptor, $parent );
$field->setShowEmptyLabel( false );
return $field;
function submitConnectForm() {
// Get variables from the request
- $newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBport', 'wgDBname', 'wgDBmwschema' ) );
+ $newValues = $this->setVarsFromRequest( array(
+ 'wgDBserver',
+ 'wgDBport',
+ 'wgDBname',
+ 'wgDBmwschema'
+ ) );
// Validate them
$status = Status::newGood();
array( 'addPgIndex', 'recentchanges', 'rc_timestamp_bot', '(rc_timestamp) WHERE rc_bot = 0' ),
array( 'addPgIndex', 'templatelinks', 'templatelinks_from', '(tl_from)' ),
array( 'addPgIndex', 'watchlist', 'wl_user', '(wl_user)' ),
- array( 'addPgIndex', 'watchlist', 'wl_user_notificationtimestamp', '(wl_user, wl_notificationtimestamp)' ),
+ array( 'addPgIndex', 'watchlist', 'wl_user_notificationtimestamp',
+ '(wl_user, wl_notificationtimestamp)' ),
array( 'addPgIndex', 'logging', 'logging_user_type_time',
'(log_user, log_type, log_timestamp)' ),
array( 'addPgIndex', 'logging', 'logging_page_id_time', '(log_page,log_timestamp)' ),
$this->output( "...bug 66650 already fixed or not applicable.\n" );
return true;
};
- $this->applyPatch( 'patch-textsearch_bug66650.sql', false, "Rebuilding text search for bug 66650" );
+ $this->applyPatch( 'patch-textsearch_bug66650.sql', false,
+ 'Rebuilding text search for bug 66650' );
}
}
// 1.24
array( 'addField', 'page_props', 'pp_sortkey', 'patch-pp_sortkey.sql' ),
array( 'dropField', 'recentchanges', 'rc_cur_time', 'patch-drop-rc_cur_time.sql' ),
- array( 'addIndex', 'watchlist', 'wl_user_notificationtimestamp', 'patch-watchlist-user-notificationtimestamp-index.sql' ),
+ array( 'addIndex', 'watchlist', 'wl_user_notificationtimestamp',
+ 'patch-watchlist-user-notificationtimestamp-index.sql' ),
array( 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql' ),
array( 'addField', 'pagelinks', 'pl_from_namespace', 'patch-pl_from_namespace.sql' ),
array( 'addField', 'templatelinks', 'tl_from_namespace', 'patch-tl_from_namespace.sql' ),
* var: The variable to be configured (required)
* label: The message name for the label (required)
* itemLabelPrefix: The message name prefix for the item labels (required)
- * itemLabels: List of message names to use for the item labels instead of itemLabelPrefix, keyed by values
+ * itemLabels: List of message names to use for the item labels instead
+ * of itemLabelPrefix, keyed by values
* values: List of allowed values (required)
* itemAttribs: Array of attribute arrays, outer key is the value name (optional)
* commonAttribs: Attribute array applied to all items
if ( $status === 200 || $status === 301 || $status === 302 || $status === 400 ) {
return true;
} elseif ( $status ) {
- $this->setLastError( __METHOD__ . ': incorrect HTTP status ' . $status . ' when hitting ' . $thumbUrl );
+ $this->setLastError( __METHOD__ . ': incorrect HTTP status ' .
+ $status . ' when hitting ' . $thumbUrl );
return false;
} else {
$this->setLastError( __METHOD__ . ': HTTP request failure' );
return false;
}
} else {
- $this->setLastError( __METHOD__ . ': unknown thumbnail render method ' . $wgUploadThumbnailRenderMethod );
+ $this->setLastError( __METHOD__ . ': unknown thumbnail render method ' .
+ $wgUploadThumbnailRenderMethod );
return false;
}
} else {
}
}
- # Using the (log_namespace, log_title, log_timestamp) index with a
- # range scan (LIKE) on the first two parts, instead of simple equality,
- # makes it unusable for sorting. Sorted retrieval using another index
- # would be possible, but then we might have to scan arbitrarily many
- # nodes of that index. Therefore, we need to avoid this if $wgMiserMode
- # is on.
- #
- # This is not a problem with simple title matches, because then we can
- # use the page_time index. That should have no more than a few hundred
- # log entries for even the busiest pages, so it can be safely scanned
- # in full to satisfy an impossible condition on user or similar.
+ /**
+ * Using the (log_namespace, log_title, log_timestamp) index with a
+ * range scan (LIKE) on the first two parts, instead of simple equality,
+ * makes it unusable for sorting. Sorted retrieval using another index
+ * would be possible, but then we might have to scan arbitrarily many
+ * nodes of that index. Therefore, we need to avoid this if $wgMiserMode
+ * is on.
+ *
+ * This is not a problem with simple title matches, because then we can
+ * use the page_time index. That should have no more than a few hundred
+ * log entries for even the busiest pages, so it can be safely scanned
+ * in full to satisfy an impossible condition on user or similar.
+ */
$this->mConds['log_namespace'] = $ns;
if ( $doUserRightsLogLike ) {
$params = array( $name . $wgUserrightsInterwikiDelimiter );
$watchers = self::updateWatchlistTimestamp( $editor, $title, $timestamp );
$sendEmail = true;
+ // $watchers deals with $wgEnotifWatchlist.
// If nobody is watching the page, and there are no users notified on all changes
// don't bother creating a job/trying to send emails, unless it's a
// talk page with an applicable notification.
- //
- // $watchers deals with $wgEnotifWatchlist
if ( !count( $watchers ) && !count( $wgUsersNotifiedOnAllChanges ) ) {
$sendEmail = false;
// Only send notification for non minor edits, unless $wgEnotifMinorEdits
return Status::newFatal( 'user-mail-no-addy' );
}
- // Forge email headers
- // -------------------
- //
- // WARNING
- //
- // DO NOT add To: or Subject: headers at this step. They need to be
- // handled differently depending upon the mailer we are going to use.
- //
- // To:
- // PHP mail() first argument is the mail receiver. The argument is
- // used as a recipient destination and as a To header.
- //
- // PEAR mailer has a recipient argument which is only used to
- // send the mail. If no To header is given, PEAR will set it to
- // to 'undisclosed-recipients:'.
- //
- // NOTE: To: is for presentation, the actual recipient is specified
- // by the mailer using the Rcpt-To: header.
- //
- // Subject:
- // PHP mail() second argument to pass the subject, passing a Subject
- // as an additional header will result in a duplicate header.
- //
- // PEAR mailer should be passed a Subject header.
- //
- // -- hashar 20120218
+ /**
+ * Forge email headers
+ * -------------------
+ *
+ * WARNING
+ *
+ * DO NOT add To: or Subject: headers at this step. They need to be
+ * handled differently depending upon the mailer we are going to use.
+ *
+ * To:
+ * PHP mail() first argument is the mail receiver. The argument is
+ * used as a recipient destination and as a To header.
+ *
+ * PEAR mailer has a recipient argument which is only used to
+ * send the mail. If no To header is given, PEAR will set it to
+ * to 'undisclosed-recipients:'.
+ *
+ * NOTE: To: is for presentation, the actual recipient is specified
+ * by the mailer using the Rcpt-To: header.
+ *
+ * Subject:
+ * PHP mail() second argument to pass the subject, passing a Subject
+ * as an additional header will result in a duplicate header.
+ *
+ * PEAR mailer should be passed a Subject header.
+ *
+ * -- hashar 20120218
+ */
$headers['From'] = $from->toString();
$returnPath = $from->address;
MediaWiki\restoreWarnings();
return Status::newGood();
} else {
- //
// PHP mail()
- //
if ( count( $to ) > 1 ) {
$headers['To'] = 'undisclosed-recipients:;';
}
*/
protected function transformGd( $image, $params ) {
# Use PHP's builtin GD library functions.
- #
# First find out what kind of file this is, and select the correct
# input routine for this.
$binaryHeader = fread( $f, 26 );
fclose( $f );
- # Master image structure:
- #
- # byte[9] "gimp xcf " File type magic
- # byte[4] version XCF version
- # "file" - version 0
- # "v001" - version 1
- # "v002" - version 2
- # byte 0 Zero-terminator for version tag
- # uint32 width With of canvas
- # uint32 height Height of canvas
- # uint32 base_type Color mode of the image; one of
- # 0: RGB color
- # 1: Grayscale
- # 2: Indexed color
- # (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
+ /**
+ * Master image structure:
+ *
+ * byte[9] "gimp xcf " File type magic
+ * byte[4] version XCF version
+ * "file" - version 0
+ * "v001" - version 1
+ * "v002" - version 2
+ * byte 0 Zero-terminator for version tag
+ * uint32 width With of canvas
+ * uint32 height Height of canvas
+ * uint32 base_type Color mode of the image; one of
+ * 0: RGB color
+ * 1: Grayscale
+ * 2: Indexed color
+ * (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h)
+ */
try {
$header = wfUnpack(
"A9magic" . # A: space padded
// immediately following the StandardXMP. However, the JPEG standard
// does not require preservation of marker segment order. A robust JPEG
// reader should tolerate the marker segments in any order."
- //
- // otoh the probability that an image will have more than 128k of
- // metadata is rather low... so the probability that it will have
+ // On the other hand, the probability that an image will have more than
+ // 128k of metadata is rather low... so the probability that it will have
// > 128k, and be in the wrong order is very low...
if ( $len['offset'] !== $this->extendedXMPOffset ) {
// In practise I have yet to see a file that
// uses this element, however it is mentioned
// on page 25 of part 1 of the xmp standard.
- //
- // also it seems as if exiv2 and exiftool do not support
+ // Also it seems as if exiv2 and exiftool do not support
// this either (That or I misunderstand the standard)
$this->logger->info( __METHOD__ . ' Encountered <rdf:type> which isn\'t currently supported' );
}
if ( $rt->isExternal() ) {
if ( $rt->isLocal() ) {
// Offsite wikis need an HTTP redirect.
- //
// This can be hard to reverse and may produce loops,
// so they may be disabled in the site configuration.
$source = $this->mTitle->getFullURL( 'redirect=no' );
if ( $rt->isSpecialPage() ) {
// Gotta handle redirects to special pages differently:
- // Fill the HTTP response "Location" header and ignore
- // the rest of the page we're on.
- //
- // Some pages are not valid targets
+ // Fill the HTTP response "Location" header and ignore the rest of the page we're on.
+ // Some pages are not valid targets.
if ( $rt->isValidRedirectTarget() ) {
return $rt->getFullURL();
} else {
}
$revisionId = $revision->insertOn( $dbw );
- // Update page
- //
+ // Update page.
// We check for conflicts by comparing $oldid with the current latest revision ID.
$ok = $this->updateRevisionOn( $dbw, $revision, $oldid, $oldIsRedirect );
$bitfield = 'rev_deleted';
}
- // For now, shunt the revision data into the archive table.
- // Text is *not* removed from the text table; bulk storage
- // is left intact to avoid breaking block-compression or
- // immutable storage schemes.
- //
- // For backwards compatibility, note that some older archive
- // table entries will have ar_text and ar_flags fields still.
- //
- // In the future, we may keep revisions and mark them with
- // the rev_deleted field, which is reserved for this purpose.
+ /**
+ * For now, shunt the revision data into the archive table.
+ * Text is *not* removed from the text table; bulk storage
+ * is left intact to avoid breaking block-compression or
+ * immutable storage schemes.
+ *
+ * For backwards compatibility, note that some older archive
+ * table entries will have ar_text and ar_flags fields still.
+ *
+ * In the future, we may keep revisions and mark them with
+ * the rev_deleted field, which is reserved for this purpose.
+ */
$row = array(
'ar_namespace' => 'page_namespace',
* @ingroup Parser
*/
class ParserOutput extends CacheTime {
- public $mText, # The output text
- $mLanguageLinks, # List of the full text of language links, in the order they appear
- $mCategories, # Map of category names to sort keys
- $mIndicators = array(), # Page status indicators, usually displayed in top-right corner
- $mTitleText, # title text of the chosen language variant
- $mLinks = array(), # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken.
- $mTemplates = array(), # 2-D map of NS/DBK to ID for the template references. ID=zero for broken.
- $mTemplateIds = array(), # 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken.
- $mImages = array(), # DB keys of the images used, in the array key only
- $mFileSearchOptions = array(), # DB keys of the images used mapped to sha1 and MW timestamp
- $mExternalLinks = array(), # External link URLs, in the key only
- $mInterwikiLinks = array(), # 2-D map of prefix/DBK (in keys only) for the inline interwiki links in the document.
- $mNewSection = false, # Show a new section link?
- $mHideNewSection = false, # Hide the new section link?
- $mNoGallery = false, # No gallery on category page? (__NOGALLERY__)
- $mHeadItems = array(), # Items to put in the <head> section
- $mModules = array(), # Modules to be loaded by the resource loader
- $mModuleScripts = array(), # Modules of which only the JS will be loaded by the resource loader
- $mModuleStyles = array(), # Modules of which only the CSSS will be loaded by the resource loader
- $mJsConfigVars = array(), # JavaScript config variable for mw.config combined with this page
- $mOutputHooks = array(), # Hook tags as per $wgParserOutputHooks
- $mWarnings = array(), # Warning text to be returned to the user. Wikitext formatted, in the key only
- $mSections = array(), # Table of contents
- $mEditSectionTokens = false, # prefix/suffix markers if edit sections were output as tokens
- $mProperties = array(), # Name/value pairs to be cached in the DB
- $mTOCHTML = '', # HTML of the TOC
- $mTimestamp, # Timestamp of the revision
- $mTOCEnabled = true, # Whether TOC should be shown, can't override __NOTOC__
- $mEnableOOUI = false; # Whether OOUI should be enabled
- private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other value will result in no change.
- private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
- private $mExtensionData = array(); # extra data used by extensions
- private $mLimitReportData = array(); # Parser limit report data
- private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
- private $mPreventClickjacking = false; # Whether to emit X-Frame-Options: DENY
- private $mFlags = array(); # Generic flags
+ /**
+ * @var string $mText The output text
+ */
+ public $mText;
+
+ /**
+ * @var array $mLanguageLinks List of the full text of language links,
+ * in the order they appear.
+ */
+ public $mLanguageLinks;
+
+ /**
+ * @var array $mCategoriesMap of category names to sort keys
+ */
+ public $mCategories;
+
+ /**
+ * @var array $mIndicators Page status indicators, usually displayed in top-right corner.
+ */
+ public $mIndicators = array();
+
+ /**
+ * @var string $mTitleText Title text of the chosen language variant
+ */
+ public $mTitleText;
+
+ /**
+ * @var array $mLinks 2-D map of NS/DBK to ID for the links in the document.
+ * ID=zero for broken.
+ */
+ public $mLinks = array();
+
+ /**
+ * @var array $mTemplates 2-D map of NS/DBK to ID for the template references.
+ * ID=zero for broken.
+ */
+ public $mTemplates = array();
+
+ /**
+ * @var array $mTemplateIds 2-D map of NS/DBK to rev ID for the template references.
+ * ID=zero for broken.
+ */
+ public $mTemplateIds = array();
+
+ /**
+ * @var array $mImages DB keys of the images used, in the array key only
+ */
+ public $mImages = array();
+
+ /**
+ * @var array $mFileSearchOptions DB keys of the images used mapped to sha1 and MW timestamp.
+ */
+ public $mFileSearchOptions = array();
+
+ /**
+ * @var array $mExternalLinks External link URLs, in the key only.
+ */
+ public $mExternalLinks = array();
+
+ /**
+ * @var array $mInterwikiLinks 2-D map of prefix/DBK (in keys only)
+ * for the inline interwiki links in the document.
+ */
+ public $mInterwikiLinks = array();
+
+ /**
+ * @var bool $mNewSection Show a new section link?
+ */
+ public $mNewSection = false;
+
+ /**
+ * @var bool $mHideNewSection Hide the new section link?
+ */
+ public $mHideNewSection = false;
+
+ /**
+ * @var bool $mNoGallery No gallery on category page? (__NOGALLERY__).
+ */
+ public $mNoGallery = false;
+
+ /**
+ * @var array $mHeadItems Items to put in the <head> section
+ */
+ public $mHeadItems = array();
+
+ /**
+ * @var array $mModules Modules to be loaded by the resource loader
+ */
+ public $mModules = array();
+
+ /**
+ * @var array $mModuleScripts Modules of which only the JS will be loaded by
+ * the resource loader.
+ */
+ public $mModuleScripts = array();
+
+ /**
+ * @var array $mModuleStyles Modules of which only the CSSS will be loaded by
+ * the resource loader.
+ */
+ public $mModuleStyles = array();
+
+ /**
+ * @var array $mJsConfigVars JavaScript config variable for mw.config combined with this page.
+ */
+ public $mJsConfigVars = array();
+
+ /**
+ * @var array $mOutputHooks Hook tags as per $wgParserOutputHooks.
+ */
+ public $mOutputHooks = array();
+
+ /**
+ * @var array $mWarnings Warning text to be returned to the user.
+ * Wikitext formatted, in the key only.
+ */
+ public $mWarnings = array();
+
+ /**
+ * @var array $mSections Table of contents
+ */
+ public $mSections = array();
+
+ /**
+ * @var bool $mEditSectionTokens prefix/suffix markers if edit sections were output as tokens.
+ */
+ public $mEditSectionTokens = false;
+
+ /**
+ * @var array $mProperties Name/value pairs to be cached in the DB.
+ */
+ public $mProperties = array();
+
+ /**
+ * @var string $mTOCHTML HTML of the TOC.
+ */
+ public $mTOCHTML = '';
+
+ /**
+ * @var string $mTimestamp Timestamp of the revision.
+ */
+ public $mTimestamp;
+
+ /**
+ * @var bool $mTOCEnabled Whether TOC should be shown, can't override __NOTOC__.
+ */
+ public $mTOCEnabled = true;
+
+ /**
+ * @var bool $mEnableOOUI Whether OOUI should be enabled.
+ */
+ public $mEnableOOUI = false;
+
+ /**
+ * @var string $mIndexPolicy 'index' or 'noindex'? Any other value will result in no change.
+ */
+ private $mIndexPolicy = '';
+
+ /**
+ * @var array $mAccessedOptions List of ParserOptions (stored in the keys).
+ */
+ private $mAccessedOptions = array();
+
+ /**
+ * @var array $mExtensionData extra data used by extensions.
+ */
+ private $mExtensionData = array();
+
+ /**
+ * @var array $mLimitReportData Parser limit report data.
+ */
+ private $mLimitReportData = array();
+
+ /**
+ * @var array $mParseStartTime Timestamps for getTimeSinceStart().
+ */
+ private $mParseStartTime = array();
+
+ /**
+ * @var bool $mPreventClickjacking Whether to emit X-Frame-Options: DENY.
+ */
+ private $mPreventClickjacking = false;
+
+ /**
+ * @var array $mFlags Generic flags.
+ */
+ private $mFlags = array();
const EDITSECTION_REGEX =
'#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#';
*/
public function addSecondaryDataUpdate( DataUpdate $update ) {
wfDeprecated( __METHOD__, '1.25' );
- throw new MWException( 'ParserOutput::addSecondaryDataUpdate() is no longer supported. Override Content::getSecondaryDataUpdates() or use the SecondaryDataUpdates hook instead.' );
+ throw new MWException(
+ 'ParserOutput::addSecondaryDataUpdate() is no longer supported. ' .
+ 'Override Content::getSecondaryDataUpdates() ' .
+ 'or use the SecondaryDataUpdates hook instead.'
+ );
}
/**
* @return string|bool PNG image data, or false on failure
*/
protected function rasterize( $svg ) {
- // This code should be factored out to a separate method on SvgHandler, or perhaps a separate
- // class, with a separate set of configuration settings.
- //
- // This is a distinct use case from regular SVG rasterization:
- // * We can skip many sanity and security checks (as the images come from a trusted source,
- // rather than from the user).
- // * We need to provide extra options to some converters to achieve acceptable quality for very
- // small images, which might cause performance issues in the general case.
- // * We want to directly pass image data to the converter, rather than a file path.
- //
- // See https://phabricator.wikimedia.org/T76473#801446 for examples of what happens with the
- // default settings.
- //
- // For now, we special-case rsvg (used in WMF production) and do a messy workaround for other
- // converters.
+ /**
+ * This code should be factored out to a separate method on SvgHandler, or perhaps a separate
+ * class, with a separate set of configuration settings.
+ *
+ * This is a distinct use case from regular SVG rasterization:
+ * * We can skip many sanity and security checks (as the images come from a trusted source,
+ * rather than from the user).
+ * * We need to provide extra options to some converters to achieve acceptable quality for very
+ * small images, which might cause performance issues in the general case.
+ * * We want to directly pass image data to the converter, rather than a file path.
+ *
+ * See https://phabricator.wikimedia.org/T76473#801446 for examples of what happens with the
+ * default settings.
+ *
+ * For now, we special-case rsvg (used in WMF production) and do a messy workaround for other
+ * converters.
+ */
global $wgSVGConverter, $wgSVGConverterPath;
// section link
if ( $showNewSection ) {
// Adds new section link
- //$content_navigation['actions']['addsection']
+ // $content_navigation['actions']['addsection']
$content_navigation['views']['addsection'] = array(
'class' => ( $isEditing && $section == 'new' ) ? 'selected' : false,
'text' => wfMessageFallback( "$skname-action-addsection", 'addsection' )
}
if ( $config->get( 'UserEmailUseReplyTo' ) ) {
- // Put the generic wiki autogenerated address in the From:
- // header and reserve the user for Reply-To.
- //
- // This is a bit ugly, but will serve to differentiate
- // wiki-borne mails from direct mails and protects against
- // SPF and bounce problems with some mailers (see below).
+ /**
+ * Put the generic wiki autogenerated address in the From:
+ * header and reserve the user for Reply-To.
+ *
+ * This is a bit ugly, but will serve to differentiate
+ * wiki-borne mails from direct mails and protects against
+ * SPF and bounce problems with some mailers (see below).
+ */
$mailFrom = new MailAddress( $config->get( 'PasswordSender' ),
wfMessage( 'emailsender' )->inContentLanguage()->text() );
$replyTo = $from;
} else {
- // Put the sending user's e-mail address in the From: header.
- //
- // This is clean-looking and convenient, but has issues.
- // One is that it doesn't as clearly differentiate the wiki mail
- // from "directly" sent mails.
- //
- // Another is that some mailers (like sSMTP) will use the From
- // address as the envelope sender as well. For open sites this
- // can cause mails to be flunked for SPF violations (since the
- // wiki server isn't an authorized sender for various users'
- // domains) as well as creating a privacy issue as bounces
- // containing the recipient's e-mail address may get sent to
- // the sending user.
+ /**
+ * Put the sending user's e-mail address in the From: header.
+ *
+ * This is clean-looking and convenient, but has issues.
+ * One is that it doesn't as clearly differentiate the wiki mail
+ * from "directly" sent mails.
+ *
+ * Another is that some mailers (like sSMTP) will use the From
+ * address as the envelope sender as well. For open sites this
+ * can cause mails to be flunked for SPF violations (since the
+ * wiki server isn't an authorized sender for various users'
+ * domains) as well as creating a privacy issue as bounces
+ * containing the recipient's e-mail address may get sent to
+ * the sending user.
+ */
$mailFrom = $from;
$replyTo = null;
}
$this->moveSubpages = false;
}
- # Next make a list of id's. This might be marginally less efficient
- # than a more direct method, but this is not a highly performance-cri-
- # tical code path and readable code is more important here.
- #
- # Note: this query works nicely on MySQL 5, but the optimizer in MySQL
- # 4 might get confused. If so, consider rewriting as a UNION.
- #
- # If the target namespace doesn't allow subpages, moving with subpages
- # would mean that you couldn't move them back in one operation, which
- # is bad.
- # @todo FIXME: A specific error message should be given in this case.
+ /**
+ * Next make a list of id's. This might be marginally less efficient
+ * than a more direct method, but this is not a highly performance-cri-
+ * tical code path and readable code is more important here.
+ *
+ * Note: this query works nicely on MySQL 5, but the optimizer in MySQL
+ * 4 might get confused. If so, consider rewriting as a UNION.
+ *
+ * If the target namespace doesn't allow subpages, moving with subpages
+ * would mean that you couldn't move them back in one operation, which
+ * is bad.
+ * @todo FIXME: A specific error message should be given in this case.
+ */
// @todo FIXME: Use Title::moveSubpages() here
$dbr = wfGetDB( DB_MASTER );
// UploadStash
private $stash;
- // Since we are directly writing the file to STDOUT,
- // we should not be reading in really big files and serving them out.
- //
- // We also don't want people using this as a file drop, even if they
- // share credentials.
- //
- // This service is really for thumbnails and other such previews while
- // uploading.
+ /**
+ * Since we are directly writing the file to STDOUT,
+ * we should not be reading in really big files and serving them out.
+ *
+ * We also don't want people using this as a file drop, even if they
+ * share credentials.
+ *
+ * This service is really for thumbnails and other such previews while
+ * uploading.
+ */
const MAX_SERVE_BYTES = 1048576; // 1MB
public function __construct() {
}
$this->setHeaders();
- // In the case where the user is already logged in, and was redirected to the login form from a
- // page that requires login, do not show the login page. The use case scenario for this is when
- // a user opens a large number of tabs, is redirected to the login page on all of them, and then
- // logs in on one, expecting all the others to work properly.
- //
- // However, do show the form if it was visited intentionally (no 'returnto' is present). People
- // who often switch between several accounts have grown accustomed to this behavior.
+ /**
+ * In the case where the user is already logged in, and was redirected to
+ * the login form from a page that requires login, do not show the login
+ * page. The use case scenario for this is when a user opens a large number
+ * of tabs, is redirected to the login page on all of them, and then logs
+ * in on one, expecting all the others to work properly.
+ *
+ * However, do show the form if it was visited intentionally (no 'returnto'
+ * is present). People who often switch between several accounts have grown
+ * accustomed to this behavior.
+ */
if (
$this->mType !== 'signup' &&
!$this->mPosted &&
}
$status = $this->addNewAccountInternal();
- LoggerFactory::getInstance( 'authmanager' )->info( 'Account creation attempt with mailed password', array(
- 'event' => 'accountcreation',
- 'status' => $status,
- ) );
+ LoggerFactory::getInstance( 'authmanager' )->info(
+ 'Account creation attempt with mailed password',
+ array( 'event' => 'accountcreation', 'status' => $status )
+ );
if ( !$status->isGood() ) {
$error = $status->getMessage();
$this->mainLoginForm( $error->toString() );
global $wgBlockDisablesLogin;
if ( !$u->checkPassword( $this->mPassword ) ) {
if ( $u->checkTemporaryPassword( $this->mPassword ) ) {
- // The e-mailed temporary password should not be used for actu-
- // al logins; that's a very sloppy habit, and insecure if an
- // attacker has a few seconds to click "search" on someone's o-
- // pen mail reader.
- //
- // Allow it to be used only to reset the password a single time
- // to a new value, which won't be in the user's e-mail ar-
- // chives.
- //
- // For backwards compatibility, we'll still recognize it at the
- // login form to minimize surprises for people who have been
- // logging in with a temporary password for some time.
- //
- // As a side-effect, we can authenticate the user's e-mail ad-
- // dress if it's not already done, since the temporary password
- // was sent via e-mail.
+ /**
+ * The e-mailed temporary password should not be used for actu-
+ * al logins; that's a very sloppy habit, and insecure if an
+ * attacker has a few seconds to click "search" on someone's
+ * open mail reader.
+ *
+ * Allow it to be used only to reset the password a single time
+ * to a new value, which won't be in the user's e-mail ar-
+ * chives.
+ *
+ * For backwards compatibility, we'll still recognize it at the
+ * login form to minimize surprises for people who have been
+ * logging in with a temporary password for some time.
+ *
+ * As a side-effect, we can authenticate the user's e-mail ad-
+ * dress if it's not already done, since the temporary password
+ * was sent via e-mail.
+ */
if ( !$u->isEmailConfirmed() && !wfReadOnly() ) {
$u->confirmEmail();
$u->saveSettings();
$template->set( 'emailothers', $wgEnableUserEmail );
$template->set( 'canreset', $wgAuth->allowPasswordChange() );
$template->set( 'resetlink', $resetLink );
- $template->set( 'canremember', $wgExtendedLoginCookieExpiration === null ? ( $wgCookieExpiration > 0 ) : ( $wgExtendedLoginCookieExpiration > 0 ) );
+ $template->set( 'canremember', $wgExtendedLoginCookieExpiration === null ?
+ ( $wgCookieExpiration > 0 ) :
+ ( $wgExtendedLoginCookieExpiration > 0 ) );
$template->set( 'usereason', $user->isLoggedIn() );
$template->set( 'remember', $this->mRemember );
$template->set( 'cansecurelogin', ( $wgSecureLogin === true ) );
global $wgContLang;
- // Can we assume that the part of the page title before the colon is a
- // namespace name?
- //
- // XML export schema version 0.5 and earlier (MW 1.18 and earlier) does not
- // contain a <ns> tag, so we need to be able to handle that case.
- //
- // If we know the namespace ID, we assume a non-zero namespace ID means
- // the ':' sets off a valid namespace name. If we don't know the namespace
- // ID, we fall back to using the local wiki's namespace names to resolve
- // this -- better than nothing, and mimics the old crappy behavior
+ /**
+ * Can we assume that the part of the page title before the colon is a
+ * namespace name?
+ *
+ * XML export schema version 0.5 and earlier (MW 1.18 and earlier) does not
+ * contain a <ns> tag, so we need to be able to handle that case.
+ *
+ * If we know the namespace ID, we assume a non-zero namespace ID means
+ * the ':' sets off a valid namespace name. If we don't know the namespace
+ * ID, we fall back to using the local wiki's namespace names to resolve
+ * this -- better than nothing, and mimics the old crappy behavior
+ */
$isNamespacePartValid = is_null( $ns ) ?
( $wgContLang->getNsIndex( $pieces[0] ) !== false ) :
$ns != 0;
/**
* Russian (русский язык)
*
- * You can contact Alexander Sigachov (alexander.sigachov at Googgle Mail)
+ * You can contact:
+ * Alexander Sigachov (alexander.sigachov at Googgle Mail)
+ * Amir E. Aharoni (amir.aharoni@mail.huji.ac.il)
*
* @ingroup Language
*/
return $wgGrammarForms['ru'][$case][$word];
}
- # These rules are not perfect, but they are currently only used for Wikimedia
- # site names so it doesn't matter if they are wrong sometimes.
- # Just add a special case for your site name if necessary.
+ # These rules don't cover the whole language, and are intended only for
+ # names of languages and Wikimedia sites.
# substr doesn't support Unicode and mb_substr has issues,
# so break it to characters using preg_match_all and then use array_slice and join
} elseif ( join( '', array_slice( $chars[0], -3 ) ) === 'ные' ) {
$word = join( '', array_slice( $chars[0], 0, -3 ) ) . 'ных';
}
+ break;
+ case 'languagegen': # язык в родительном падеже ("(с) русского")
+ $suffix = join( '', array_slice( $chars[0], -3 ) );
+ if ( $suffix === 'кий' ) {
+ $word = join(
+ '',
+ array_slice( $chars[0], 0, count( $chars[0] ) - 2 )
+ ) . 'ого';
+
+ break;
+ }
+
+ if ( in_array( $word, array( 'иврит', 'идиш' ) ) ) {
+ $word = $word . 'а';
+
+ break;
+ }
+
+ break;
+ case 'languageprep': # язык в предложном падеже ("(на) русском")
+ $suffix = join( '', array_slice( $chars[0], -3 ) );
+ if ( $suffix === 'кий' ) {
+ $word = join(
+ '',
+ array_slice( $chars[0], 0, count( $chars[0] ) - 2 )
+ ) . 'ом';
+
+ break;
+ }
+
+ if ( in_array( $word, array( 'иврит', 'идиш' ) ) ) {
+ $word = $word . 'е';
+
+ break;
+ }
+
+ break;
+ case 'languageadverb': # наречие с названием языка ("по-русски")
+ $suffix = join( '', array_slice( $chars[0], -3 ) );
+ if ( $suffix === 'кий' ) {
+ $word = 'по-' . join(
+ '',
+ array_slice( $chars[0], 0, count( $chars[0] ) - 1 )
+ );
+
+ break;
+ }
+
+ if ( in_array( $word, array( 'иврит', 'идиш' ) ) ) {
+ $word = 'на ' . $word . 'е';
+
+ break;
+ }
+
+ // Known particular cases of undeclinable names
+ // Известные несклоняемые
+ if ( in_array( $word, array( 'идо', 'урду', 'хинди', 'эсперанто' ) ) ) {
+ $word = "на $word";
+
+ break;
+ }
+
+ // Undeclinable
+ // Остальные несклоняемые
+ $word = "на языке $word";
+
break;
}
}
}
// Set up some constants...
- $allVowels = array( "е", "и", "э", "ө", "ү", "а", "ё", "о", "у", "ы",
- "ю", "я", "a", "e", "i", "o", "ö", "u", "ü", "y" );
- $frontVowels = array( "е", "и", "э", "ө", "ү", "e", "i", "ö", "ü" );
- $backVowels = array( "а", "ё", "о", "у", "ы", "ю", "я", "a", "o", "u", "y" );
- $unroundFrontVowels = array( "е", "и", "э", "e", "i" );
- $roundFrontVowels = array( "ө", "ү", "ö", "ü" );
- $unroundBackVowels = array( "а", "ы", "я", "a", "y" );
- $roundBackVowels = array( "ё", "о", "у", "ю", "o", "u" );
- // $voicedPhonemes = array( "д", "б", "з", "ж", "г", "d", "b", "z", "g" );
- $unvoicedPhonemes = array( "т", "п", "с", "ш", "к", "ч", "х", "t", "p", "s", "k", "x" );
- $directiveUnvoicedStems = array( "т", "п", "с", "ш", "к", "ч", "х", "л",
- "м", "н", "ң", "t", "p", "s", "k", "x", "l", "m", "n", "ŋ" );
- $directiveVoicedStems = array( "д", "б", "з", "ж", "г", "р", "й", "d", "b", "z", "g", "r", "j" );
-
- // $allSonants = array("л", "м", "н", "ң", "р", "й");
- // $allNasals = array("м", "н", "ң");
+ $allVowels = array( "е", "и", "э", "ө", "ү", "а", "ё", "о", "у", "ы", "ю", "я" );
+ $frontVowels = array( "е", "и", "э", "ө", "ү" );
+ $backVowels = array( "а", "ё", "о", "у", "ы", "ю", "я" );
+ $unroundFrontVowels = array( "е", "и", "э" );
+ $roundFrontVowels = array( "ө", "ү" );
+ $unroundBackVowels = array( "а", "ы", "я" );
+ $roundBackVowels = array( "ё", "о", "у", "ю" );
+ $unvoicedPhonemes = array( "т", "п", "с", "ш", "к", "ч", "х" );
+ $directiveUnvoicedStems = array( "т", "п", "с", "ш", "к", "ч", "х", "л", "м", "н", "ң" );
+ $directiveVoicedStems = array( "д", "б", "з", "ж", "г", "р", "й" );
// Put the word in a form we can play with since we're using UTF-8
preg_match_all( '/./us', $word, $ar );
// Here's the last letter in the word
$wordEnding = $ar[0][count( $ar[0] ) - 1];
+
// Here's an array with the order of the letters in the word reversed so
// we can find a match quicker. *shrug*
$wordReversed = array_reverse( $ar[0] );
continue;
}
}
+
if ( $wordLastVowel !== null ) {
break;
} else {
$word = implode( "", $ar[0] ) . "тың";
} else {
}
- } elseif ( $wordEnding === "л" || $wordEnding === "l" ) {
+ } elseif ( $wordEnding === "л" ) {
if ( in_array( $wordLastVowel, $roundFrontVowels ) ) {
$word = implode( "", $ar[0] ) . "дүң";
} elseif ( in_array( $wordLastVowel, $unroundFrontVowels ) ) {
$word = implode( "", $ar[0] ) . "ты";
} else {
}
- } elseif ( $wordEnding === "л" || $wordEnding === "l" ) {
+ } elseif ( $wordEnding === "л" ) {
if ( in_array( $wordLastVowel, $roundFrontVowels ) ) {
$word = implode( "", $ar[0] ) . "дү";
} elseif ( in_array( $wordLastVowel, $unroundFrontVowels ) ) {
default:
break;
}
+
return $word;
}
}
// cases.
mediaWiki.language.convertGrammar = function ( word, form ) {
+ /*global $ */
'use strict';
var grammarForms = mediaWiki.language.getData( 'ru', 'grammarForms' );
word = word.slice( 0, -3 ) + 'нике';
}
break;
+ case 'languagegen': // язык в родительном падеже ("(с) русского")
+ if ( word.slice( -3 ) === 'кий' ) {
+ word = word.slice( 0, -2 ) + 'ого';
+ } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) {
+ word = word + 'а';
+ }
+ break;
+ case 'languageprep': // язык в предложном падеже ("(на) русском")
+ if ( word.slice( -3 ) === 'кий' ) {
+ word = word.slice( 0, -2 ) + 'ом';
+ } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) {
+ word = word + 'е';
+ }
+ break;
+ case 'languageadverb': // наречие с названием языка ("по-русски")
+ if ( word.slice( -3 ) === 'кий' ) {
+ word = 'по-' + word.slice( 0, -1 );
+ } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) {
+ word = 'на ' + word + 'е';
+ } else if ( $.inArray( word, [ 'идо', 'урду', 'хинди', 'эсперанто' ] ) > -1 ) {
+ word = 'на ' + word;
+ } else {
+ word = 'на языке ' + word;
+ }
+ break;
}
return word;
};
/**
* Links
*/
-a.stub,
-a.new {
- color: #ba0000;
- text-decoration: none;
-}
-
a {
- color: black !important;
background: none !important;
padding: 0 !important;
}
-a:link, a:visited {
- color: #520;
- background: transparent;
- text-decoration: underline;
-}
-
/* Expand URLs for printing */
.mw-body a.external.text:after,
.mw-body a.external.autonumber:after {
#mw-editbutton-hr {
.background-image("images/@{button-hr}");
}
+
+// Awful workaround for T113868, while it awaits a better fix.
+#mw-t113868 {
+ background-image: url(images/ar/button_bold.png), url(images/ar/button_headline.png), url(images/ar/button_italic.png), url(images/ar/button_link.png), url(images/ar/button_nowiki.png), url(images/be-tarask/button_bold.png), url(images/be-tarask/button_italic.png), url(images/be-tarask/button_link.png), url(images/de/button_bold.png), url(images/de/button_italic.png), url(images/en/button_bold.png), url(images/en/button_extlink.png), url(images/en/button_headline.png), url(images/en/button_hr.png), url(images/en/button_image.png), url(images/en/button_italic.png), url(images/en/button_link.png), url(images/en/button_media.png), url(images/en/button_nowiki.png), url(images/en/button_sig.png), url(images/fa/button_bold.png), url(images/fa/button_headline.png), url(images/fa/button_italic.png), url(images/fa/button_link.png), url(images/fa/button_nowiki.png), url(images/ksh/button_italic.png), url(images/ru/button_bold.png), url(images/ru/button_italic.png), url(images/ru/button_link.png);
+}
'Викиданные',
'prepositional',
),
+ array(
+ 'русского',
+ 'русский',
+ 'languagegen',
+ ),
+ array(
+ 'немецкого',
+ 'немецкий',
+ 'languagegen',
+ ),
+ array(
+ 'иврита',
+ 'иврит',
+ 'languagegen',
+ ),
+ array(
+ 'эсперанто',
+ 'эсперанто',
+ 'languagegen',
+ ),
+ array(
+ 'русском',
+ 'русский',
+ 'languageprep',
+ ),
+ array(
+ 'немецком',
+ 'немецкий',
+ 'languageprep',
+ ),
+ array(
+ 'идише',
+ 'идиш',
+ 'languageprep',
+ ),
+ array(
+ 'эсперанто',
+ 'эсперанто',
+ 'languageprep',
+ ),
+ array(
+ 'по-русски',
+ 'русский',
+ 'languageadverb',
+ ),
+ array(
+ 'по-немецки',
+ 'немецкий',
+ 'languageadverb',
+ ),
+ array(
+ 'на иврите',
+ 'иврит',
+ 'languageadverb',
+ ),
+ array(
+ 'на эсперанто',
+ 'эсперанто',
+ 'languageadverb',
+ ),
+ array(
+ 'на языке гуарани',
+ 'гуарани',
+ 'languageadverb',
+ ),
);
}
}
grammarForm: 'prepositional',
expected: 'данных',
description: 'Grammar test for prepositional case, данные -> данных'
+ },
+ {
+ word: 'русский',
+ grammarForm: 'languagegen',
+ expected: 'русского',
+ description: 'Grammar test for languagegen case, русский -> русского'
+ },
+ {
+ word: 'немецкий',
+ grammarForm: 'languagegen',
+ expected: 'немецкого',
+ description: 'Grammar test for languagegen case, немецкий -> немецкого'
+ },
+ {
+ word: 'иврит',
+ grammarForm: 'languagegen',
+ expected: 'иврита',
+ description: 'Grammar test for languagegen case, иврит -> иврита'
+ },
+ {
+ word: 'эсперанто',
+ grammarForm: 'languagegen',
+ expected: 'эсперанто',
+ description: 'Grammar test for languagegen case, эсперанто -> эсперанто'
+ },
+ {
+ word: 'русский',
+ grammarForm: 'languageprep',
+ expected: 'русском',
+ description: 'Grammar test for languageprep case, русский -> русском'
+ },
+ {
+ word: 'немецкий',
+ grammarForm: 'languageprep',
+ expected: 'немецком',
+ description: 'Grammar test for languageprep case, немецкий -> немецком'
+ },
+ {
+ word: 'идиш',
+ grammarForm: 'languageprep',
+ expected: 'идише',
+ description: 'Grammar test for languageprep case, идиш -> идише'
+ },
+ {
+ word: 'эсперанто',
+ grammarForm: 'languageprep',
+ expected: 'эсперанто',
+ description: 'Grammar test for languageprep case, эсперанто -> эсперанто'
+ },
+ {
+ word: 'русский',
+ grammarForm: 'languageadverb',
+ expected: 'по-русски',
+ description: 'Grammar test for languageadverb case, русский -> по-русски'
+ },
+ {
+ word: 'немецкий',
+ grammarForm: 'languageadverb',
+ expected: 'по-немецки',
+ description: 'Grammar test for languageadverb case, немецкий -> по-немецки'
+ },
+ {
+ word: 'иврит',
+ grammarForm: 'languageadverb',
+ expected: 'на иврите',
+ description: 'Grammar test for languageadverb case, иврит -> на иврите'
+ },
+ {
+ word: 'эсперанто',
+ grammarForm: 'languageadverb',
+ expected: 'на эсперанто',
+ description: 'Grammar test for languageadverb case, эсперанто -> на эсперанто'
+ },
+ {
+ word: 'гуарани',
+ grammarForm: 'languageadverb',
+ expected: 'на языке гуарани',
+ description: 'Grammar test for languageadverb case, гуарани -> на языке гуарани'
}
],
$this->sectionData['config'] = '';
}
- $isDisabled = preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) && !$this->parserTest->runDisabled;
- $isParsoidOnly = preg_match( '/\\bparsoid\\b/i', $this->sectionData['options'] ) && $result == 'html' && !$this->parserTest->runParsoid;
+ $isDisabled = preg_match( '/\\bdisabled\\b/i', $this->sectionData['options'] ) &&
+ !$this->parserTest->runDisabled;
+ $isParsoidOnly = preg_match( '/\\bparsoid\\b/i', $this->sectionData['options'] ) &&
+ $result == 'html' &&
+ !$this->parserTest->runParsoid;
$isFiltered = !preg_match( "/" . $this->parserTest->regex . "/i", $this->sectionData['test'] );
if ( $input == false || $result == false || $isDisabled || $isParsoidOnly || $isFiltered ) {
# disabled test