summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/simpletest/tests/file.test62
-rw-r--r--modules/simpletest/tests/file_test.module50
-rw-r--r--modules/system/system.api.php61
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: