MimeTypeGuesser.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php
  2. namespace Drupal\Core\File\MimeType;
  3. use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
  4. use Symfony\Component\DependencyInjection\ContainerInterface;
  5. use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser as SymfonyMimeTypeGuesser;
  6. use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
  7. /**
  8. * Defines a MIME type guesser that also supports stream wrapper paths.
  9. */
  10. class MimeTypeGuesser implements MimeTypeGuesserInterface {
  11. /**
  12. * An array of arrays of registered guessers keyed by priority.
  13. *
  14. * @var array
  15. */
  16. protected $guessers = [];
  17. /**
  18. * Holds the array of guessers sorted by priority.
  19. *
  20. * If this is NULL a rebuild will be triggered.
  21. *
  22. * @var \Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface[]
  23. *
  24. * @see \Drupal\Core\File\MimeType\MimeTypeGuesser::addGuesser()
  25. * @see \Drupal\Core\File\MimeType\MimeTypeGuesser::sortGuessers()
  26. */
  27. protected $sortedGuessers = NULL;
  28. /**
  29. * The stream wrapper manager.
  30. *
  31. * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
  32. */
  33. protected $streamWrapperManager;
  34. /**
  35. * Constructs a MimeTypeGuesser object.
  36. *
  37. * @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager
  38. * The stream wrapper manager.
  39. */
  40. public function __construct(StreamWrapperManagerInterface $stream_wrapper_manager) {
  41. $this->streamWrapperManager = $stream_wrapper_manager;
  42. }
  43. /**
  44. * {@inheritdoc}
  45. */
  46. public function guess($path) {
  47. if ($wrapper = $this->streamWrapperManager->getViaUri($path)) {
  48. // Get the real path from the stream wrapper, if available. Files stored
  49. // in remote file systems will not have one.
  50. $real_path = $wrapper->realpath();
  51. if ($real_path !== FALSE) {
  52. $path = $real_path;
  53. }
  54. }
  55. if ($this->sortedGuessers === NULL) {
  56. // Sort is not triggered yet.
  57. $this->sortedGuessers = $this->sortGuessers();
  58. }
  59. foreach ($this->sortedGuessers as $guesser) {
  60. $mime_type = $guesser->guess($path);
  61. if ($mime_type !== NULL) {
  62. return $mime_type;
  63. }
  64. }
  65. }
  66. /**
  67. * Appends a MIME type guesser to the guessers chain.
  68. *
  69. * @param \Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface $guesser
  70. * The guesser to be appended.
  71. * @param int $priority
  72. * The priority of the guesser being added.
  73. *
  74. * @return $this
  75. */
  76. public function addGuesser(MimeTypeGuesserInterface $guesser, $priority = 0) {
  77. $this->guessers[$priority][] = $guesser;
  78. // Mark sorted guessers for rebuild.
  79. $this->sortedGuessers = NULL;
  80. return $this;
  81. }
  82. /**
  83. * Sorts guessers according to priority.
  84. *
  85. * @return \Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface[]
  86. * A sorted array of MIME type guesser objects.
  87. */
  88. protected function sortGuessers() {
  89. $sorted = [];
  90. krsort($this->guessers);
  91. foreach ($this->guessers as $guesser) {
  92. $sorted = array_merge($sorted, $guesser);
  93. }
  94. return $sorted;
  95. }
  96. /**
  97. * A helper function to register with Symfony's singleton MIME type guesser.
  98. *
  99. * Symfony's default mimetype guessers have dependencies on PHP's fileinfo
  100. * extension or being able to run the system command file. Drupal's guesser
  101. * does not have these dependencies.
  102. *
  103. * @see \Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser
  104. */
  105. public static function registerWithSymfonyGuesser(ContainerInterface $container) {
  106. // Reset state, so we do not store more and more services during test runs.
  107. SymfonyMimeTypeGuesser::reset();
  108. $singleton = SymfonyMimeTypeGuesser::getInstance();
  109. $singleton->register($container->get('file.mime_type.guesser'));
  110. }
  111. }