Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactoring asset handling in `Media`, implementing support for addin…

…g asset hosts through `Libraries`.
  • Loading branch information...
commit 974469cf25db5cbab61f3e1ff172405f4635032e 1 parent 5e0ad63
@nateabele nateabele authored
Showing with 83 additions and 24 deletions.
  1. +51 −24 net/http/Media.php
  2. +32 −0 tests/cases/net/http/MediaTest.php
View
75 net/http/Media.php
@@ -11,6 +11,7 @@
use lithium\util\Set;
use lithium\util\String;
use lithium\core\Libraries;
+use lithium\core\Environment;
use lithium\net\http\MediaException;
/**
@@ -441,42 +442,68 @@ public static function asset($path, $type, array $options = array()) {
}
$config = Libraries::get($library);
$paths = $options['path'];
-
$config['default'] ? end($paths) : reset($paths);
$options['library'] = basename($config['path']);
if ($options['suffix'] && strpos($path, $options['suffix']) === false) {
$path .= $options['suffix'];
}
+ return $self::filterAssetPath($path, $paths, $config, compact('type') + $options);
+ });
+ }
- if ($options['check'] || $options['timestamp']) {
- $file = $self::path($path, $type, $options);
- }
+ /**
+ * Performs checks and applies transformations to asset paths, including verifying that the
+ * virtual path exists on the filesystem, appending a timestamp, prepending an asset host, or
+ * applying a user-defined filter.
+ *
+ * @see lithium\net\http\Media::asset()
+ * @param string $asset A full asset path, relative to the public web path of the application.
+ * @param mixed $path Path information for the asset type.
+ * @param array $config The configuration array of the library from which the asset is being
+ * loaded.
+ * @param array $options The array of options passed to `asset()` (see the `$options` parameter
+ * of `Media::asset()`).
+ * @return mixed Returns a modified path to a web asset, or `false`, if the path fails a check.
+ */
+ public static function filterAssetPath($asset, $path, array $config, array $options = array()) {
+ $config += array('assets' => null);
- if (strlen($path) > 0 && $path[0] === '/') {
- if ($options['base'] && strpos($path, $options['base']) !== 0) {
- $path = "{$options['base']}{$path}";
- }
- } else {
- $path = String::insert(key($paths), compact('path') + $options);
- }
+ if ($options['check'] || $options['timestamp']) {
+ $file = static::path($asset, $options['type'], $options);
+ }
+ if ($options['check'] && !is_file($file)) {
+ return false;
+ }
+ $isAbsolute = ($asset && $asset[0] === '/');
- if ($options['check'] && !is_file($file)) {
- return false;
- }
+ if ($isAbsolute && $options['base'] && strpos($asset, $options['base']) !== 0) {
+ $asset = "{$options['base']}{$asset}";
+ } elseif (!$isAbsolute) {
+ $asset = String::insert(key($path), array('path' => $asset) + $options);
+ }
- if (is_array($options['filter']) && !empty($options['filter'])) {
- $keys = array_keys($options['filter']);
- $values = array_values($options['filter']);
- $path = str_replace($keys, $values, $path);
- }
+ if (is_array($options['filter']) && !empty($options['filter'])) {
+ $filter = $options['filter'];
+ $asset = str_replace(array_keys($filter), array_values($filter), $asset);
+ }
+
+ if ($options['timestamp'] && is_file($file)) {
+ $separator = (strpos($asset, '?') !== false) ? '&' : '?';
+ $asset .= $separator . filemtime($file);
+ }
+
+ if ($host = $config['assets']) {
+ $type = $options['type'];
+ $env = Environment::get();
+ $base = isset($host[$env][$type]) ? $host[$env][$type] : null;
+ $base = (isset($host[$type]) && !$base) ? $host[$type] : $base;
- if ($options['timestamp'] && is_file($file)) {
- $separator = (strpos($path, '?') !== false) ? '&' : '?';
- $path .= $separator . filemtime($file);
+ if ($base) {
+ return "{$base}{$asset}";
}
- return $path;
- });
+ }
+ return $asset;
}
/**
View
32 tests/cases/net/http/MediaTest.php
@@ -8,6 +8,7 @@
namespace lithium\tests\cases\net\http;
+use lithium\core\Environment;
use lithium\net\http\Media;
use lithium\action\Request;
use lithium\action\Response;
@@ -147,6 +148,37 @@ public function testAssetAbsoluteRelativePaths() {
$this->assertEqual($expected, $result);
}
+ public function testCustomAssetUrls() {
+ $env = Environment::get();
+
+ Libraries::add('cdn_js_test', array(
+ 'path' => Libraries::get(true, 'path'),
+ 'assets' => array(
+ 'js' => 'http://static.cdn.com'
+ )
+ ));
+
+ Libraries::add('cdn_env_test', array(
+ 'path' => Libraries::get(true, 'path'),
+ 'assets' => array(
+ 'js' => 'wrong',
+ $env => array('js' => 'http://static.cdn.com/myapp')
+ )
+ ));
+
+ $result = Media::asset('foo', 'js', array('library' => 'cdn_js_test'));
+ $this->assertEqual("http://static.cdn.com/lithium/js/foo.js", $result);

Is this (and the next 2 asserts) not hardcoded with the path that the library would be in, if it is tested stand-alone?

All tests pass if I run them from the cli on just the library. If I run the tests through the web interface, in an app context, testCustomAssetUrls() fails on all three asserts.

e.g.

expected: 'http://static.cdn.com/lithium/js/foo.js'
result: 'http://static.cdn.com/app/js/foo.js'

@nateabele Owner

@davidmturner Ah, good call. Yes, the test assumes it's being run from the docroot, so we'll have to control for that in the test. Can you do me a favor and open an issue so we don't lose track of it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ $result = Media::asset('foo', 'css', array('library' => 'cdn_js_test'));
+ $this->assertEqual("/lithium/css/foo.css", $result);
+
+ $result = Media::asset('foo', 'js', array('library' => 'cdn_env_test'));
+ $this->assertEqual("http://static.cdn.com/myapp/lithium/js/foo.js", $result);
+
+ Libraries::remove('cdn_env_test');
+ Libraries::remove('cdn_js_test');
+ }
+
public function testAssetPathGeneration() {
$resources = Libraries::get(true, 'resources');
$this->skipIf(!is_writable($resources), "Cannot write test app to resources directory.");
Please sign in to comment.
Something went wrong with that request. Please try again.