diff --git a/README.md b/README.md
index b22c833..9551744 100644
--- a/README.md
+++ b/README.md
@@ -11,11 +11,11 @@ An ultra-simple-to-use assets management PHP library.
- [Usage](#usage).
- [Views](#views).
- [Controllers](#controllers).
- - [API](#api).
- [Configuration](#configuration).
- [Collections](#collections).
- [Pipeline](#pipeline).
- [More options](#options).
+ - [Multitenancy](#multitenancy).
- [Non static interface usage](#nonstatic).
- [Sample collections](#samples).
- [Troubleshooting / F.A.Q.](#troubleshooting).
@@ -28,21 +28,21 @@ An ultra-simple-to-use assets management PHP library.
- **Very easy to use**.
- Autogenerates HTML tags for including your JavaScript and CSS files.
+- Automatically detects type of asset (CSS, JavaScript or collection).
- Supports programmatically adding assets on the fly.
- Supports local (**including packages**) or remote assets.
- Prevents from loading duplicated assets.
- Included assets **pipeline** (*concatenate and minify all your assets to a single file*) with URL **timestamps** and **gzip** support.
- Automatically prefixes local assets with a configurable folder name or url.
- Supports secure (*https*) and protocol agnostic (*//*) links.
-- Supports **collections** (*named groups of assets*) that can be nested, allowing assets dependencies definitions.
-- Automatically detects type of asset (CSS, JavaScript or collection).
+- Supports **collections** (*named sets of assets*) that can be nested, allowing assets dependencies definitions.
+- Supports **multitenancy** (multiple independent configurations) for different groups of assets (*this feature is only available for Laravel >= 5.0*).
- Allows autoloading by default preconfigured assets and collections.
-
## Supported frameworks
-The library is framework agnostic and it should work well with any framework or naked PHP application. Nevertheless, the following instructions have been tailored for **Laravel 5** framework ([still on Laravel 4?](https://github.com/Stolz/Assets/issues/55#issuecomment-73024822)). If you want to use the library in any other scenario please read the [non static interface](#nonstatic) instructions.
+The library is framework agnostic and it should work well with any framework or naked PHP application. Nevertheless, sice the library is most popular between Laravel users the following instructions have been tailored for **Laravel 5** framework ([still on Laravel 4?](https://github.com/Stolz/Assets/issues/55#issuecomment-73024822)). If you want to use the library in any other scenario please read the [non static interface](#nonstatic) instructions.
## Installation
@@ -79,7 +79,8 @@ Basically all you have to do to add and asset, no matter if it's CSS or JS or a
Assets::add('filename');
-*For more advanced uses keep reading ...*
+>For more advanced uses keep reading but please note that there are some more methods not documented here. For a **full list of all the available methods** please read the provided [`API.md`](https://github.com/Stolz/Assets/blob/master/API.md) file.
+
Add more than one asset at once
@@ -98,8 +99,8 @@ You may add remote assets in the same fashion
If your assets have no extension and autodetection fails, then just use canonical functions *(they accept an array of assets too)*
- Assets::addCss('asset.css');
- Assets::addJs('asset.js');
+ Assets::addCss('CSSfile.foo');
+ Assets::addJs('JavaScriptFile.bar');
If at some point you decide you added the wrong assets you can reset them and start over
@@ -111,11 +112,6 @@ All methods that don't generate output will accept chaining:
Assets::reset()->add('collection')->addJs('file.js')->css();
-
-### API
-
-There are some methods not documented here. For a **full list of all the available methods** please read the provided [`API.md`](https://github.com/Stolz/Assets/blob/master/API.md) file.
-
## Configuration
@@ -130,7 +126,7 @@ If you are using the [non static interface](#nonstatic) just pass an associative
### Collections
-A collection is a named group of assets, that is, a set of JavaScript and CSS files. Any collection may include more collections, allowing dependencies definition and collection nesting. Collections can be created on run time or via config file.
+A collection is a named set of assets, that is, a set of JavaScript and CSS files. Any collection may include more collections, allowing dependencies definition and collection nesting. Collections can be created on run time or via config file.
To register a collection on run time for later use:
@@ -138,7 +134,7 @@ To register a collection on run time for later use:
To preconfigure collections using the config file:
- // ... config.php ...
+ // ... File: config/assets.php ...
'collections' => [
'one' => 'one.css',
'two' => ['two.css', 'two.js'],
@@ -240,6 +236,46 @@ It is possible to **change any config options on the fly** by passing an array o
echo Assets::reset()->add('do-not-pipeline-this.js')->js(),
Assets::reset()->add('please-pipeline-this.js')->config(array('pipeline' => true))->js();
+
+### Multitenancy
+
+**Note:** *This feature is only available for Laravel >= 5.0*.
+
+Multitenancy is achieved using groups. A group is an isolated container of the library. Each group is totally independent of other groups so it uses its own settings and assets flow. This is useful if you need different approaches for different types of assets (for instance, you may need some assets to be pipelined but some others no). Therefore, when using multiple groups is your responsability to make sure the assets of different groups that depend on eachother are loaded in ther right order.
+
+By default if no groups are defined the default group is used. To define a group just nest your normal settings within an array in the config file. The array key will be the group name. For instance:
+
+
+ // ... File: config/assets.php ...
+
+ // Default group
+ 'default' => [
+ 'pipeline' => true,
+ 'js_dir' => 'js',
+ // ... more options for default group
+ ],
+
+ // Other group
+ 'group1' => [
+ 'pipeline' => false,
+ 'public_dir' => '/foo',
+ // ... more options for group1
+ ],
+
+ // Another group
+ 'group2' => [
+ 'pipeline' => false,
+ 'css_dir' => 'css/admin',
+ // ... more options for group2
+ ],
+
+For choosing which group you want to interact with, use the `group()` method. If no group is specified the 'default' group will be used.
+
+ Assets::add('foo.js')->js(); // Uses default group
+ Assets::group('group1')->add('bar.css')->css(); // Uses the 'group1' group.
+
+Please note the `group()` method is part of the Facade, so it does not accept chaining and it always has to be used at the beginning of each interaction with the library.
+
----
@@ -357,7 +393,7 @@ If you use a massive amount of assets make sure your connection is fast enough a
### Can I use multiple instances of the library?
-Yes you can but there is no need. Read next question. If you still want to use multiple instances, [read how](https://github.com/Stolz/Assets/issues/37#issuecomment-57676554).
+Yes you can but there is no need. You better use the [multitenancy feature](#multitenancy) (*only available for Laravel >= 5.0*).
### Can I change settings on the fly?
@@ -367,6 +403,8 @@ Yes you can. There is a `config()` public method to change settings on the fly.
echo Assets::add('jquery-cdn')->js();
echo Assets::reset()->add(array('custom.js', 'main.js'))->config(array('pipeline' => true))->js();
+If you want the different settings to be permanent, then use the [multitenancy feature](#multitenancy).
+
### Can I filter/preprocess my assets?
diff --git a/composer.json b/composer.json
index 7bb1f6a..e91f867 100644
--- a/composer.json
+++ b/composer.json
@@ -32,6 +32,5 @@
"optimize-autoloader": true,
"preferred-install": "dist"
},
- "minimum-stability": "dev",
"license": "MIT"
}
diff --git a/src/Laravel/Facade.php b/src/Laravel/Facade.php
index 4c56c13..e371682 100644
--- a/src/Laravel/Facade.php
+++ b/src/Laravel/Facade.php
@@ -11,6 +11,25 @@ class Facade extends LaravelFacade
*/
protected static function getFacadeAccessor()
{
- return 'stolz.assets';
+ return 'stolz.assets.group.default';
+ }
+
+ /**
+ * Get the instance of the assets manager for a given group.
+ *
+ * @param string $group
+ *
+ * @return \Stolz\Assets\Manager
+ *
+ * @throws \RuntimeException
+ */
+ public static function group($group = 'default')
+ {
+ $binding = "stolz.assets.group.$group";
+
+ if( ! static::$app->bound($binding))
+ throw new \RuntimeException("Stolz\Assets: Assets group '$group' not found in the config file");
+
+ return static::$app[$binding];
}
}
diff --git a/src/Laravel/ServiceProvider.php b/src/Laravel/ServiceProvider.php
index 7c49a46..aab8ab5 100644
--- a/src/Laravel/ServiceProvider.php
+++ b/src/Laravel/ServiceProvider.php
@@ -7,47 +7,67 @@
class ServiceProvider extends LaravelServiceProvider
{
/**
- * Register bindings in the container.
+ * Perform post-registration booting of services.
*
* @return void
*/
- public function register()
+ public function boot()
{
- // Merge user's configuration
- $this->mergeConfigFrom(__DIR__ . '/config.php', 'assets');
-
- // Bind 'stolz.assets' shared component to the IoC container
- $this->app->singleton('stolz.assets', function ($app) {
+ // Register paths to be published by 'vendor:publish' Artisan command
+ $this->publishes([
+ __DIR__ . '/config.php' => config_path('assets.php'),
+ ]);
- $config = $app['config']['assets'];
- if( ! isset($config['public_dir']))
- $config['public_dir'] = public_path();
+ // Add 'Assets' facade alias
+ AliasLoader::getInstance()->alias('Assets', 'Stolz\Assets\Laravel\Facade');
- return new Assets($config);
- });
+ // Register the Artisan command
+ $this->commands('stolz.assets.command.flush');
+ }
- // Bind 'stolz.assets.command.flush' component to the IoC container
+ /**
+ * Register bindings in the container.
+ *
+ * @return void
+ */
+ public function register()
+ {
+ // Register the Artisan command binding
$this->app->bind('stolz.assets.command.flush', function ($app) {
return new FlushPipelineCommand();
});
+
+ // Merge user's configuration with the default package config file
+ //$this->mergeConfigFrom(__DIR__ . '/config.php', 'assets');
+ $config = $this->app['config']->get('assets', []);
+
+ // Register the library instances bindings ...
+
+ // No groups defined. Assume the config is for the default group.
+ if( ! isset($config['default']))
+ return $this->registerAssetsManagerInstance('default', $config);
+
+ // Multiple groups
+ foreach($config as $groupName => $groupConfig)
+ $this->registerAssetsManagerInstance($groupName, (array) $groupConfig);
}
/**
- * Perform post-registration booting of services.
+ * Register an instance of the assets manager library in the IoC container.
+ *
+ * @param string $name Name of the group
+ * @param array $config Config of the group
*
* @return void
*/
- public function boot()
+ protected function registerAssetsManagerInstance($name, array $config)
{
- // Register paths to be published by 'vendor:publish' artisan command
- $this->publishes([
- __DIR__ . '/config.php' => config_path('assets.php'),
- ]);
+ $this->app->singleton("stolz.assets.group.$name", function ($app) use ($config) {
- // Add 'Assets' facade alias
- AliasLoader::getInstance()->alias('Assets', 'Stolz\Assets\Laravel\Facade');
+ if( ! isset($config['public_dir']))
+ $config['public_dir'] = public_path();
- // Add artisan command
- $this->commands('stolz.assets.command.flush');
+ return new Assets($config);
+ });
}
}
diff --git a/src/Laravel/config.php b/src/Laravel/config.php
index 9829087..cee4447 100644
--- a/src/Laravel/config.php
+++ b/src/Laravel/config.php
@@ -11,156 +11,161 @@
return array(
- /**
- * Regex to match against a filename/url to determine if it is an asset.
- *
- * @var string
- */
- //'asset_regex' => '/.\.(css|js)$/i',
-
- /**
- * Regex to match against a filename/url to determine if it is a CSS asset.
- *
- * @var string
- */
- //'css_regex' => '/.\.css$/i',
-
- /**
- * Regex to match against a filename/url to determine if it is a JavaScript asset.
- *
- * @var string
- */
- //'js_regex' => '/.\.js$/i',
-
- /**
- * Regex to match against a filename/url to determine if it should not be minified by pipeline.
- *
- * @var string
- */
- //'no_minification_regex' => '/.[-.]min\.(css|js)$/i',
-
- /**
- * Absolute path to the public directory of your App (WEBROOT).
- * Required if you enable the pipeline.
- * No trailing slash!.
- *
- * @var string
- */
- //'public_dir' => (function_exists('public_path')) ? public_path() : '/var/www/localhost/htdocs',
-
- /**
- * Directory for local CSS assets.
- * Relative to your public directory ('public_dir').
- * No trailing slash!.
- *
- * @var string
- */
- //'css_dir' => 'css',
-
- /**
- * Directory for local JavaScript assets.
- * Relative to your public directory ('public_dir').
- * No trailing slash!.
- *
- * @var string
- */
- //'js_dir' => 'js',
-
- /**
- * Directory for local package assets.
- * Relative to your public directory ('public_dir').
- * No trailing slash!.
- *
- * @var string
- */
- //'packages_dir' => 'packages',
-
- /**
- * Enable assets pipeline (concatenation and minification).
- * Use a string that evaluates to `true` to provide the salt of the pipeline hash.
- * Use 'auto' to automatically calculated the salt from your assets last modification time.
- *
- * @var bool|string
- */
- //'pipeline' => false,
-
- /**
- * Directory for storing pipelined assets.
- * Relative to your assets directories ('css_dir' and 'js_dir').
- * No trailing slash!.
- *
- * @var string
- */
- //'pipeline_dir' => 'min',
-
- /**
- * Enable pipelined assets compression with Gzip.
- * Use only if your webserver supports Gzip HTTP_ACCEPT_ENCODING.
- * Set to true to use the default compression level.
- * Set an integer between 0 (no compression) and 9 (maximum compression) to choose compression level.
- *
- * @var bool|integer
- */
- //'pipeline_gzip' => false,
-
- /**
- * Closure used by the pipeline to fetch assets.
- *
- * Useful when file_get_contents() function is not available in your PHP
- * instalation or when you want to apply any kind of preprocessing to
- * your assets before they get pipelined.
- *
- * The closure will receive as the only parameter a string with the path/URL of the asset and
- * it should return the content of the asset file as a string.
- *
- * @var Closure
- */
- //'fetch_command' => function ($asset) {return preprocess(file_get_contents($asset));},
-
- /**
- * Available collections.
- * Each collection is an array of assets.
- * Collections may also contain other collections.
- *
- * @var array
- */
- /*'collections' => array(
-
- // jQuery (CDN)
- 'jquery-cdn' => array('//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'),
-
- // jQuery UI (CDN)
- 'jquery-ui-cdn' => array(
- 'jquery-cdn',
- '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js',
- ),
-
- // Twitter Bootstrap (CDN)
- 'bootstrap-cdn' => array(
- 'jquery-cdn',
- '//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css',
- '//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css',
- '//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js'
- ),
-
- // Zurb Foundation (CDN)
- 'foundation-cdn' => array(
- 'jquery-cdn',
- '//cdn.jsdelivr.net/foundation/5.3.3/css/normalize.css',
- '//cdn.jsdelivr.net/foundation/5.3.3/css/foundation.min.css',
- '//cdn.jsdelivr.net/foundation/5.3.3/js/foundation.min.js',
- 'app.js'
- ),
-
- ),*/
-
- /**
- * Preload assets.
- * Here you may set which assets (CSS files, JavaScript files or collections)
- * should be loaded by default even if you don't explicitly add them on run time.
- *
- * @var array
- */
- //'autoload' => array('jquery-cdn'),
-
+ // Configuration for the default group. Feel free to add more groups.
+ // Each group can have different settings.
+ 'default' => array(
+
+ /**
+ * Regex to match against a filename/url to determine if it is an asset.
+ *
+ * @var string
+ */
+ //'asset_regex' => '/.\.(css|js)$/i',
+
+ /**
+ * Regex to match against a filename/url to determine if it is a CSS asset.
+ *
+ * @var string
+ */
+ //'css_regex' => '/.\.css$/i',
+
+ /**
+ * Regex to match against a filename/url to determine if it is a JavaScript asset.
+ *
+ * @var string
+ */
+ //'js_regex' => '/.\.js$/i',
+
+ /**
+ * Regex to match against a filename/url to determine if it should not be minified by pipeline.
+ *
+ * @var string
+ */
+ //'no_minification_regex' => '/.[-.]min\.(css|js)$/i',
+
+ /**
+ * Absolute path to the public directory of your App (WEBROOT).
+ * Required if you enable the pipeline.
+ * No trailing slash!.
+ *
+ * @var string
+ */
+ //'public_dir' => (function_exists('public_path')) ? public_path() : '/var/www/localhost/htdocs',
+
+ /**
+ * Directory for local CSS assets.
+ * Relative to your public directory ('public_dir').
+ * No trailing slash!.
+ *
+ * @var string
+ */
+ //'css_dir' => 'css',
+
+ /**
+ * Directory for local JavaScript assets.
+ * Relative to your public directory ('public_dir').
+ * No trailing slash!.
+ *
+ * @var string
+ */
+ //'js_dir' => 'js',
+
+ /**
+ * Directory for local package assets.
+ * Relative to your public directory ('public_dir').
+ * No trailing slash!.
+ *
+ * @var string
+ */
+ //'packages_dir' => 'packages',
+
+ /**
+ * Enable assets pipeline (concatenation and minification).
+ * Use a string that evaluates to `true` to provide the salt of the pipeline hash.
+ * Use 'auto' to automatically calculated the salt from your assets last modification time.
+ *
+ * @var bool|string
+ */
+ //'pipeline' => false,
+
+ /**
+ * Directory for storing pipelined assets.
+ * Relative to your assets directories ('css_dir' and 'js_dir').
+ * No trailing slash!.
+ *
+ * @var string
+ */
+ //'pipeline_dir' => 'min',
+
+ /**
+ * Enable pipelined assets compression with Gzip.
+ * Use only if your webserver supports Gzip HTTP_ACCEPT_ENCODING.
+ * Set to true to use the default compression level.
+ * Set an integer between 0 (no compression) and 9 (maximum compression) to choose compression level.
+ *
+ * @var bool|integer
+ */
+ //'pipeline_gzip' => false,
+
+ /**
+ * Closure used by the pipeline to fetch assets.
+ *
+ * Useful when file_get_contents() function is not available in your PHP
+ * instalation or when you want to apply any kind of preprocessing to
+ * your assets before they get pipelined.
+ *
+ * The closure will receive as the only parameter a string with the path/URL of the asset and
+ * it should return the content of the asset file as a string.
+ *
+ * @var Closure
+ */
+ //'fetch_command' => function ($asset) {return preprocess(file_get_contents($asset));},
+
+ /**
+ * Available collections.
+ * Each collection is an array of assets.
+ * Collections may also contain other collections.
+ *
+ * @var array
+ */
+ /*'collections' => array(
+
+ // jQuery (CDN)
+ 'jquery-cdn' => array('//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'),
+
+ // jQuery UI (CDN)
+ 'jquery-ui-cdn' => array(
+ 'jquery-cdn',
+ '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js',
+ ),
+
+ // Twitter Bootstrap (CDN)
+ 'bootstrap-cdn' => array(
+ 'jquery-cdn',
+ '//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css',
+ '//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css',
+ '//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js'
+ ),
+
+ // Zurb Foundation (CDN)
+ 'foundation-cdn' => array(
+ 'jquery-cdn',
+ '//cdn.jsdelivr.net/foundation/5.3.3/css/normalize.css',
+ '//cdn.jsdelivr.net/foundation/5.3.3/css/foundation.min.css',
+ '//cdn.jsdelivr.net/foundation/5.3.3/js/foundation.min.js',
+ 'app.js'
+ ),
+
+ ),*/
+
+ /**
+ * Preload assets.
+ * Here you may set which assets (CSS files, JavaScript files or collections)
+ * should be loaded by default even if you don't explicitly add them on run time.
+ *
+ * @var array
+ */
+ //'autoload' => array('jquery-cdn'),
+
+ ), // End of default group
);
diff --git a/tests/AssetsManagerTest.php b/tests/AssetsManagerTest.php
index fb4429a..751ceaa 100644
--- a/tests/AssetsManagerTest.php
+++ b/tests/AssetsManagerTest.php
@@ -40,7 +40,6 @@ public function testRemoteLinkDetection()
$this->assertFalse($method->invokeArgs($this->manager, array('foo')));
}
-
public function testPackageAssetDetection()
{
$vendor = '_This-Is-Vendor.0';
@@ -162,9 +161,9 @@ public function testDetectAndAddCollection()
$this->assertStringEndsWith($asset2, array_pop($assets2));
}
- public function testRegexOptions(){
-
- $files = [
+ public function testRegexOptions()
+ {
+ $files = array(
'.css', // Not an asset
'foo.CSS',
'foomin.css',
@@ -176,7 +175,7 @@ public function testRegexOptions(){
'foomin.js',
'foo.min.js', // Skip from minification
'foo-MIN.js', // Skip from minification
- ];
+ );
// Test asset detection
$regex = PHPUnit_Framework_Assert::readAttribute($this->manager, 'asset_regex');
@@ -207,7 +206,8 @@ public function testRegexOptions(){
$this->assertEquals(4, count($matching));
}
- protected static function getMethod($name) {
+ protected static function getMethod($name)
+ {
$class = new ReflectionClass('Stolz\Assets\Manager');
$method = $class->getMethod($name);
$method->setAccessible(true);