diff --git a/file_example/src/Form/FileExampleReadWriteForm.php b/file_example/src/Form/FileExampleReadWriteForm.php index d839982..7626cd2 100644 --- a/file_example/src/Form/FileExampleReadWriteForm.php +++ b/file_example/src/Form/FileExampleReadWriteForm.php @@ -12,6 +12,7 @@ use Drupal\file\FileInterface; use Drupal\Core\State\StateInterface; use Drupal\Core\Database\Database; use Drupal\Core\File\FileSystemInterface; +use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Url; @@ -47,8 +48,14 @@ class FileExampleReadWriteForm extends FormBase { protected $fileSystem; /** + * @var StreamWrapperInterface + * Service for fetching a stream wrapper for a file or directory. + */ + protected $streamWrapperManager; + + /** * @var ModuleHandlerInterface - * Handler for invoking hooks and other module operations. + * Service for invoking hooks and other module operations. */ protected $moduleHandler; @@ -57,12 +64,23 @@ class FileExampleReadWriteForm extends FormBase { * * @param StateInterface $state * Storage interface for state data. + * @param FileSystemInterface $file_system + * Interface for common file system operations. + * @param StreamWrapperManagerInterface $stream_wrapper_manager + * Interface to obtain stream wrappers used to manipulate a given file scheme. + * @param ModuleHandlerInterface $module_handler + * Interface to get information about the status of modules and other extensions. + * @param RequestStack $request_stack + * Access to the current request, including to session objects. */ - public function __construct(StateInterface $state, FileSystemInterface $file_system, ModuleHandlerInterface $module_handler, RequestStack $request_stack) { + public function __construct(StateInterface $state, FileSystemInterface $file_system, + StreamWrapperManagerInterface $stream_wrapper_manager, + ModuleHandlerInterface $module_handler, RequestStack $request_stack) { $this->state = $state; $this->fileSystem = $file_system; $this->moduleHandler = $module_handler; $this->requestStack = $request_stack; + $this->streamWrapperManager = $stream_wrapper_manager; } /** @@ -75,7 +93,8 @@ class FileExampleReadWriteForm extends FormBase { $file_system = $container->get('file_system'); $module_handler = $container->get('module_handler'); $request_stack = $container->get('request_stack'); - return new static($state, $file_system, $module_handler, $request_stack); + $stream_wrapper_manager = $container->get('stream_wrapper_manager'); + return new static($state, $file_system, $stream_wrapper_manager, $module_handler, $request_stack); } /** @@ -84,7 +103,7 @@ class FileExampleReadWriteForm extends FormBase { * @return string * The unique string identifying the form. */ - public function getFormID() { + public function getFormId() { return 'file_example_readwrite'; } @@ -175,26 +194,6 @@ class FileExampleReadWriteForm extends FormBase { } /** - * {@inheritdoc} - * - * This is an override of LinkGeneratorTrait::l to work around - * some problems related to handling non-routing URLs. - * - * @see https://www.drupal.org/node/2539622 - */ - protected function l($text, Url $url) { - try { - $new_url = Url::fromUri(file_create_url($url->getUri())); - $l = parent::l($text, $new_url); - return $l; - } - catch (\Exception $e) { - // We might want to log this. - } - return ''; - } - - /** * Prepare Url objects to prevent exceptions by the URL generator. * * Helper function to get us an external URL if this is legal, and to catch @@ -205,35 +204,39 @@ class FileExampleReadWriteForm extends FormBase { * exceptions if you deviate from what's expected. This function will raise * the chances your URL will be valid, and not do this. * - * @param \Drupal\file\Entity\File $file_object|string + * @param \Drupal\file\Entity\File|string $file_object * A file entity object. * * @return \Drupal\Core\Url * A Url object that can be displayed as an internal URL. - * - * @see http://drupal.stackexchange.com/questions/177869/how-to-create-a-url-to-an-unmanaged-public-file-in-drupal-8 */ - private static function getExternalUrl($file_object) { + protected function getExternalUrl($file_object) { if ($file_object instanceof FileInterface) { $uri = $file_object->getFileUri(); - $url = Url::fromUri($uri); } else { // A little tricky, since file.inc is a little inconsistent, but often this // is a Uri. - $url = file_create_url($file_object); + $uri = file_create_url($file_object); } try { - // If the Uri is unroutable (such as for a temporary file), or if Drupal cannot create - // a link, we will throw here: - if (is_string($url)) { - $url = Url::fromUri($url); + // If we have been given a PHP stream URI, ask the stream itself if it knows + // how to create an external URL. + $wrapper = $this->streamWrapperManager->getViaUri($uri); + if ($wrapper) { + $external_url = $wrapper->getExternalUrl(); + // Some streams may not have the concept of an external URL, so we check here. + if ($external_url) { + $url = Url::fromUri($external_url); + return $url; + } } - if (!empty($url) and $url->isExternal()) { + else { + $url = Url::fromUri($uri); + // If we did not throw on ::fromUri (you can), we return the URL. return $url; } - // $url->toString(); } catch (\Exception $e) { return FALSE; @@ -386,17 +389,17 @@ class FileExampleReadWriteForm extends FormBase { // Managed operations work with a file object. $file_object = \file_save_data($data, $uri, FILE_EXISTS_RENAME); if (!empty($file_object)) { - $url = self::getExternalUrl($file_object); + $url = $this->getExternalUrl($file_object); $this->setDefaultFile($file_object->getFileUri()); $file_data = $file_object->toArray(); if ($url) { drupal_set_message( - $this->t('Saved managed file: %file to destination %destination (accessible via !url, actual uri=@uri)', + $this->t('Saved managed file: %file to destination %destination (accessible via this URL, actual uri=@uri)', array( '%file' => print_r($file_data, TRUE), '%destination' => $uri, '@uri' => $file_object->getFileUri(), - '!url' => $this->l(t('this URL'), $url), + ':url' => $url->toString(), ) ) ); @@ -449,15 +452,15 @@ class FileExampleReadWriteForm extends FormBase { // With the unmanaged file we just get a filename back. $filename = file_unmanaged_save_data($data, $destination, FILE_EXISTS_REPLACE); if ($filename) { - $url = self::getExternalUrl($filename); + $url = $this->getExternalUrl($filename); $this->setDefaultFile($filename); if ($url) { drupal_set_message( - $this->t('Saved file as %filename (accessible via !url, uri=@uri)', + $this->t('Saved file as %filename (accessible via this URL, uri=@uri)', array( '%filename' => $filename, '@uri' => $filename, - '!url' => $this->l(t('this URL'), $url), + ':url' => $url->toString(), ) ) ); @@ -523,15 +526,15 @@ class FileExampleReadWriteForm extends FormBase { return; } } - $url = self::getExternalUrl($destination); + $url = $this->getExternalUrl($destination); $this->setDefaultFile($destination); if ($url) { drupal_set_message( - $this->t('Saved file as %filename (accessible via !url, uri=@uri)', + $this->t('Saved file as %filename (accessible via this URL, uri=@uri)', array( '%filename' => $destination, '@uri' => $destination, - '!url' => $this->l(t('this URL'), $url), + ':url' => $url->toString(), ) ) ); @@ -593,16 +596,14 @@ class FileExampleReadWriteForm extends FormBase { if ($buffer) { $sourcename = file_unmanaged_save_data($buffer, 'public://' . $filename); if ($sourcename) { - $url = self::getExternalUrl($sourcename); + $url = $this->getExternalUrl($sourcename); $this->setDefaultFile($sourcename); if ($url) { - // We need to convert the URL to string. Since the URL class throws on non-routables. - $url_string = file_create_url($url->getUri()); drupal_set_message( - $this->t('The file was read and copied to %filename which is accessible at !url', + $this->t('The file was read and copied to %filename which is accessible at this URL', array( '%filename' => $sourcename, - '!url' => $this->l($url_string, $url), + ':url' => $url->toString(), ) ) );