MediaWiki  REL1_24
SkinFactory.php
Go to the documentation of this file.
00001 <?php
00002 
00029 class SkinFactory {
00030 
00035     private $factoryFunctions = array();
00042     private $displayNames = array();
00049     private $legacySkins = array();
00050 
00054     private static $self;
00055 
00056     public static function getDefaultInstance() {
00057         if ( !self::$self ) {
00058             self::$self = new self;
00059         }
00060 
00061         return self::$self;
00062     }
00063 
00077     public function register( $name, $displayName, $callback ) {
00078         if ( !is_callable( $callback ) ) {
00079             throw new InvalidArgumentException( 'Invalid callback provided' );
00080         }
00081         $this->factoryFunctions[$name] = $callback;
00082         $this->displayNames[$name] = $displayName;
00083     }
00084 
00088     private function getLegacySkinNames() {
00089         static $skinsInitialised = false;
00090 
00091         if ( !$skinsInitialised || !count( $this->legacySkins ) ) {
00092             # Get a list of available skins
00093             # Build using the regular expression '^(.*).php$'
00094             # Array keys are all lower case, array value keep the case used by filename
00095             #
00096             wfProfileIn( __METHOD__ . '-init' );
00097 
00098             global $wgStyleDirectory;
00099 
00100             $skinDir = dir( $wgStyleDirectory );
00101 
00102             if ( $skinDir !== false && $skinDir !== null ) {
00103                 # while code from www.php.net
00104                 while ( false !== ( $file = $skinDir->read() ) ) {
00105                     // Skip non-PHP files, hidden files, and '.dep' includes
00106                     $matches = array();
00107 
00108                     if ( preg_match( '/^([^.]*)\.php$/', $file, $matches ) ) {
00109                         $aSkin = $matches[1];
00110 
00111                         // Explicitly disallow loading core skins via the autodiscovery mechanism.
00112                         //
00113                         // They should be loaded already (in a non-autodicovery way), but old files might still
00114                         // exist on the server because our MW version upgrade process is widely documented as
00115                         // requiring just copying over all files, without removing old ones.
00116                         //
00117                         // This is one of the reasons we should have never used autodiscovery in the first
00118                         // place. This hack can be safely removed when autodiscovery is gone.
00119                         if ( in_array( $aSkin, array( 'CologneBlue', 'Modern', 'MonoBook', 'Vector' ) ) ) {
00120                             wfLogWarning(
00121                                 "An old copy of the $aSkin skin was found in your skins/ directory. " .
00122                                 "You should remove it to avoid problems in the future." .
00123                                 "See https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery for details."
00124                             );
00125                             continue;
00126                         }
00127 
00128                         wfLogWarning(
00129                             "A skin using autodiscovery mechanism, $aSkin, was found in your skins/ directory. " .
00130                             "The mechanism will be removed in MediaWiki 1.25 and the skin will no longer be recognized. " .
00131                             "See https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery for information how to fix this."
00132                         );
00133                         $this->legacySkins[strtolower( $aSkin )] = $aSkin;
00134                     }
00135                 }
00136                 $skinDir->close();
00137             }
00138             $skinsInitialised = true;
00139             wfProfileOut( __METHOD__ . '-init' );
00140         }
00141         return $this->legacySkins;
00142 
00143     }
00144 
00151     public function getSkinNames() {
00152         return array_merge(
00153             $this->getLegacySkinNames(),
00154             $this->displayNames
00155         );
00156     }
00157 
00164     private function getLegacySkin( $name ) {
00165         $skinNames = $this->getLegacySkinNames();
00166         if ( !isset( $skinNames[$name] ) ) {
00167             return false;
00168         }
00169         $skinName = $skinNames[$name];
00170         $className = "Skin{$skinName}";
00171 
00172         # Grab the skin class and initialise it.
00173         if ( !class_exists( $className ) ) {
00174             global $wgStyleDirectory;
00175             require_once "{$wgStyleDirectory}/{$skinName}.php";
00176 
00177             # Check if we got it
00178             if ( !class_exists( $className ) ) {
00179                 # DO NOT die if the class isn't found. This breaks maintenance
00180                 # scripts and can cause a user account to be unrecoverable
00181                 # except by SQL manipulation if a previously valid skin name
00182                 # is no longer valid.
00183                 return false;
00184             }
00185         }
00186         $skin = new $className( $name );
00187         return $skin;
00188 
00189     }
00190 
00198     public function makeSkin( $name ) {
00199         if ( !isset( $this->factoryFunctions[$name] ) ) {
00200             // Check the legacy autodiscovery method of skin loading
00201             $legacy = $this->getLegacySkin( $name );
00202             if ( $legacy ) {
00203                 return $legacy;
00204             }
00205             throw new SkinException( "No registered builder available for $name." );
00206         }
00207         $skin = call_user_func( $this->factoryFunctions[$name], $name );
00208         if ( $skin instanceof Skin ) {
00209             return $skin;
00210         } else {
00211             throw new UnexpectedValueException( "The builder for $name returned a non-Skin object." );
00212         }
00213     }
00214 }