MediaWiki  master
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 
00047         abstract protected function getPages( ResourceLoaderContext $context );
00048 
00049         /* Protected Methods */
00050 
00062         protected function getDB() {
00063                 return wfGetDB( DB_SLAVE );
00064         }
00065 
00070         protected function getContent( $title ) {
00071                 if ( !$title->isCssJsSubpage() && !$title->isCssOrJsPage() ) {
00072                         return null;
00073                 }
00074                 $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
00075                 if ( !$revision ) {
00076                         return null;
00077                 }
00078 
00079                 $content = $revision->getContent( Revision::RAW );
00080 
00081                 if ( !$content ) {
00082                         wfDebug( __METHOD__ . "failed to load content of JS/CSS page!\n" );
00083                         return null;
00084                 }
00085 
00086                 $model = $content->getModel();
00087 
00088                 if ( $model !== CONTENT_MODEL_CSS && $model !== CONTENT_MODEL_JAVASCRIPT ) {
00089                         wfDebug( __METHOD__ . "bad content model $model for JS/CSS page!\n" );
00090                         return null;
00091                 }
00092 
00093                 return $content->getNativeData(); //NOTE: this is safe, we know it's JS or CSS
00094         }
00095 
00096         /* Methods */
00097 
00102         public function getScript( ResourceLoaderContext $context ) {
00103                 $scripts = '';
00104                 foreach ( $this->getPages( $context ) as $titleText => $options ) {
00105                         if ( $options['type'] !== 'script' ) {
00106                                 continue;
00107                         }
00108                         $title = Title::newFromText( $titleText );
00109                         if ( !$title || $title->isRedirect() ) {
00110                                 continue;
00111                         }
00112                         $script = $this->getContent( $title );
00113                         if ( strval( $script ) !== '' ) {
00114                                 $script = $this->validateScriptFile( $titleText, $script );
00115                                 if ( strpos( $titleText, '*/' ) === false ) {
00116                                         $scripts .=  "/* $titleText */\n";
00117                                 }
00118                                 $scripts .= $script . "\n";
00119                         }
00120                 }
00121                 return $scripts;
00122         }
00123 
00128         public function getStyles( ResourceLoaderContext $context ) {
00129                 global $wgScriptPath;
00130 
00131                 $styles = array();
00132                 foreach ( $this->getPages( $context ) as $titleText => $options ) {
00133                         if ( $options['type'] !== 'style' ) {
00134                                 continue;
00135                         }
00136                         $title = Title::newFromText( $titleText );
00137                         if ( !$title || $title->isRedirect()  ) {
00138                                 continue;
00139                         }
00140                         $media = isset( $options['media'] ) ? $options['media'] : 'all';
00141                         $style = $this->getContent( $title );
00142                         if ( strval( $style ) === '' ) {
00143                                 continue;
00144                         }
00145                         if ( $this->getFlip( $context ) ) {
00146                                 $style = CSSJanus::transform( $style, true, false );
00147                         }
00148                         $style = CSSMin::remap( $style, false, $wgScriptPath, true );
00149                         if ( !isset( $styles[$media] ) ) {
00150                                 $styles[$media] = array();
00151                         }
00152                         if ( strpos( $titleText, '*/' ) === false ) {
00153                                 $style =  "/* $titleText */\n" . $style;
00154                         }
00155                         $styles[$media][] = $style;
00156                 }
00157                 return $styles;
00158         }
00159 
00164         public function getModifiedTime( ResourceLoaderContext $context ) {
00165                 $modifiedTime = 1; // wfTimestamp() interprets 0 as "now"
00166                 $mtimes = $this->getTitleMtimes( $context );
00167                 if ( count( $mtimes ) ) {
00168                         $modifiedTime = max( $modifiedTime, max( $mtimes ) );
00169                 }
00170                 $modifiedTime = max( $modifiedTime, $this->getMsgBlobMtime( $context->getLanguage() ) );
00171                 return $modifiedTime;
00172         }
00173 
00178         public function isKnownEmpty( ResourceLoaderContext $context ) {
00179                 return count( $this->getTitleMtimes( $context ) ) == 0;
00180         }
00181 
00188         protected function getTitleMtimes( ResourceLoaderContext $context ) {
00189                 $dbr = $this->getDB();
00190                 if ( !$dbr ) {
00191                         // We're dealing with a subclass that doesn't have a DB
00192                         return array();
00193                 }
00194 
00195                 $hash = $context->getHash();
00196                 if ( isset( $this->titleMtimes[$hash] ) ) {
00197                         return $this->titleMtimes[$hash];
00198                 }
00199 
00200                 $this->titleMtimes[$hash] = array();
00201                 $batch = new LinkBatch;
00202                 foreach ( $this->getPages( $context ) as $titleText => $options ) {
00203                         $batch->addObj( Title::newFromText( $titleText ) );
00204                 }
00205 
00206                 if ( !$batch->isEmpty() ) {
00207                         $res = $dbr->select( 'page',
00208                                 array( 'page_namespace', 'page_title', 'page_touched' ),
00209                                 $batch->constructSet( 'page', $dbr ),
00210                                 __METHOD__
00211                         );
00212                         foreach ( $res as $row ) {
00213                                 $title = Title::makeTitle( $row->page_namespace, $row->page_title );
00214                                 $this->titleMtimes[$hash][$title->getPrefixedDBkey()] =
00215                                         wfTimestamp( TS_UNIX, $row->page_touched );
00216                         }
00217                 }
00218                 return $this->titleMtimes[$hash];
00219         }
00220 }