. * * @file * @ingroup Skins */ declare( strict_types=1 ); namespace Citizen\Partials; use Exception; use ExtensionRegistry; use MWException; use Skin; use SpecialPage; /** * Drawer partial of Skin Citizen * Generates the following partials: * - Logo * - Drawer * + Special Pages Link * + Upload Link */ final class Drawer extends Partial { /** * Render the navigation drawer * Based on buildSidebar() * * @return array * @throws Exception */ public function buildDrawer() { $portals = $this->skin->buildSidebar(); $props = []; $languages = null; // Render portals foreach ( $portals as $name => $content ) { if ( $content === false ) { continue; } // Numeric strings gets an integer when set as key, cast back - T73639 $name = (string)$name; switch ( $name ) { case 'SEARCH': case 'TOOLBOX': break; case 'LANGUAGES': $languages = $this->skin->getLanguages(); $portal = $this->skin->getMenuData( 'lang', $content ); // The language portal will be added provided either // languages exist or there is a value in html-after-portal // for example to show the add language wikidata link (T252800) if ( count( $content ) || $portal['html-after-portal'] ) { $languages = $portal; } break; default: // Historically some portals have been defined using HTML rather than arrays. // Let's move away from that to a uniform definition. if ( !is_array( $content ) ) { $html = $content; $content = []; wfDeprecated( "`content` field in portal $name must be array." . "Previously it could be a string but this is no longer supported.", '1.35.0' ); } else { $html = false; } $portal = $this->skin->getMenuData( $name, $content ); if ( $html ) { $portal['html-items'] .= $html; } $props[] = $portal; break; } } $portalLabel = $this->getConfigValue( 'CitizenPortalAttach' ) ?? 'first'; $firstPortal = array_shift( $props ); if ( $portalLabel === 'first' && $firstPortal !== null && isset( $firstPortal['html-items'] ) ) { $this->addToolboxLinksToDrawer( $firstPortal['html-items'] ); } else { for ( $i = 0, $portalCount = count( $props ); $i < $portalCount; $i++ ) { if ( isset( $props[$i]['label'] ) && $props[$i]['label'] === $portalLabel ) { $this->addToolboxLinksToDrawer( $props[$i]['html-items'] ); break; } } } $portals = [ 'msg-citizen-drawer-toggle' => $this->skin->msg( 'citizen-drawer-toggle' )->text(), 'msg-citizen-drawer-search' => $this->skin->msg( 'citizen-drawer-search' )->text(), 'data-portals-first' => $firstPortal, 'array-portals-rest' => $props, 'data-portals-languages' => $languages, 'data-drawer-sitestats' => $this->getSiteStats(), 'data-drawer-subsearch' => false, ]; // Drawer subsearch if ( $this->getConfigValue( 'CitizenEnableDrawerSubSearch' ) ) { $portals['data-drawer-subsearch'] = true; } return $portals; } /** * Get messages used for site stats in the drawer * * @return array for use in Mustache template. */ private function getSiteStats() { $props = []; if ( $this->getConfigValue( 'CitizenEnableDrawerSiteStats' ) ) { $stats = [ 'articles', 'images', 'users', 'edits' ]; $items = []; $fmt = new \NumberFormatter( 'en_US', \NumberFormatter::PADDING_POSITION ); $fmt->setAttribute( \NumberFormatter::ROUNDING_MODE, \NumberFormatter::ROUND_DOWN ); $fmt->setAttribute( \NumberFormatter::MAX_FRACTION_DIGITS, 1 ); foreach ( $stats as &$stat ) { $items[] = [ 'id' => $stat, 'value' => $this->getSiteStat( $stat ), 'label' => $this->skin->msg( "citizen-sitestats-$stat-label" )->text(), ]; } } $props['array-drawer-sitestats-item'] = $items; return $props; } /** * Get and format sitestat value * TODO: Formatting should be based on user locale * * @param string $key * * @return int */ private function getSiteStat( $key ) { $value = call_user_func( 'SiteStats::' . $key ); if ( $value >= 10000 ) { $fmt = new \NumberFormatter( 'en_US', \NumberFormatter::PADDING_POSITION ); $fmt->setAttribute( \NumberFormatter::ROUNDING_MODE, \NumberFormatter::ROUND_DOWN ); $fmt->setAttribute( \NumberFormatter::MAX_FRACTION_DIGITS, 1 ); $value = $fmt->format( $value ); } else { $value = number_format( $value ); } return $value; } /** * Add a link to special pages and the upload form to the first portal in the drawer * * @param string &$htmlItems * * @return void * @throws MWException */ private function addToolboxLinksToDrawer( &$htmlItems ) { // First add a link to special pages $htmlItems .= $this->skin->makeListItem( 'specialpages', [ 'href' => Skin::makeSpecialUrl( 'Specialpages' ), 'id' => 't-specialpages' ] ); $uploadHref = Skin::makeSpecialUrl( 'Upload' ); if ( ExtensionRegistry::getInstance()->isLoaded( 'Upload Wizard' ) ) { $uploadHref = SpecialPage::getTitleFor( 'UploadWizard' )->getLocalURL(); } // Then add a link to the upload form $htmlItems .= $this->skin->makeListItem( 'upload', [ 'href' => $uploadHref, 'id' => 't-upload' ] ); } }