4
\$\begingroup\$

There isn't a very reliable way (in my opinion) to get the mime type of a specific extension, regardless of the file actually being of that type or not.

This type of thing usually is used when sending a different Content-type when you intend to send, for example, an image.

class MIMETypes {
 /**
 * @var string Contains the default type when none is found
 * @access protected
 */
 static private $default='application/octet-stream';
 /**
 * @var array Contains all the mime types and extensions
 * @access protected
 */
 static private $mimes=array(
 'text'=>array(
 'plain'=>array(
 'php','php5','php4','php3','inc','sphp','phps','phtml',
 'htm','html',
 'txt'
 )
 ),
 'audio'=>array(
 'aac'=>array('aac'),
 'midi'=>array('mid','midi'),
 'mp4'=>array('mp4','m4a'),
 'mpeg'=>array('m2a','mp1','mp2','mp3','mp4','mpg','mpeg','mpa','mpga'),
 'ogg'=>array('oga','ogg'),
 'wav'=>array('wav','wave','pcm'),
 'webm'=>array('webm'),
 'x-mpequrl'=>array('m3u')
 ),
 'video'=>array(
 'mp4'=>array('mp4','m4v','m1v','m2v'),
 'ogg'=>array('ogv'),
 'webm'=>array('webm')
 )
 );
 /**
 * @var array Contains the last accessed contents and comes pre-initialized with some extensions and mime types that didn't matched
 * @access protected
 */ 
 static private $cache=array(
 'ext'=>array(
 'txt'=>array('plain/text')
 ),
 'mime'=>array(
 '*/*'=>array()
 )
 );
 /**
 * Creates a list of matching mime types for that file extension
 * @param string $ext The extension to look for
 * @param string|null $hint Hint to reduce the search load for only that mime "group"<br/>
 * *WARNING*: Setting this parameter will ignore the cache!
 * @return array An array with the multiple mime types
 */
 static function fromExt( $ext, $hint=null )
 {
 //this will have all matched mime types
 $exts = array();
 //clean up the $ext var, to hold nothing but an extension
 $ext = preg_replace( '@^(?:.*\.)*([^.\\]+)$@', '1ドル', $ext );
 if( func_num_args() > 1 )
 {
 $hint = strtolower( trim($hint) );
 foreach( self::$mimes[$hint] as $mime=>$types)
 {
 if( in_array( $ext, $types) )
 {
 $exts[] = $hint . '/' . $mime;
 }
 }
 }
 else if( self::$cache['ext'][$ext] )
 {
 return self::$cache['ext'][$ext];
 }
 else
 {
 foreach( self::$mimes as $mime=>$mimes)
 {
 foreach( $mimes as $type=>$types)
 {
 if( in_array( $ext, $list) )
 {
 $exts[] = $mime . '/' . $type;
 }
 }
 }
 if(!$exts)
 {
 $exts=array( self::$default );
 }
 }
 return self::$cache['ext'][$ext] = $exts;
 }
 /**
 * Creates a list of matching extensions for that mime type
 * @param string $mime The extension to look for
 * @return array An array with the multiple extensions
 */
 static function fromMIME( $mime )
 {
 //'clean' blindly-exploded mime type 
 $mime_c=explode('/', $mime, 2);
 if( self::$cache['mime'][$mime] )
 {
 return array(); //self::$cache['mime'][$mime];
 }
 else if( self::$mimes[$mime_c[0]] )
 {
 return self::$mimes[$mime_c[0]][$mime_c[1]];
 }
 else
 {
 return self::$cache['mime'][$mime] = array();
 }
 }
}

The functioning of the class is complete, but I'm aware that there are lots of missing mime types like the image/* or application/*.

What can I do to improve my code in quality and make a better class and (maybe) make it production-ready?

What should I improve in terms of performance?

asked Jan 2, 2015 at 17:05
\$\endgroup\$
2
  • \$\begingroup\$ What if you have two different mime types that share the same file extension? This is a possibility. Personally, I would determine the mime type based on the data contain in the file, and cache the findings. Then when the file is requested, get the mime type from the cache. \$\endgroup\$ Commented Jan 7, 2015 at 16:12
  • \$\begingroup\$ @Bonner If you already have a 'hint' on what mime type the file will have (if you are dealing with audio files, for example), you can set the 2nd parameter on the method fromExt(). E.g.: MIMETypes::fromExt('mp4','audio') and it should return an array with only 1 mime type. If you don't set, it will return an array with all the mime types matching that extension. An example would be the extension mp4 (MIMETypes::fromExt('mp4')) which will return an array containing the mime types audio/mp4 and video/mp4. \$\endgroup\$ Commented Jan 7, 2015 at 18:05

1 Answer 1

3
\$\begingroup\$

This is mostly a style review, but I'll be back to work on it further later.


Your usage of whitespace leaves a bit to be desired.

  1. You should have whitespace in between your key => value, rather than none.
  2. You should have spaces between commas
  3. You should have spaces in between your binary operators static private $default='application/octet-stream'
  4. You shouldn't have whitespace before and after your brackets

You should consider moving the regex statement in the following line to an external variable.

$ext = preg_replace( '@^(?:.*\.)*([^.\\]+)$@', '1ドル', $ext );
answered Jul 5, 2015 at 3:56
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.