1: <?php
2:
3: /*
4: * This file is part of the Symfony package.
5: *
6: * (c) Fabien Potencier <fabien@symfony.com>
7: *
8: * For the full copyright and license information, please view the LICENSE
9: * file that was distributed with this source code.
10: */
11:
12: namespace Symfony\Component\HttpFoundation\File\MimeType;
13:
14: use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
15: use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
16:
17: /**
18: * A singleton mime type guesser.
19: *
20: * By default, all mime type guessers provided by the framework are installed
21: * (if available on the current OS/PHP setup).
22: *
23: * You can register custom guessers by calling the register() method on the
24: * singleton instance. Custom guessers are always called before any default ones.
25: *
26: * $guesser = MimeTypeGuesser::getInstance();
27: * $guesser->register(new MyCustomMimeTypeGuesser());
28: *
29: * If you want to change the order of the default guessers, just re-register your
30: * preferred one as a custom one. The last registered guesser is preferred over
31: * previously registered ones.
32: *
33: * Re-registering a built-in guesser also allows you to configure it:
34: *
35: * $guesser = MimeTypeGuesser::getInstance();
36: * $guesser->register(new FileinfoMimeTypeGuesser('/path/to/magic/file'));
37: *
38: * @author Bernhard Schussek <bschussek@gmail.com>
39: */
40: class MimeTypeGuesser implements MimeTypeGuesserInterface
41: {
42: /**
43: * The singleton instance.
44: *
45: * @var MimeTypeGuesser
46: */
47: private static $instance = null;
48:
49: /**
50: * All registered MimeTypeGuesserInterface instances.
51: *
52: * @var array
53: */
54: protected $guessers = array();
55:
56: /**
57: * Returns the singleton instance.
58: *
59: * @return MimeTypeGuesser
60: */
61: public static function getInstance()
62: {
63: if (null === self::$instance) {
64: self::$instance = new self();
65: }
66:
67: return self::$instance;
68: }
69:
70: /**
71: * Registers all natively provided mime type guessers.
72: */
73: private function __construct()
74: {
75: if (FileBinaryMimeTypeGuesser::isSupported()) {
76: $this->register(new FileBinaryMimeTypeGuesser());
77: }
78:
79: if (FileinfoMimeTypeGuesser::isSupported()) {
80: $this->register(new FileinfoMimeTypeGuesser());
81: }
82: }
83:
84: /**
85: * Registers a new mime type guesser.
86: *
87: * When guessing, this guesser is preferred over previously registered ones.
88: *
89: * @param MimeTypeGuesserInterface $guesser
90: */
91: public function register(MimeTypeGuesserInterface $guesser)
92: {
93: array_unshift($this->guessers, $guesser);
94: }
95:
96: /**
97: * Tries to guess the mime type of the given file.
98: *
99: * The file is passed to each registered mime type guesser in reverse order
100: * of their registration (last registered is queried first). Once a guesser
101: * returns a value that is not NULL, this method terminates and returns the
102: * value.
103: *
104: * @param string $path The path to the file
105: *
106: * @return string The mime type or NULL, if none could be guessed
107: *
108: * @throws \LogicException
109: * @throws FileNotFoundException
110: * @throws AccessDeniedException
111: */
112: public function guess($path)
113: {
114: if (!is_file($path)) {
115: throw new FileNotFoundException($path);
116: }
117:
118: if (!is_readable($path)) {
119: throw new AccessDeniedException($path);
120: }
121:
122: if (!$this->guessers) {
123: $msg = 'Unable to guess the mime type as no guessers are available';
124: if (!FileinfoMimeTypeGuesser::isSupported()) {
125: $msg .= ' (Did you enable the php_fileinfo extension?)';
126: }
127: throw new \LogicException($msg);
128: }
129:
130: foreach ($this->guessers as $guesser) {
131: if (null !== $mimeType = $guesser->guess($path)) {
132: return $mimeType;
133: }
134: }
135: }
136: }
137: