From c1316d6957820bbf5e2ef9a5684cfba09fb4e131 Mon Sep 17 00:00:00 2001 From: effulgentsia <alex.bronstein@acquia.com> Date: Fri, 2 Oct 2015 11:49:01 -0700 Subject: [PATCH] Issue #2522008 by pwolanin, nlisgo, Wim Leers, jplopezy: Provide a setting to override base url when creating links to public files --- .../Core/StreamWrapper/PrivateStream.php | 4 +++ .../Core/StreamWrapper/PublicStream.php | 28 ++++++++++++++++++- core/modules/file/src/Tests/DownloadTest.php | 13 ++++++++- .../system/src/Form/FileSystemForm.php | 7 +++++ sites/default/default.settings.php | 13 +++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/core/lib/Drupal/Core/StreamWrapper/PrivateStream.php b/core/lib/Drupal/Core/StreamWrapper/PrivateStream.php index 1332a97fd6a7..3eb23496a35f 100644 --- a/core/lib/Drupal/Core/StreamWrapper/PrivateStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/PrivateStream.php @@ -59,6 +59,10 @@ public function getExternalUrl() { /** * Returns the base path for private://. * + * Note that this static method is used by \Drupal\system\Form\FileSystemForm + * so you should alter that form or substitute a different form if you change + * the class providing the stream_wrapper.private service. + * * @return string * The base path for private://. */ diff --git a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php index acfa7f45a215..e88eb53ef7d9 100644 --- a/core/lib/Drupal/Core/StreamWrapper/PublicStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/PublicStream.php @@ -53,7 +53,29 @@ public function getDirectoryPath() { */ public function getExternalUrl() { $path = str_replace('\\', '/', $this->getTarget()); - return $GLOBALS['base_url'] . '/' . self::getDirectoryPath() . '/' . UrlHelper::encodePath($path); + return static::baseUrl() . '/' . UrlHelper::encodePath($path); + } + + /** + * Finds and returns the base URL for public://. + * + * Defaults to the current site's base URL plus directory path. + * + * Note that this static method is used by \Drupal\system\Form\FileSystemForm + * so you should alter that form or substitute a different form if you change + * the class providing the stream_wrapper.public service. + * + * @return string + * The external base URL for public:// + */ + public static function baseUrl() { + $settings_base_url = Settings::get('file_public_base_url', ''); + if ($settings_base_url) { + return (string) $settings_base_url; + } + else { + return $GLOBALS['base_url'] . '/' . static::basePath(); + } } /** @@ -63,6 +85,10 @@ public function getExternalUrl() { * Otherwise we build a reasonable default based on the site.path service if * it's available, or a default behavior based on the request. * + * Note that this static method is used by \Drupal\system\Form\FileSystemForm + * so you should alter that form or substitute a different form if you change + * the class providing the stream_wrapper.public service. + * * The site path is injectable from the site.path service: * @code * $base_path = PublicStream::basePath(\Drupal::service('site.path')); diff --git a/core/modules/file/src/Tests/DownloadTest.php b/core/modules/file/src/Tests/DownloadTest.php index d2df0d26657d..ea2b7456e6b6 100644 --- a/core/modules/file/src/Tests/DownloadTest.php +++ b/core/modules/file/src/Tests/DownloadTest.php @@ -113,14 +113,25 @@ function testFileCreateUrl() { 'clean' => '', 'unclean' => 'index.php/', ); + $public_directory_path = \Drupal::service('stream_wrapper_manager')->getViaScheme('public')->getDirectoryPath(); foreach ($clean_url_settings as $clean_url_setting => $script_path) { $clean_urls = $clean_url_setting == 'clean'; $request = $this->prepareRequestForGenerator($clean_urls); $base_path = $request->getSchemeAndHttpHost() . $request->getBasePath(); - $this->checkUrl('public', '', $basename, $base_path . '/' . \Drupal::service('stream_wrapper_manager')->getViaScheme('public')->getDirectoryPath() . '/' . $basename_encoded); + $this->checkUrl('public', '', $basename, $base_path . '/' . $public_directory_path . '/' . $basename_encoded); $this->checkUrl('private', '', $basename, $base_path . '/' . $script_path . 'system/files/' . $basename_encoded); } $this->assertEqual(file_create_url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Generated URL matches expected URL.')); + // Test public files with a different host name from settings. + $test_base_url = 'http://www.example.com/cdn'; + $this->settingsSet('file_public_base_url', $test_base_url); + $filepath = file_create_filename('test.txt', ''); + $directory_uri = 'public://' . dirname($filepath); + file_prepare_directory($directory_uri, FILE_CREATE_DIRECTORY); + $file = $this->createFile($filepath, NULL, 'public'); + $url = file_create_url($file->getFileUri()); + $expected_url = $test_base_url . '/' . basename($filepath); + $this->assertEqual($url, $expected_url); } /** diff --git a/core/modules/system/src/Form/FileSystemForm.php b/core/modules/system/src/Form/FileSystemForm.php index 002d7f770418..bb507dbb56bc 100644 --- a/core/modules/system/src/Form/FileSystemForm.php +++ b/core/modules/system/src/Form/FileSystemForm.php @@ -89,6 +89,13 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#description' => t('A local file system path where public files will be stored. This directory must exist and be writable by Drupal. This directory must be relative to the Drupal installation directory and be accessible over the web. This must be changed in settings.php'), ); + $form['file_public_base_url'] = array( + '#type' => 'item', + '#title' => t('Public file base URL'), + '#markup' => PublicStream::baseUrl(), + '#description' => t('The base URL that will be used for public file URLs. This can be changed in settings.php'), + ); + $form['file_private_path'] = array( '#type' => 'item', '#title' => t('Private file system path'), diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index ad557f5a6037..1ea5d727efa7 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -453,6 +453,19 @@ # $settings['file_chmod_directory'] = 0775; # $settings['file_chmod_file'] = 0664; +/** + * Public file base URL: + * + * An alternative base URL to be used for serving public files. This must + * include any leading directory path. + * + * A different value from the domain used by Drupal to be used for accessing + * public files. This can be used for a simple CDN integration, or to improve + * security by serving user-uploaded files from a different domain or subdomain + * pointing to the same server. Do not include a trailing slash. + */ +# $settings['file_public_base_url'] = 'http://downloads.example.com/files'; + /** * Public file path: * -- GitLab