[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/skins/CologneBlue/ -> SkinCologneBlue.php (source)

   1  <?php
   2  /**
   3   * Cologne Blue: A nicer-looking alternative to Standard.
   4   *
   5   * This program is free software; you can redistribute it and/or modify
   6   * it under the terms of the GNU General Public License as published by
   7   * the Free Software Foundation; either version 2 of the License, or
   8   * (at your option) any later version.
   9   *
  10   * This program is distributed in the hope that it will be useful,
  11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13   * GNU General Public License for more details.
  14   *
  15   * You should have received a copy of the GNU General Public License along
  16   * with this program; if not, write to the Free Software Foundation, Inc.,
  17   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18   * http://www.gnu.org/copyleft/gpl.html
  19   *
  20   * @todo document
  21   * @file
  22   * @ingroup Skins
  23   */
  24  
  25  if ( !defined( 'MEDIAWIKI' ) ) {
  26      die( -1 );
  27  }
  28  
  29  /**
  30   * @todo document
  31   * @ingroup Skins
  32   */
  33  class SkinCologneBlue extends SkinTemplate {
  34      public $skinname = 'cologneblue';
  35      public $template = 'CologneBlueTemplate';
  36  
  37      /**
  38       * @param OutputPage $out
  39       */
  40  	function setupSkinUserCss( OutputPage $out ) {
  41          parent::setupSkinUserCss( $out );
  42          $out->addModuleStyles( 'mediawiki.legacy.oldshared' );
  43          $out->addModuleStyles( 'skins.cologneblue' );
  44      }
  45  
  46      /**
  47       * Override langlink formatting behavior not to uppercase the language names.
  48       * See otherLanguages() in CologneBlueTemplate.
  49       * @param string $name
  50       * @return string
  51       */
  52  	function formatLanguageName( $name ) {
  53          return $name;
  54      }
  55  }
  56  
  57  class CologneBlueTemplate extends BaseTemplate {
  58  	function execute() {
  59          // Suppress warnings to prevent notices about missing indexes in $this->data
  60          wfSuppressWarnings();
  61          $this->html( 'headelement' );
  62          echo $this->beforeContent();
  63          $this->html( 'bodytext' );
  64          echo "\n";
  65          echo $this->afterContent();
  66          $this->html( 'dataAfterContent' );
  67          $this->printTrail();
  68          echo "\n</body></html>";
  69          wfRestoreWarnings();
  70      }
  71  
  72      /**
  73       * Language/charset variant links for classic-style skins
  74       * @return string
  75       */
  76  	function variantLinks() {
  77          $s = array();
  78  
  79          $variants = $this->data['content_navigation']['variants'];
  80  
  81          foreach ( $variants as $key => $link ) {
  82              $s[] = $this->makeListItem( $key, $link, array( 'tag' => 'span' ) );
  83          }
  84  
  85          return $this->getSkin()->getLanguage()->pipeList( $s );
  86      }
  87  
  88  	function otherLanguages() {
  89          if ( $this->config->get( 'HideInterlanguageLinks' ) ) {
  90              return "";
  91          }
  92  
  93          $html = '';
  94  
  95          // We override SkinTemplate->formatLanguageName() in SkinCologneBlue
  96          // not to capitalize the language names.
  97          $language_urls = $this->data['language_urls'];
  98          if ( !empty( $language_urls ) ) {
  99              $s = array();
 100              foreach ( $language_urls as $key => $data ) {
 101                  $s[] = $this->makeListItem( $key, $data, array( 'tag' => 'span' ) );
 102              }
 103  
 104              $html = wfMessage( 'otherlanguages' )->text()
 105                  . wfMessage( 'colon-separator' )->text()
 106                  . $this->getSkin()->getLanguage()->pipeList( $s );
 107          }
 108  
 109          $html .= $this->renderAfterPortlet( 'lang' );
 110  
 111          return $html;
 112      }
 113  
 114      /**
 115       * @param string $name
 116       */
 117  	protected function renderAfterPortlet( $name ) {
 118          $content = '';
 119          wfRunHooks( 'BaseTemplateAfterPortlet', array( $this, $name, &$content ) );
 120  
 121          $html = $content !== '' ? "<div class='after-portlet after-portlet-$name'>$content</div>" : '';
 122  
 123          return $html;
 124      }
 125  
 126  	function pageTitleLinks() {
 127          $s = array();
 128          $footlinks = $this->getFooterLinks();
 129  
 130          foreach ( $footlinks['places'] as $item ) {
 131              $s[] = $this->data[$item];
 132          }
 133  
 134          return $this->getSkin()->getLanguage()->pipeList( $s );
 135      }
 136  
 137      /**
 138       * Used in bottomLinks() to eliminate repetitive code.
 139       *
 140       * @param string $key Key to be passed to makeListItem()
 141       * @param array $navlink Navlink suitable for processNavlinkForDocument()
 142       * @param string $message Key of the message to use in place of standard text
 143       *
 144       * @return string
 145       */
 146  	function processBottomLink( $key, $navlink, $message = null ) {
 147          if ( !$navlink ) {
 148              // Empty navlinks might be passed.
 149              return null;
 150          }
 151  
 152          if ( $message ) {
 153              $navlink['text'] = wfMessage( $message )->escaped();
 154          }
 155  
 156          return $this->makeListItem(
 157              $key,
 158              $this->processNavlinkForDocument( $navlink ),
 159              array( 'tag' => 'span' )
 160          );
 161      }
 162  
 163  	function bottomLinks() {
 164          $toolbox = $this->getToolbox();
 165          $content_nav = $this->data['content_navigation'];
 166  
 167          $lines = array();
 168  
 169          if ( $this->getSkin()->getOutput()->isArticleRelated() ) {
 170              // First row. Regular actions.
 171              $element = array();
 172  
 173              $editLinkMessage = $this->getSkin()->getTitle()->exists() ? 'editthispage' : 'create-this-page';
 174              $element[] = $this->processBottomLink( 'edit', $content_nav['views']['edit'], $editLinkMessage );
 175              $element[] = $this->processBottomLink(
 176                  'viewsource',
 177                  $content_nav['views']['viewsource'],
 178                  'viewsource'
 179              );
 180  
 181              $element[] = $this->processBottomLink(
 182                  'watch',
 183                  $content_nav['actions']['watch'],
 184                  'watchthispage'
 185              );
 186              $element[] = $this->processBottomLink(
 187                  'unwatch',
 188                  $content_nav['actions']['unwatch'],
 189                  'unwatchthispage'
 190              );
 191  
 192              $element[] = $this->talkLink();
 193  
 194              $element[] = $this->processBottomLink( 'history', $content_nav['views']['history'], 'history' );
 195              $element[] = $this->processBottomLink( 'info', $toolbox['info'] );
 196              $element[] = $this->processBottomLink( 'whatlinkshere', $toolbox['whatlinkshere'] );
 197              $element[] = $this->processBottomLink( 'recentchangeslinked', $toolbox['recentchangeslinked'] );
 198  
 199              $element[] = $this->processBottomLink( 'contributions', $toolbox['contributions'] );
 200              $element[] = $this->processBottomLink( 'emailuser', $toolbox['emailuser'] );
 201  
 202              $lines[] = $this->getSkin()->getLanguage()->pipeList( array_filter( $element ) );
 203  
 204              // Second row. Privileged actions.
 205              $element = array();
 206  
 207              $element[] = $this->processBottomLink(
 208                  'delete',
 209                  $content_nav['actions']['delete'],
 210                  'deletethispage'
 211              );
 212              $element[] = $this->processBottomLink(
 213                  'undelete',
 214                  $content_nav['actions']['undelete'],
 215                  'undeletethispage'
 216              );
 217  
 218              $element[] = $this->processBottomLink(
 219                  'protect',
 220                  $content_nav['actions']['protect'],
 221                  'protectthispage'
 222              );
 223              $element[] = $this->processBottomLink(
 224                  'unprotect',
 225                  $content_nav['actions']['unprotect'],
 226                  'unprotectthispage'
 227              );
 228  
 229              $element[] = $this->processBottomLink( 'move', $content_nav['actions']['move'], 'movethispage' );
 230  
 231              $lines[] = $this->getSkin()->getLanguage()->pipeList( array_filter( $element ) );
 232  
 233              // Third row. Language links.
 234              $lines[] = $this->otherLanguages();
 235          }
 236  
 237          return implode( array_filter( $lines ), "<br />\n" ) . "<br />\n";
 238      }
 239  
 240  	function talkLink() {
 241          $title = $this->getSkin()->getTitle();
 242  
 243          if ( $title->getNamespace() == NS_SPECIAL ) {
 244              // No discussion links for special pages
 245              return "";
 246          }
 247  
 248          $companionTitle = $title->isTalkPage() ? $title->getSubjectPage() : $title->getTalkPage();
 249          $companionNamespace = $companionTitle->getNamespace();
 250  
 251          // TODO these messages are only be used by CologneBlue,
 252          // kill and replace with something more sensibly named?
 253          $nsToMessage = array(
 254              NS_MAIN => 'articlepage',
 255              NS_USER => 'userpage',
 256              NS_PROJECT => 'projectpage',
 257              NS_FILE => 'imagepage',
 258              NS_MEDIAWIKI => 'mediawikipage',
 259              NS_TEMPLATE => 'templatepage',
 260              NS_HELP => 'viewhelppage',
 261              NS_CATEGORY => 'categorypage',
 262              NS_FILE => 'imagepage',
 263          );
 264  
 265          // Find out the message to use for link text. Use either the array above or,
 266          // for non-talk pages, a generic "discuss this" message.
 267          // Default is the same as for main namespace.
 268          if ( isset( $nsToMessage[$companionNamespace] ) ) {
 269              $message = $nsToMessage[$companionNamespace];
 270          } else {
 271              $message = $companionTitle->isTalkPage() ? 'talkpage' : 'articlepage';
 272          }
 273  
 274          // Obviously this can't be reasonable and just return the key for talk
 275          // namespace, only for content ones. Thus we have to mangle it in
 276          // exactly the same way SkinTemplate does. (bug 40805)
 277          $key = $companionTitle->getNamespaceKey( '' );
 278          if ( $companionTitle->isTalkPage() ) {
 279              $key = ( $key == 'main' ? 'talk' : $key . "_talk" );
 280          }
 281  
 282          // Use the regular navigational link, but replace its text. Everything else stays unmodified.
 283          $namespacesLinks = $this->data['content_navigation']['namespaces'];
 284  
 285          return $this->processBottomLink( $message, $namespacesLinks[$key], $message );
 286      }
 287  
 288      /**
 289       * Takes a navigational link generated by SkinTemplate in whichever way
 290       * and mangles attributes unsuitable for repeated use. In particular, this
 291       * modifies the ids and removes the accesskeys. This is necessary to be
 292       * able to use the same navlink twice, e.g. in sidebar and in footer.
 293       *
 294       * @param array $navlink Navigational link generated by SkinTemplate
 295       * @param mixed $idPrefix Prefix to add to id of this navlink. If false, id
 296       *   is removed entirely. Default is 'cb-'.
 297       */
 298  	function processNavlinkForDocument( $navlink, $idPrefix = 'cb-' ) {
 299          if ( $navlink['id'] ) {
 300              $navlink['single-id'] = $navlink['id']; // to allow for tooltip generation
 301              $navlink['tooltiponly'] = true; // but no accesskeys
 302  
 303              // mangle or remove the id
 304              if ( $idPrefix === false ) {
 305                  unset( $navlink['id'] );
 306              } else {
 307                  $navlink['id'] = $idPrefix . $navlink['id'];
 308              }
 309          }
 310  
 311          return $navlink;
 312      }
 313  
 314      /**
 315       * @return string
 316       */
 317  	function beforeContent() {
 318          ob_start();
 319          ?>
 320          <div id="content">
 321          <div id="topbar">
 322              <p id="sitetitle" role="banner">
 323                  <a href="<?php echo htmlspecialchars( $this->data['nav_urls']['mainpage']['href'] ) ?>">
 324                      <?php echo wfMessage( 'sitetitle' )->escaped() ?>
 325                  </a>
 326              </p>
 327  
 328              <p id="sitesub"><?php echo wfMessage( 'sitesubtitle' )->escaped() ?></p>
 329  
 330              <div id="linkcollection" role="navigation">
 331                  <div id="langlinks"><?php echo str_replace( '<br />', '', $this->otherLanguages() ) ?></div>
 332                  <?php echo $this->getSkin()->getCategories() ?>
 333                  <div id="titlelinks"><?php echo $this->pageTitleLinks() ?></div>
 334                  <?php
 335                  if ( $this->data['newtalk'] ) {
 336                      ?>
 337                      <div class="usermessage"><strong><?php echo $this->data['newtalk'] ?></strong></div>
 338                  <?php
 339                  }
 340                  ?>
 341              </div>
 342          </div>
 343          <div id="article" class="mw-body" role="main">
 344          <?php
 345          if ( $this->getSkin()->getSiteNotice() ) {
 346              ?>
 347              <div id="siteNotice"><?php echo $this->getSkin()->getSiteNotice() ?></div>
 348          <?php
 349          }
 350          ?>
 351          <h1 id="firstHeading" lang="<?php
 352          $this->data['pageLanguage'] = $this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode();
 353          $this->text( 'pageLanguage' );
 354          ?>"><span dir="auto"><?php echo $this->data['title'] ?></span></h1>
 355          <?php
 356          if ( $this->translator->translate( 'tagline' ) ) {
 357              ?>
 358              <p class="tagline"><?php
 359                  echo htmlspecialchars( $this->translator->translate( 'tagline' ) )
 360                  ?></p>
 361          <?php
 362          }
 363          ?>
 364          <?php
 365          if ( $this->getSkin()->getOutput()->getSubtitle() ) {
 366              ?>
 367              <p class="subtitle"><?php echo $this->getSkin()->getOutput()->getSubtitle() ?></p>
 368          <?php
 369          }
 370          ?>
 371          <?php
 372          if ( $this->getSkin()->subPageSubtitle() ) {
 373              ?>
 374              <p class="subpages"><?php echo $this->getSkin()->subPageSubtitle() ?></p>
 375          <?php
 376          }
 377          ?>
 378          <?php
 379          $s = ob_get_contents();
 380          ob_end_clean();
 381  
 382          return $s;
 383      }
 384  
 385      /**
 386       * @return string
 387       */
 388  	function afterContent() {
 389          ob_start();
 390          ?>
 391          </div>
 392          <div id="footer">
 393              <div id="footer-navigation" role="navigation">
 394                  <?php
 395                  // Page-related links
 396                  echo $this->bottomLinks();
 397                  echo "\n<br />";
 398  
 399                  // Footer and second searchbox
 400                  echo $this->getSkin()->getLanguage()->pipeList( array(
 401                      $this->getSkin()->mainPageLink(),
 402                      $this->getSkin()->aboutLink(),
 403                      $this->searchForm( 'footer' )
 404                  ) );
 405                  ?>
 406              </div>
 407              <div id="footer-info" role="contentinfo">
 408                  <?php
 409                  // Standard footer info
 410                  $footlinks = $this->getFooterLinks();
 411                  if ( $footlinks['info'] ) {
 412                      foreach ( $footlinks['info'] as $item ) {
 413                          echo $this->data[$item] . ' ';
 414                      }
 415                  }
 416                  ?>
 417              </div>
 418          </div>
 419          </div>
 420          <div id="mw-navigation">
 421              <h2><?php echo wfMessage( 'navigation-heading' )->escaped() ?></h2>
 422  
 423              <div id="toplinks" role="navigation">
 424                  <p id="syslinks"><?php echo $this->sysLinks() ?></p>
 425  
 426                  <p id="variantlinks"><?php echo $this->variantLinks() ?></p>
 427              </div>
 428              <?php echo $this->quickBar() ?>
 429          </div>
 430          <?php
 431          $s = ob_get_contents();
 432          ob_end_clean();
 433  
 434          return $s;
 435      }
 436  
 437      /**
 438       * @return string
 439       */
 440  	function sysLinks() {
 441          $s = array(
 442              $this->getSkin()->mainPageLink(),
 443              Linker::linkKnown(
 444                  Title::newFromText( wfMessage( 'aboutpage' )->inContentLanguage()->text() ),
 445                  wfMessage( 'about' )->text()
 446              ),
 447              Linker::makeExternalLink(
 448                  Skin::makeInternalOrExternalUrl( wfMessage( 'helppage' )->inContentLanguage()->text() ),
 449                  wfMessage( 'help' )->text(),
 450                  false
 451              ),
 452              Linker::linkKnown(
 453                  Title::newFromText( wfMessage( 'faqpage' )->inContentLanguage()->text() ),
 454                  wfMessage( 'faq' )->text()
 455              ),
 456          );
 457  
 458          $personalUrls = $this->getPersonalTools();
 459          foreach ( array( 'logout', 'createaccount', 'login' ) as $key ) {
 460              if ( $personalUrls[$key] ) {
 461                  $s[] = $this->makeListItem( $key, $personalUrls[$key], array( 'tag' => 'span' ) );
 462              }
 463          }
 464  
 465          return $this->getSkin()->getLanguage()->pipeList( $s );
 466      }
 467  
 468      /**
 469       * Adds CologneBlue-specific items to the sidebar: qbedit, qbpageoptions and qbmyoptions menus.
 470       *
 471       * @param array $bar Sidebar data
 472       * @return array Modified sidebar data
 473       */
 474  	function sidebarAdditions( $bar ) {
 475          // "This page" and "Edit" menus
 476          // We need to do some massaging here... we reuse all of the items,
 477          // except for $...['views']['view'], as $...['namespaces']['main'] and
 478          // $...['namespaces']['talk'] together serve the same purpose. We also
 479          // don't use $...['variants'], these are displayed in the top menu.
 480          $content_navigation = $this->data['content_navigation'];
 481          $qbpageoptions = array_merge(
 482              $content_navigation['namespaces'],
 483              array(
 484                  'history' => $content_navigation['views']['history'],
 485                  'watch' => $content_navigation['actions']['watch'],
 486                  'unwatch' => $content_navigation['actions']['unwatch'],
 487              )
 488          );
 489          $content_navigation['actions']['watch'] = null;
 490          $content_navigation['actions']['unwatch'] = null;
 491          $qbedit = array_merge(
 492              array(
 493                  'edit' => $content_navigation['views']['edit'],
 494                  'addsection' => $content_navigation['views']['addsection'],
 495              ),
 496              $content_navigation['actions']
 497          );
 498  
 499          // Personal tools ("My pages")
 500          $qbmyoptions = $this->getPersonalTools();
 501          foreach ( array( 'logout', 'createaccount', 'login', ) as $key ) {
 502              $qbmyoptions[$key] = null;
 503          }
 504  
 505          // Use the closest reasonable name
 506          $bar['cactions'] = $qbedit;
 507          $bar['pageoptions'] = $qbpageoptions; // this is a non-standard portlet name, but nothing fits
 508          $bar['personal'] = $qbmyoptions;
 509  
 510          return $bar;
 511      }
 512  
 513      /**
 514       * Compute the sidebar
 515       * @access private
 516       *
 517       * @return string
 518       */
 519  	function quickBar() {
 520          // Massage the sidebar. We want to:
 521          // * place SEARCH at the beginning
 522          // * add new portlets before TOOLBOX (or at the end, if it's missing)
 523          // * remove LANGUAGES (langlinks are displayed elsewhere)
 524          $orig_bar = $this->data['sidebar'];
 525          $bar = array();
 526          $hasToolbox = false;
 527  
 528          // Always display search first
 529          $bar['SEARCH'] = true;
 530          // Copy everything except for langlinks, inserting new items before toolbox
 531          foreach ( $orig_bar as $heading => $data ) {
 532              if ( $heading == 'TOOLBOX' ) {
 533                  // Insert the stuff
 534                  $bar = $this->sidebarAdditions( $bar );
 535                  $hasToolbox = true;
 536              }
 537  
 538              if ( $heading != 'LANGUAGES' ) {
 539                  $bar[$heading] = $data;
 540              }
 541          }
 542          // If toolbox is missing, add our items at the end
 543          if ( !$hasToolbox ) {
 544              $bar = $this->sidebarAdditions( $bar );
 545          }
 546  
 547          // Fill out special sidebar items with content
 548          $orig_bar = $bar;
 549          $bar = array();
 550          foreach ( $orig_bar as $heading => $data ) {
 551              if ( $heading == 'SEARCH' ) {
 552                  $bar['search'] = $this->searchForm( 'sidebar' );
 553              } elseif ( $heading == 'TOOLBOX' ) {
 554                  $bar['tb'] = $this->getToolbox();
 555              } else {
 556                  $bar[$heading] = $data;
 557              }
 558          }
 559  
 560          // Output the sidebar
 561          // CologneBlue uses custom messages for some portlets, but we should keep the ids for consistency
 562          $idToMessage = array(
 563              'search' => 'qbfind',
 564              'navigation' => 'qbbrowse',
 565              'tb' => 'toolbox',
 566              'cactions' => 'qbedit',
 567              'personal' => 'qbmyoptions',
 568              'pageoptions' => 'qbpageoptions',
 569          );
 570  
 571          $s = "<div id='quickbar'>\n";
 572  
 573          foreach ( $bar as $heading => $data ) {
 574              $portletId = Sanitizer::escapeId( "p-$heading" );
 575              $headingMsg = wfMessage( $idToMessage[$heading] ? $idToMessage[$heading] : $heading );
 576              $headingHTML = "<h3>";
 577              $headingHTML .= $headingMsg->exists()
 578                  ? $headingMsg->escaped()
 579                  : htmlspecialchars( $heading );
 580              $headingHTML .= "</h3>";
 581              $listHTML = "";
 582  
 583              if ( is_array( $data ) ) {
 584                  // $data is an array of links
 585                  foreach ( $data as $key => $link ) {
 586                      // Can be empty due to how the sidebar additions are done
 587                      if ( $link ) {
 588                          $listHTML .= $this->makeListItem( $key, $link );
 589                      }
 590                  }
 591                  if ( $listHTML ) {
 592                      $listHTML = "<ul>$listHTML</ul>";
 593                  }
 594              } else {
 595                  // $data is a HTML <ul>-list string
 596                  $listHTML = $data;
 597              }
 598  
 599              if ( $listHTML ) {
 600                  $role = ( $heading == 'search' ) ? 'search' : 'navigation';
 601                  $s .= "<div class=\"portlet\" id=\"$portletId\" "
 602                      . "role=\"$role\">\n$headingHTML\n$listHTML\n</div>\n";
 603              }
 604  
 605              $s .= $this->renderAfterPortlet( $heading );
 606          }
 607  
 608          $s .= "</div>\n";
 609  
 610          return $s;
 611      }
 612  
 613      /**
 614       * @param string $label
 615       * @return string
 616       */
 617  	function searchForm( $which ) {
 618          $search = $this->getSkin()->getRequest()->getText( 'search' );
 619          $action = $this->data['searchaction'];
 620          $s = "<form id=\"searchform-" . htmlspecialchars( $which )
 621              . "\" method=\"get\" class=\"inline\" action=\"$action\">";
 622          if ( $which == 'footer' ) {
 623              $s .= wfMessage( 'qbfind' )->text() . ": ";
 624          }
 625  
 626          $s .= $this->makeSearchInput( array(
 627              'class' => 'mw-searchInput',
 628              'type' => 'text',
 629              'size' => '14'
 630          ) );
 631          $s .= ( $which == 'footer' ? " " : "<br />" );
 632          $s .= $this->makeSearchButton( 'go', array( 'class' => 'searchButton' ) );
 633  
 634          if ( $this->config->get( 'UseTwoButtonsSearchForm' ) ) {
 635              $s .= $this->makeSearchButton( 'fulltext', array( 'class' => 'searchButton' ) );
 636          } else {
 637              $s .= '<div><a href="' . $action . '" rel="search">'
 638                  . wfMessage( 'powersearch-legend' )->escaped() . "</a></div>\n";
 639          }
 640  
 641          $s .= '</form>';
 642  
 643          return $s;
 644      }
 645  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1