+ public function headElement( Skin $sk, $includeStyle = true ) {
+ global $wgOutputEncoding, $wgMimeType;
+ global $wgUseTrackbacks, $wgHtml5;
+ global $wgUser, $wgRequest, $wgLang;
+
+ if ( $sk->commonPrintStylesheet() ) {
+ $this->addModuleStyles( 'mediawiki.legacy.wikiprintable' );
+ }
+ $sk->setupUserCss( $this );
+
+ $lang = wfUILang();
+ $ret = Html::htmlHeader( array( 'lang' => $lang->getCode(), 'dir' => $lang->getDir() ) );
+
+ if ( $this->getHTMLTitle() == '' ) {
+ $this->setHTMLTitle( wfMsg( 'pagetitle', $this->getPageTitle() ) );
+ }
+
+ $openHead = Html::openElement( 'head' );
+ if ( $openHead ) {
+ # Don't bother with the newline if $head == ''
+ $ret .= "$openHead\n";
+ }
+
+ if ( $wgHtml5 ) {
+ # More succinct than <meta http-equiv=Content-Type>, has the
+ # same effect
+ $ret .= Html::element( 'meta', array( 'charset' => $wgOutputEncoding ) ) . "\n";
+ } else {
+ $this->addMeta( 'http:Content-Type', "$wgMimeType; charset=$wgOutputEncoding" );
+ }
+
+ $ret .= Html::element( 'title', null, $this->getHTMLTitle() ) . "\n";
+
+ $ret .= implode( "\n", array(
+ $this->getHeadLinks( $sk ),
+ $this->buildCssLinks( $sk ),
+ $this->getHeadItems()
+ ) );
+
+ if ( $wgUseTrackbacks && $this->isArticleRelated() ) {
+ $ret .= $this->getTitle()->trackbackRDF();
+ }
+
+ $closeHead = Html::closeElement( 'head' );
+ if ( $closeHead ) {
+ $ret .= "$closeHead\n";
+ }
+
+ $bodyAttrs = array();
+
+ # Crazy edit-on-double-click stuff
+ $action = $wgRequest->getVal( 'action', 'view' );
+
+ if (
+ $this->getTitle()->getNamespace() != NS_SPECIAL &&
+ !in_array( $action, array( 'edit', 'submit' ) ) &&
+ $wgUser->getOption( 'editondblclick' )
+ )
+ {
+ $editUrl = $this->getTitle()->getLocalUrl( $sk->editUrlOptions() );
+ $bodyAttrs['ondblclick'] = "document.location = '" .
+ Xml::escapeJsString( $editUrl ) . "'";
+ }
+
+ # Class bloat
+ $dir = wfUILang()->getDir();
+ $bodyAttrs['class'] = "mediawiki $dir";
+
+ if ( $wgLang->capitalizeAllNouns() ) {
+ # A <body> class is probably not the best way to do this . . .
+ $bodyAttrs['class'] .= ' capitalize-all-nouns';
+ }
+ $bodyAttrs['class'] .= ' ns-' . $this->getTitle()->getNamespace();
+ if ( $this->getTitle()->getNamespace() == NS_SPECIAL ) {
+ $bodyAttrs['class'] .= ' ns-special';
+ } elseif ( $this->getTitle()->isTalkPage() ) {
+ $bodyAttrs['class'] .= ' ns-talk';
+ } else {
+ $bodyAttrs['class'] .= ' ns-subject';
+ }
+ $bodyAttrs['class'] .= ' ' . Sanitizer::escapeClass( 'page-' . $this->getTitle()->getPrefixedText() );
+ $bodyAttrs['class'] .= ' skin-' . Sanitizer::escapeClass( $wgUser->getSkin()->getSkinName() );
+
+ $sk->addToBodyAttributes( $this, $bodyAttrs ); // Allow skins to add body attributes they need
+ wfRunHooks( 'OutputPageBodyAttributes', array( $this, $sk, &$bodyAttrs ) );
+
+ $ret .= Html::openElement( 'body', $bodyAttrs ) . "\n";
+
+ return $ret;
+ }
+
+ /**
+ * Get a ResourceLoader object associated with this OutputPage
+ */
+ public function getResourceLoader() {
+ if ( is_null( $this->mResourceLoader ) ) {
+ $this->mResourceLoader = new ResourceLoader();
+ }
+ return $this->mResourceLoader;
+ }
+
+ /**
+ * TODO: Document
+ * @param $skin Skin
+ * @param $modules Array/string with the module name
+ * @param $only string May be styles, messages or scripts
+ * @param $useESI boolean
+ * @return string html <script> and <style> tags
+ */
+ protected function makeResourceLoaderLink( Skin $skin, $modules, $only, $useESI = false ) {
+ global $wgUser, $wgLang, $wgLoadScript, $wgResourceLoaderUseESI, $wgRequest;
+ // Lazy-load ResourceLoader
+ // TODO: Should this be a static function of ResourceLoader instead?
+ $baseQuery = array(
+ 'lang' => $wgLang->getCode(),
+ 'debug' => ResourceLoader::inDebugMode() ? 'true' : 'false',
+ 'skin' => $skin->getSkinName(),
+ 'only' => $only,
+ );
+ // Propagate printable and handheld parameters if present
+ if ( $wgRequest->getBool( 'printable' ) ) {
+ $baseQuery['printable'] = 1;
+ }
+ if ( $wgRequest->getBool( 'handheld' ) ) {
+ $baseQuery['handheld'] = 1;
+ }
+
+ if ( !count( $modules ) ) {
+ return '';
+ }
+
+ if ( count( $modules ) > 1 ) {
+ // Remove duplicate module requests
+ $modules = array_unique( (array) $modules );
+ // Sort module names so requests are more uniform
+ sort( $modules );
+
+ if ( ResourceLoader::inDebugMode() ) {
+ // Recursively call us for every item
+ $links = '';
+ foreach ( $modules as $name ) {
+ $links .= $this->makeResourceLoaderLink( $skin, $name, $only, $useESI );
+ }
+ return $links;
+ }