'CloneDatabase' => __DIR__ . '/includes/db/CloneDatabase.php',
'CodeCleanerGlobalsPass' => __DIR__ . '/maintenance/CodeCleanerGlobalsPass.inc',
'CodeContentHandler' => __DIR__ . '/includes/content/CodeContentHandler.php',
+ 'CollapsibleFieldsetLayout' => __DIR__ . '/includes/htmlform/CollapsibleFieldsetLayout.php',
'Collation' => __DIR__ . '/includes/collation/Collation.php',
'CollationCkb' => __DIR__ . '/includes/collation/CollationCkb.php',
'CommandLineInc' => __DIR__ . '/maintenance/commandLine.inc',
--- /dev/null
+<?php
+
+class CollapsibleFieldsetLayout extends OOUI\FieldsetLayout {
+ public function __construct( array $config = [] ) {
+ parent::__construct( $config );
+
+ $this->addClasses( [ 'mw-collapsible' ] );
+ if ( isset( $config[ 'collapsed' ] ) && $config[ 'collapsed' ] ) {
+ $this->addClasses( [ 'mw-collapsed' ] );
+ }
+ $this->header->addClasses( [ 'mw-collapsible-toggle' ] );
+ $this->group->addClasses( [ 'mw-collapsible-content' ] );
+
+ $this->header->appendContent(
+ new OOUI\IconWidget( [
+ 'icon' => 'expand',
+ 'label' => wfMessage( 'collapsible-expand' )->text(),
+ ] ),
+ new OOUI\IconWidget( [
+ 'icon' => 'collapse',
+ 'label' => wfMessage( 'collapsible-collapse' )->text(),
+ ] )
+ );
+
+ $this->header->setAttributes( [
+ 'role' => 'button',
+ ] );
+ }
+}
public function wrapForm( $html ) {
if ( is_string( $this->mWrapperLegend ) ) {
- $classes = $this->mCollapsible ? [ 'mw-collapsible' ] : [];
- if ( $this->mCollapsed ) {
- $classes[] = 'mw-collapsed';
- }
- $content = new OOUI\FieldsetLayout( [
+ $phpClass = $this->mCollapsible ? CollapsibleFieldsetLayout::class : OOUI\FieldsetLayout::class;
+ $content = new $phpClass( [
'label' => $this->mWrapperLegend,
- 'classes' => $classes,
- 'group' => new OOUI\StackLayout( [
- 'expanded' => false,
- 'classes' => [ 'mw-collapsible-content' ],
- ] ),
+ 'collapsed' => $this->mCollapsed,
'items' => [
new OOUI\Widget( [
'content' => new OOUI\HtmlSnippet( $html )
* Generate a new MWHttpRequest object
* @param string $url Url to use
* @param array $options Possible keys for the array:
- * - timeout Timeout length in seconds
- * - connectTimeout Timeout for connection, in seconds (curl only)
+ * - timeout Timeout length in seconds or 'default'
+ * - connectTimeout Timeout for connection, in seconds (curl only) or 'default'
* - postData An array of key-value pairs or a url-encoded form data
* - proxy The proxy to use.
* Otherwise it will use $wgHTTPProxy (if set)
* - originalRequest Information about the original request (as a WebRequest object or
* an associative array with 'ip' and 'userAgent').
* @codingStandardsIgnoreStart
- * @phan-param array{timeout?:int,connectTimeout?:int,postData?:array,proxy?:string,noProxy?:bool,sslVerifyHost?:bool,sslVerifyCert?:bool,caInfo?:string,maxRedirects?:int,followRedirects?:bool,userAgent?:string,method?:string,logger?:\Psr\Log\LoggerInterface,username?:string,password?:string,originalRequest?:WebRequest|array{ip:string,userAgent:string}} $options
+ * @phan-param array{timeout?:int|string,connectTimeout?:int|string,postData?:array,proxy?:string,noProxy?:bool,sslVerifyHost?:bool,sslVerifyCert?:bool,caInfo?:string,maxRedirects?:int,followRedirects?:bool,userAgent?:string,method?:string,logger?:\Psr\Log\LoggerInterface,username?:string,password?:string,originalRequest?:WebRequest|array{ip:string,userAgent:string}} $options
* @codingStandardsIgnoreEnd
* @param string $caller The method making this request, for profiling
* @throws RuntimeException
* @param string $url Url to use. If protocol-relative, will be expanded to an http:// URL
* @param array $options (optional) extra params to pass (see HttpRequestFactory::create())
* @codingStandardsIgnoreStart
- * @phan-param array{timeout?:int,connectTimeout?:int,postData?:array,proxy?:string,noProxy?:bool,sslVerifyHost?:bool,sslVerifyCert?:bool,caInfo?:string,maxRedirects?:int,followRedirects?:bool,userAgent?:string,logger?:LoggerInterface,username?:string,password?:string,originalRequest?:WebRequest|array{ip:string,userAgent:string},method?:string} $options
+ * @phan-param array{timeout?:int|string,connectTimeout?:int|string,postData?:array,proxy?:string,noProxy?:bool,sslVerifyHost?:bool,sslVerifyCert?:bool,caInfo?:string,maxRedirects?:int,followRedirects?:bool,userAgent?:string,logger?:LoggerInterface,username?:string,password?:string,originalRequest?:WebRequest|array{ip:string,userAgent:string},method?:string} $options
* @codingStandardsIgnoreEnd
* @param string $caller The method making this request, for profiling
* @param Profiler|null $profiler An instance of the profiler for profiling, or null
*
* @param string|bool $pageName Page name or false (default: false)
*
- * @return string|bool|null
+ * @return string|null
*/
public function getPageUrl( $pageName = false ) {
$url = $this->getLinkPath();
- if ( $url === false ) {
- return false;
+ if ( $url === null ) {
+ return null;
}
if ( $pageName !== false ) {
/**
* Returns the full URL for the given page on the site.
- * Or false if the needed information is not known.
+ * Or null if the needed information is not known.
*
* This generated URL is usually based upon the path returned by getLinkPath(),
* but this is not a requirement.
*
* @param bool|string $pageName
*
- * @return string|bool|null
+ * @return string|null
*/
public function getPageUrl( $pageName = false ) {
$url = $this->getLinkPath();
- if ( $url === false ) {
- return false;
+ if ( $url === null ) {
+ return null;
}
if ( $pageName !== false ) {
* @ingroup Maintenance
*/
+use MediaWiki\MediaWikiServices;
+
require_once __DIR__ . '/Maintenance.php';
/**
protected function doDBUpdates() {
$replaceMissing = $this->hasOption( 'replace-missing' );
$defaultExternalStore = $this->getConfig()->get( 'DefaultExternalStore' );
+ // @phan-suppress-next-line PhanAccessMethodInternal
+ $blobStore = MediaWikiServices::getInstance()
+ ->getBlobStoreFactory()
+ ->newSqlBlobStore();
$batchSize = $this->getBatchSize();
$dbr = $this->getDB( DB_REPLICA, [ 'vslow' ] );
// Recompress the text (and store in external storage, if
// applicable) if it's not already in external storage.
- if ( !in_array( 'external', explode( ',', $row->ar_flags ), true ) ) {
- $data = Revision::getRevisionText( $row, 'ar_' );
+ $arFlags = explode( ',', $row->ar_flags );
+ if ( !in_array( 'external', $arFlags, true ) ) {
+ $data = $blobStore->decompressData( $row->ar_text, $arFlags );
if ( $data !== false ) {
$flags = Revision::compressRevisionText( $data );
}
}
-fieldset.mw-collapsible .mw-collapsible-toggle {
- position: absolute;
- right: 0;
- z-index: 1;
-}
-
// special treatment for list items to match above
// !important necessary to override overly-specific float left and right above.
ol.mw-collapsible:not( @{exclude} ):before,
@ooui-font-size-browser: 16; // assumed browser default of `16px`
@ooui-font-size-base: 0.875em; // equals `14px` at browser default of `16px`
+@ooui-spacing-small: 8 / @ooui-font-size-browser / @ooui-font-size-base; // equals `0.57142857em`≈`8px`
@ooui-spacing-medium: 12 / @ooui-font-size-browser / @ooui-font-size-base; // equals `0.8571429em`≈`12px`
@ooui-spacing-large: 16 / @ooui-font-size-browser / @ooui-font-size-base; // equals `1.1428571em`≈`16px`
@ooui-padding-horizontal: 12 / @ooui-font-size-browser / @ooui-font-size-base;
// Reducing `padding-top`, as the heading's `line-height` provides similar distance.
padding: @ooui-spacing-medium @ooui-spacing-large @ooui-spacing-large;
- // Trigger only when collapsible & JS is available via `.mw-collapsed`.
- .client-js & .oo-ui-fieldsetLayout.mw-collapsed .oo-ui-fieldsetLayout-header {
- // Negative margin to match the reduced distance on the top caused by the previous rule.
- margin-bottom: -( @ooui-spacing-large - @ooui-spacing-medium );
+ .client-js & .oo-ui-fieldsetLayout.mw-collapsible .oo-ui-fieldsetLayout-header {
+ // Push legend up when JS is on, to increase clickable area.
+ margin-top: -@ooui-spacing-small;
+ margin-bottom: @ooui-spacing-small;
+ // Add `padding-top` to make up for negative `margin` above.
+ padding: @ooui-spacing-small;
+ // Make space for toggle icon defined below.
+ padding-left: 24 / @ooui-font-size-browser / @ooui-font-size-base;
.oo-ui-labelElement-label {
margin-bottom: 0;
}
}
+
+ // Trigger only when collapsible & JS is available via `.mw-collapsed`.
+ .client-js & .oo-ui-fieldsetLayout.mw-collapsed .oo-ui-fieldsetLayout-header {
+ min-height: 30px;
+ // Negative margin to match the reduced distance on the top caused by the previous rule.
+ margin-bottom: -@ooui-spacing-medium;
+ }
}
.mw-htmlform-ooui {
.mw-htmlform-ooui .mw-htmlform-submit-buttons {
margin-top: @ooui-spacing-medium;
}
+
+.oo-ui-fieldsetLayout.mw-collapsible {
+ .oo-ui-fieldsetLayout-header {
+ max-width: none;
+ }
+
+ .mw-collapsible-toggle .oo-ui-iconElement-icon {
+ position: absolute;
+ top: 0;
+ left: 0;
+ // Special case: Reduce to `16px` icon size here.
+ min-width: 16px;
+ width: 16 / @ooui-font-size-browser / @ooui-font-size-base;
+ margin-right: 0.5em;
+ }
+
+ // When expanded: only 'collapse' icon visible
+ .mw-collapsible-toggle .oo-ui-icon-expand {
+ display: none;
+ }
+
+ // When collapsed: only 'expand' icon visible
+ &.mw-collapsed {
+ .mw-collapsible-toggle .oo-ui-icon-expand {
+ display: inline-block;
+ }
+
+ .mw-collapsible-toggle .oo-ui-icon-collapse {
+ display: none;
+ }
+ }
+}