Allow third party code to hook-up MIME type detection
authorrillke <rainerrillke@hotmail.com>
Sat, 21 Jun 2014 12:00:55 +0000 (14:00 +0200)
committerrillke <rainerrillke@hotmail.com>
Sun, 6 Jul 2014 11:38:14 +0000 (13:38 +0200)
Adding 3 hooks to MimeMagic.php

- MimeMagicInit: Add assignments of MIME types -> Media types
  and assignments of MIME types -> File extensions
- MimeMagicImproveFromExtension: Further improve the MIME type detected
  by considering the file extension
- MimeMagicGuessFromContent: Guess the MIME from file content

This is the successor of Icf9eec10bec7c0a7e.

PHP's own module fileinfo module is not capable detecting Chemical
table files. Instead, they are reported as text/plain.

MediaHandlers can be attached by MIME type only. That's why these
changes are required for [[Extension:MolHandler]] to work.

Clean up:
Do not create unused property MimeMagic::mToMime.

Change-Id: I67f3e4e83b47e6df0d9e8371f09a741a8aa77651

docs/hooks.txt
includes/MimeMagic.php

index b1ef47c..7cbb5d1 100644 (file)
@@ -1757,6 +1757,30 @@ caches.
 $title: name of the page changed.
 $text: new contents of the page.
 
+'MimeMagicInit': Before processing the list mapping MIME types to media types
+and the list mapping MIME types to file extensions.
+As an extension author, you are encouraged to submit patches to MediaWiki's
+core to add new MIME types to mime.types.
+$mimeMagic: Instance of MimeMagic.
+  Use $mimeMagic->addExtraInfo( $stringOfInfo );
+  for adding new MIME info to the list.
+  Use $mimeMagic->addExtraTypes( $stringOfTypes );
+  for adding new MIME types to the list.
+
+'MimeMagicImproveFromExtension': Allows MW extensions to further improve the
+MIME type detected by considering the file extension.
+$mimeMagic: Instance of MimeMagic.
+$ext: File extension.
+&$mime: MIME type (in/out).
+
+'MimeMagicGuessFromContent': Allows MW extensions guess the MIME by content.
+$mimeMagic: Instance of MimeMagic.
+&$head: First 1024 bytes of the file in a string (in - Do not alter!).
+&$tail: More or equal than last 65558 bytes of the file in a string
+  (in - Do not alter!).
+$file: File path.
+&$mime: MIME type (out).
+
 'ModifyExportQuery': Modify the query used by the exporter.
 $db: The database object to be queried.
 &$tables: Tables in the query.
index 59f850c..b4d3ab1 100644 (file)
@@ -164,6 +164,14 @@ class MimeMagic {
         */
        protected $mIEAnalyzer;
 
+       /** @var string Extra MIME types, set for example by media handling extensions
+        */
+       private $mExtraTypes = '';
+
+       /** @var string Extra MIME info, set for example by media handling extensions
+        */
+       private $mExtraInfo = '';
+
        /** @var MimeMagic The singleton instance
         */
        private static $instance = null;
@@ -179,6 +187,9 @@ class MimeMagic {
 
                global $wgMimeTypeFile, $IP;
 
+               # Allow media handling extensions adding MIME-types and MIME-info
+               wfRunHooks( 'MimeMagicInit', array( $this ) );
+
                $types = MM_WELL_KNOWN_MIME_TYPES;
 
                if ( $wgMimeTypeFile == 'includes/mime.types' ) {
@@ -197,11 +208,13 @@ class MimeMagic {
                        wfDebug( __METHOD__ . ": no mime types file defined, using build-ins only.\n" );
                }
 
+               $types .= "\n" . $this->mExtraTypes;
+
                $types = str_replace( array( "\r\n", "\n\r", "\n\n", "\r\r", "\r" ), "\n", $types );
                $types = str_replace( "\t", " ", $types );
 
                $this->mMimeToExt = array();
-               $this->mToMime = array();
+               $this->mExtToMime = array();
 
                $lines = explode( "\n", $types );
                foreach ( $lines as $s ) {
@@ -272,6 +285,8 @@ class MimeMagic {
                        wfDebug( __METHOD__ . ": no mime info file defined, using build-ins only.\n" );
                }
 
+               $info .= "\n" . $this->mExtraInfo;
+
                $info = str_replace( array( "\r\n", "\n\r", "\n\n", "\r\r", "\r" ), "\n", $info );
                $info = str_replace( "\t", " ", $info );
 
@@ -342,6 +357,26 @@ class MimeMagic {
                return self::$instance;
        }
 
+       /**
+        * Adds to the list mapping MIME to file extensions.
+        * As an extension author, you are encouraged to submit patches to
+        * MediaWiki's core to add new MIME types to mime.types.
+        * @param string $types
+        */
+       public function addExtraTypes( $types ) {
+               $this->mExtraTypes .= "\n" . $types;
+       }
+
+       /**
+        * Adds to the list mapping MIME to media type.
+        * As an extension author, you are encouraged to submit patches to
+        * MediaWiki's core to add new MIME info to mime.info.
+        * @param string $info
+        */
+       public function addExtraInfo( $info ) {
+               $this->mExtraInfo .= "\n" . $info;
+       }
+
        /**
         * Returns a list of file extensions for a given mime type as a space
         * separated string or null if the mime type was unrecognized. Resolves
@@ -518,6 +553,9 @@ class MimeMagic {
                        $mime = $this->guessTypesForExtension( $ext );
                }
 
+               # Media handling extensions can improve the MIME detected
+               wfRunHooks( 'MimeMagicImproveFromExtension', array( $this, $ext, &$mime ) );
+
                if ( isset( $this->mMimeTypeAliases[$mime] ) ) {
                        $mime = $this->mMimeTypeAliases[$mime];
                }
@@ -744,7 +782,17 @@ class MimeMagic {
                        return 'image/vnd.djvu';
                }
 
-               return false;
+               # Media handling extensions can guess the MIME by content
+               # It's intentionally here so that if core is wrong about a type (false positive),
+               # people will hopefully nag and submit patches :)
+               $mime = false;
+               # Some strings by reference for performance - assuming well-behaved hooks
+               wfRunHooks(
+                       'MimeMagicGuessFromContent',
+                       array( $this, &$head, &$tail, $file, &$mime )
+               );
+
+               return $mime;
        }
 
        /**