MediaWiki  REL1_22
ResourceLoaderWikiModule.php
Go to the documentation of this file.
00001 <?php
00032 abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
00033 
00034     /* Protected Members */
00035 
00036     # Origin is user-supplied code
00037     protected $origin = self::ORIGIN_USER_SITEWIDE;
00038 
00039     // In-object cache for title mtimes
00040     protected $titleMtimes = array();
00041 
00042     /* Abstract Protected Methods */
00043 
00060     abstract protected function getPages( ResourceLoaderContext $context );
00061 
00062     /* Protected Methods */
00063 
00075     protected function getDB() {
00076         return wfGetDB( DB_SLAVE );
00077     }
00078 
00083     protected function getContent( $title ) {
00084         if ( !$title->isCssJsSubpage() && !$title->isCssOrJsPage() ) {
00085             return null;
00086         }
00087         $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
00088         if ( !$revision ) {
00089             return null;
00090         }
00091 
00092         $content = $revision->getContent( Revision::RAW );
00093 
00094         if ( !$content ) {
00095             wfDebugLog( 'resourceloader', __METHOD__ . ': failed to load content of JS/CSS page!' );
00096             return null;
00097         }
00098 
00099         $model = $content->getModel();
00100 
00101         if ( $model !== CONTENT_MODEL_CSS && $model !== CONTENT_MODEL_JAVASCRIPT ) {
00102             wfDebugLog( 'resourceloader', __METHOD__ . ': bad content model $model for JS/CSS page!' );
00103             return null;
00104         }
00105 
00106         return $content->getNativeData(); //NOTE: this is safe, we know it's JS or CSS
00107     }
00108 
00109     /* Methods */
00110 
00115     public function getScript( ResourceLoaderContext $context ) {
00116         $scripts = '';
00117         foreach ( $this->getPages( $context ) as $titleText => $options ) {
00118             if ( $options['type'] !== 'script' ) {
00119                 continue;
00120             }
00121             $title = Title::newFromText( $titleText );
00122             if ( !$title || $title->isRedirect() ) {
00123                 continue;
00124             }
00125             $script = $this->getContent( $title );
00126             if ( strval( $script ) !== '' ) {
00127                 $script = $this->validateScriptFile( $titleText, $script );
00128                 if ( strpos( $titleText, '*/' ) === false ) {
00129                     $scripts .= "/* $titleText */\n";
00130                 }
00131                 $scripts .= $script . "\n";
00132             }
00133         }
00134         return $scripts;
00135     }
00136 
00141     public function getStyles( ResourceLoaderContext $context ) {
00142         global $wgScriptPath;
00143 
00144         $styles = array();
00145         foreach ( $this->getPages( $context ) as $titleText => $options ) {
00146             if ( $options['type'] !== 'style' ) {
00147                 continue;
00148             }
00149             $title = Title::newFromText( $titleText );
00150             if ( !$title || $title->isRedirect() ) {
00151                 continue;
00152             }
00153             $media = isset( $options['media'] ) ? $options['media'] : 'all';
00154             $style = $this->getContent( $title );
00155             if ( strval( $style ) === '' ) {
00156                 continue;
00157             }
00158             if ( $this->getFlip( $context ) ) {
00159                 $style = CSSJanus::transform( $style, true, false );
00160             }
00161             $style = CSSMin::remap( $style, false, $wgScriptPath, true );
00162             if ( !isset( $styles[$media] ) ) {
00163                 $styles[$media] = array();
00164             }
00165             if ( strpos( $titleText, '*/' ) === false ) {
00166                 $style = "/* $titleText */\n" . $style;
00167             }
00168             $styles[$media][] = $style;
00169         }
00170         return $styles;
00171     }
00172 
00177     public function getModifiedTime( ResourceLoaderContext $context ) {
00178         $modifiedTime = 1; // wfTimestamp() interprets 0 as "now"
00179         $mtimes = $this->getTitleMtimes( $context );
00180         if ( count( $mtimes ) ) {
00181             $modifiedTime = max( $modifiedTime, max( $mtimes ) );
00182         }
00183         $modifiedTime = max( $modifiedTime, $this->getMsgBlobMtime( $context->getLanguage() ) );
00184         return $modifiedTime;
00185     }
00186 
00191     public function isKnownEmpty( ResourceLoaderContext $context ) {
00192         return count( $this->getTitleMtimes( $context ) ) == 0;
00193     }
00194 
00201     protected function getTitleMtimes( ResourceLoaderContext $context ) {
00202         $dbr = $this->getDB();
00203         if ( !$dbr ) {
00204             // We're dealing with a subclass that doesn't have a DB
00205             return array();
00206         }
00207 
00208         $hash = $context->getHash();
00209         if ( isset( $this->titleMtimes[$hash] ) ) {
00210             return $this->titleMtimes[$hash];
00211         }
00212 
00213         $this->titleMtimes[$hash] = array();
00214         $batch = new LinkBatch;
00215         foreach ( $this->getPages( $context ) as $titleText => $options ) {
00216             $batch->addObj( Title::newFromText( $titleText ) );
00217         }
00218 
00219         if ( !$batch->isEmpty() ) {
00220             $res = $dbr->select( 'page',
00221                 array( 'page_namespace', 'page_title', 'page_touched' ),
00222                 $batch->constructSet( 'page', $dbr ),
00223                 __METHOD__
00224             );
00225             foreach ( $res as $row ) {
00226                 $title = Title::makeTitle( $row->page_namespace, $row->page_title );
00227                 $this->titleMtimes[$hash][$title->getPrefixedDBkey()] =
00228                     wfTimestamp( TS_UNIX, $row->page_touched );
00229             }
00230         }
00231         return $this->titleMtimes[$hash];
00232     }
00233 }