diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/simpletest/tests/file.test | 62 | ||||
-rw-r--r-- | modules/simpletest/tests/file_test.module | 50 | ||||
-rw-r--r-- | modules/system/system.api.php | 61 |
3 files changed, 173 insertions, 0 deletions
diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test index 2830e7b7b..837d1da36 100644 --- a/modules/simpletest/tests/file.test +++ b/modules/simpletest/tests/file.test @@ -1879,6 +1879,26 @@ class FileDownloadTest extends FileTestCase { } /** + * Test the public file transfer system. + */ + function testPublicFileTransfer() { + // Test generating an URL to a created file. + $file = $this->createFile(); + $url = file_create_url($file->uri); + $this->assertEqual($GLOBALS['base_url'] . '/' . file_directory_path() . '/' . $file->filename, $url, t('Correctly generated a URL for a created file.')); + $this->drupalHead($url); + $this->assertResponse(200, t('Confirmed that the generated URL is correct by downloading the created file.')); + + // Test generating an URL to a shipped file (i.e. a file that is part of + // Drupal core, a module or a theme, for example a JavaScript file). + $filepath = 'misc/jquery.js'; + $url = file_create_url($filepath); + $this->assertEqual($GLOBALS['base_url'] . '/' . $filepath, $url, t('Correctly generated a URL for a shipped file.')); + $this->drupalHead($url); + $this->assertResponse(200, t('Confirmed that the generated URL is correct by downloading the shipped file.')); + } + + /** * Test the private file transfer system. */ function testPrivateFileTransfer() { @@ -1908,6 +1928,48 @@ class FileDownloadTest extends FileTestCase { } /** + * Tests for file URL rewriting. + */ +class FileURLRewritingTest extends FileTestCase { + public static function getInfo() { + return array( + 'name' => t('File URL rewriting'), + 'description' => t('Tests for file URL rewriting.'), + 'group' => t('File'), + ); + } + + function setUp() { + parent::setUp('file_test'); + variable_set('file_test_hook_file_url_alter', TRUE); + } + + /** + * Test the generating of rewritten shipped file URLs. + */ + function testShippedFileURL() { + // Test generating an URL to a shipped file (i.e. a file that is part of + // Drupal core, a module or a theme, for example a JavaScript file). + $filepath = 'misc/jquery.js'; + $url = file_create_url($filepath); + $this->assertEqual(FILE_URL_TEST_CDN_1 . '/' . $filepath, $url, t('Correctly generated a URL for a shipped file.')); + $filepath = 'misc/favicon.ico'; + $url = file_create_url($filepath); + $this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . $filepath, $url, t('Correctly generated a URL for a shipped file.')); + } + + /** + * Test the generating of rewritten public created file URLs. + */ + function testPublicCreatedFileURL() { + // Test generating an URL to a created file. + $file = $this->createFile(); + $url = file_create_url($file->uri); + $this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . file_directory_path() . '/' . $file->filename, $url, t('Correctly generated a URL for a created file.')); + } +} + +/** * Tests for file_munge_filename() and file_unmunge_filename(). */ class FileNameMungingTest extends FileTestCase { diff --git a/modules/simpletest/tests/file_test.module b/modules/simpletest/tests/file_test.module index 635576506..8f087af77 100644 --- a/modules/simpletest/tests/file_test.module +++ b/modules/simpletest/tests/file_test.module @@ -9,6 +9,11 @@ * calling file_test_get_calls() or file_test_set_return(). */ + +define('FILE_URL_TEST_CDN_1', 'http://cdn1.example.com'); +define('FILE_URL_TEST_CDN_2', 'http://cdn2.example.com'); + + /** * Implement hook_menu(). */ @@ -265,6 +270,51 @@ function file_test_file_delete($file) { } /** + * Implement hook_file_url_alter(). + */ +function file_test_file_url_alter(&$uri) { + // Only run this hook when this variable is set. Otherwise, we'd have to add + // another hidden test module just for this hook. + if (!variable_get('file_test_hook_file_url_alter', FALSE)) { + return; + } + + $cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png'); + + // Most CDNs don't support private file transfers without a lot of hassle, + // so don't support this in the common case. + $schemes = array('public'); + + $scheme = file_uri_scheme($uri); + + // Only serve shipped files and public created files from the CDN. + if (!$scheme || in_array($scheme, $schemes)) { + // Shipped files. + if (!$scheme) { + $path = $uri; + } + // Public created files. + else { + $wrapper = file_stream_wrapper_get_instance_by_scheme($scheme); + $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri); + } + + // Clean up Windows paths. + $path = str_replace('\\', '/', $path); + + // Serve files with one of the CDN extensions from CDN 1, all others from + // CDN 2. + $pathinfo = pathinfo($path); + if (array_key_exists('extension', $pathinfo) && in_array($pathinfo['extension'], $cdn_extensions)) { + $uri = FILE_URL_TEST_CDN_1 . '/' . $path; + } + else { + $uri = FILE_URL_TEST_CDN_2 . '/' . $path; + } + } +} + +/** * Helper class for testing the stream wrapper registry. * * Dummy stream wrapper implementation (dummy://). diff --git a/modules/system/system.api.php b/modules/system/system.api.php index ea8bcc115..5f50c30d2 100644 --- a/modules/system/system.api.php +++ b/modules/system/system.api.php @@ -1449,6 +1449,67 @@ function hook_file_download($filepath) { } /** + * Alter the URL to a file. + * + * This hook is called from file_create_url(), and is called fairly + * frequently (10+ times per page), depending on how many files there are in a + * given page. + * If CSS and JS aggregation are disabled, this can become very frequently + * (50+ times per page) so performance is critical. + * + * This function should alter the URI, if it wants to rewrite the file URL. + * If it does so, no other hook_file_url_alter() implementation will be + * allowed to further alter the path. + * + * @param $uri + * The URI to a file for which we need an external URL, or the path to a + * shipped file. + */ +function hook_file_url_alter(&$uri) { + global $user; + + // User 1 will always see the local file in this example. + if ($user->uid == 1) { + return; + } + + $cdn1 = 'http://cdn1.example.com'; + $cdn2 = 'http://cdn2.example.com'; + $cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png'); + + // Most CDNs don't support private file transfers without a lot of hassle, + // so don't support this in the common case. + $schemes = array('public'); + + $scheme = file_uri_scheme($uri); + + // Only serve shipped files and public created files from the CDN. + if (!$scheme || in_array($scheme, $schemes)) { + // Shipped files. + if (!$scheme) { + $path = $uri; + } + // Public created files. + else { + $wrapper = file_stream_wrapper_get_instance_by_scheme($scheme); + $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri); + } + + // Clean up Windows paths. + $path = str_replace('\\', '/', $path); + + // Serve files with one of the CDN extensions from CDN 1, all others from + // CDN 2. + $pathinfo = pathinfo($path); + if (array_key_exists('extension', $pathinfo) && in_array($pathinfo['extension'], $cdn_extensions)) { + $uri = $cdn1 . '/' . $path; + } + else { + $uri = $cdn2 . '/' . $path; + } + } +} + /** * Check installation requirements and do status reporting. * * This hook has two closely related uses, determined by the $phase argument: |