silverstripe-framework/src/View/Requirements_Backend.php

1515 lines
49 KiB
PHP
Raw Normal View History

<?php
namespace SilverStripe\View;
use Exception;
API Refactor bootstrap, request handling See https://github.com/silverstripe/silverstripe-framework/pull/7037 and https://github.com/silverstripe/silverstripe-framework/issues/6681 Squashed commit of the following: commit 8f65e5653211240650eaa4fa65bb83b45aae6d58 Author: Ingo Schommer <me@chillu.com> Date: Thu Jun 22 22:25:50 2017 +1200 Fixed upgrade guide spelling commit 76f95944fa89b0b540704b8d744329f690f9698c Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 16:38:34 2017 +1200 BUG Fix non-test class manifest including sapphiretest / functionaltest commit 9379834cb4b2e5177a2600049feec05bf111c16b Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:50:47 2017 +1200 BUG Fix nesting bug in Kernel commit 188ce35d82599360c40f0f2de29579c56fb90761 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:14:51 2017 +1200 BUG fix db bootstrapping issues commit 7ed4660e7a63915e8e974deeaba9807bc4d38b0d Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 14:49:07 2017 +1200 BUG Fix issue in DetailedErrorFormatter commit 738f50c497166f81ccbe3f40fbcff895ce71f82f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:49:19 2017 +1200 Upgrading notes on mysite/_config.php commit 6279d28e5e455916f902a2f963c014d8899f7fc7 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:43:28 2017 +1200 Update developer documentation commit 5c90d53a84ef0139c729396949a7857fae60436f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 10:48:44 2017 +1200 Update installer to not use global databaseConfig commit f9b2ba4755371f08bd95f6908ac612fcbb7ca205 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 21:04:39 2017 +1200 Fix behat issues commit 5b59a912b60282b4dad4ef10ed3b97c5d0a761ac Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 17:07:11 2017 +1200 Move HTTPApplication to SilverStripe\Control namespace commit e2c4a18f637bdd3d276619554de60ee8b4d95ced Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 16:29:03 2017 +1200 More documentation Fix up remaining tests Refactor temp DB into TempDatabase class so it’s available outside of unit tests. commit 5d235e64f341d6251bfe9f4833f15cc8593c5034 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 12:13:15 2017 +1200 API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals BUG Fix issue with SSViewer Fix Security / View tests commit d88d4ed4e48291cb65407f222f190064b1f1deeb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:39:43 2017 +1200 API Refactor AppKernel into CoreKernel commit f7946aec3391139ae1b4029c353c327a36552b36 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:00:40 2017 +1200 Docs and minor cleanup commit 12bd31f9366327650b5c0c0f96cd0327d44faf0a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 15:34:34 2017 +1200 API Remove OutputMiddleware API Move environment / global / ini management into Environment class API Move getTempFolder into TempFolder class API Implement HTTPRequestBuilder / CLIRequestBuilder BUG Restore SS_ALLOWED_HOSTS check in original location API CoreKernel now requires $basePath to be passed in API Refactor installer.php to use application to bootstrap API move memstring conversion globals to Convert BUG Fix error in CoreKernel nesting not un-nesting itself properly. commit bba979114624247cf463cf2a8c9e4be9a7c3a772 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 18:07:53 2017 +1200 API Create HTTPMiddleware and standardise middleware for request handling commit 2a10c2397bdc53001013f607b5d38087ce6c0730 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:42:42 2017 +1200 Fixed ORM tests commit d75a8d1d93398af4bd0432df9e4bc6295c15a3fe Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:15:07 2017 +1200 FIx i18n tests commit 06364af3c379c931889c4cc34dd920fee3db204a Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 16:59:34 2017 +1200 Fix controller namespace Move states to sub namespace commit 2a278e2953d2dbb19f78d91c919048e1fc935436 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 12:49:45 2017 +1200 Fix forms namespace commit b65c21241bee019730027071d815dbf7571197a4 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:56:48 2017 +1200 Update API usages commit d1d4375c95a264a6b63cbaefc2c1d12f808bfd82 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:41:44 2017 +1200 API Refactor $flush into HTPPApplication API Enforce health check in Controller::pushCurrent() API Better global backup / restore Updated Director::test() to use new API commit b220534f06732db4fa940d8724c2a85c0ba2495a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 22:05:57 2017 +1200 Move app nesting to a test state helper commit 603704165c08d0c1c81fd5e6bb9506326eeee17b Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 21:46:04 2017 +1200 Restore kernel stack to fix multi-level nesting commit 2f6336a15bf79dc8c2edd44cec1931da2dd51c28 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 17:23:21 2017 +1200 API Implement kernel nesting commit fc7188da7d6ad6785354bab61f08700454c81d91 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:43:13 2017 +1200 Fix core tests commit a0ae7235148fffd71f2f02d1fe7fe45bf3aa39eb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:23:52 2017 +1200 Fix manifest tests commit ca033952513633e182040d3d13e1caa9000ca184 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:00:00 2017 +1200 API Move extension management into test state commit c66d4339777663a8a04661fea32a0cf35b95d20f Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 14:10:59 2017 +1200 API Refactor SapphireTest state management into SapphireTestState API Remove Injector::unregisterAllObjects() API Remove FakeController commit f26ae75c6ecaafa0dec1093264e0187191e6764d Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 18:04:34 2017 +1200 Implement basic CLI application object commit 001d5596621404892de0a5413392379eff990641 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 17:39:38 2017 +1200 Remove references to SapphireTest::is_running_test() Upgrade various code commit de079c041dacd96bc4f4b66421fa2b2cc4c320f8 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 7 18:07:33 2017 +1200 API Implement APP object API Refactor of Session
2017-06-22 12:50:45 +02:00
use InvalidArgumentException;
use SilverStripe\Assets\File;
use SilverStripe\Assets\Storage\GeneratedAssetHandler;
use SilverStripe\Control\Director;
2016-09-09 08:43:05 +02:00
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
2017-10-03 01:20:49 +02:00
use SilverStripe\Core\Manifest\ModuleResourceLoader;
use SilverStripe\Core\Manifest\ResourceURLGenerator;
use SilverStripe\Core\Path;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Deprecation;
use SilverStripe\i18n\i18n;
use SilverStripe\ORM\FieldType\DBField;
class Requirements_Backend
{
2016-11-29 00:31:16 +01:00
use Injectable;
/**
* Whether to add caching query params to the requests for file-based requirements.
* Eg: themes/myTheme/js/main.js?m=123456789. The parameter is a timestamp generated by
* filemtime. This has the benefit of allowing the browser to cache the URL infinitely,
* while automatically busting this cache every time the file is changed.
*
* @var bool
*/
protected $suffixRequirements = true;
/**
* Whether to combine CSS and JavaScript files
*
API Refactor bootstrap, request handling See https://github.com/silverstripe/silverstripe-framework/pull/7037 and https://github.com/silverstripe/silverstripe-framework/issues/6681 Squashed commit of the following: commit 8f65e5653211240650eaa4fa65bb83b45aae6d58 Author: Ingo Schommer <me@chillu.com> Date: Thu Jun 22 22:25:50 2017 +1200 Fixed upgrade guide spelling commit 76f95944fa89b0b540704b8d744329f690f9698c Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 16:38:34 2017 +1200 BUG Fix non-test class manifest including sapphiretest / functionaltest commit 9379834cb4b2e5177a2600049feec05bf111c16b Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:50:47 2017 +1200 BUG Fix nesting bug in Kernel commit 188ce35d82599360c40f0f2de29579c56fb90761 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:14:51 2017 +1200 BUG fix db bootstrapping issues commit 7ed4660e7a63915e8e974deeaba9807bc4d38b0d Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 14:49:07 2017 +1200 BUG Fix issue in DetailedErrorFormatter commit 738f50c497166f81ccbe3f40fbcff895ce71f82f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:49:19 2017 +1200 Upgrading notes on mysite/_config.php commit 6279d28e5e455916f902a2f963c014d8899f7fc7 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:43:28 2017 +1200 Update developer documentation commit 5c90d53a84ef0139c729396949a7857fae60436f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 10:48:44 2017 +1200 Update installer to not use global databaseConfig commit f9b2ba4755371f08bd95f6908ac612fcbb7ca205 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 21:04:39 2017 +1200 Fix behat issues commit 5b59a912b60282b4dad4ef10ed3b97c5d0a761ac Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 17:07:11 2017 +1200 Move HTTPApplication to SilverStripe\Control namespace commit e2c4a18f637bdd3d276619554de60ee8b4d95ced Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 16:29:03 2017 +1200 More documentation Fix up remaining tests Refactor temp DB into TempDatabase class so it’s available outside of unit tests. commit 5d235e64f341d6251bfe9f4833f15cc8593c5034 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 12:13:15 2017 +1200 API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals BUG Fix issue with SSViewer Fix Security / View tests commit d88d4ed4e48291cb65407f222f190064b1f1deeb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:39:43 2017 +1200 API Refactor AppKernel into CoreKernel commit f7946aec3391139ae1b4029c353c327a36552b36 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:00:40 2017 +1200 Docs and minor cleanup commit 12bd31f9366327650b5c0c0f96cd0327d44faf0a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 15:34:34 2017 +1200 API Remove OutputMiddleware API Move environment / global / ini management into Environment class API Move getTempFolder into TempFolder class API Implement HTTPRequestBuilder / CLIRequestBuilder BUG Restore SS_ALLOWED_HOSTS check in original location API CoreKernel now requires $basePath to be passed in API Refactor installer.php to use application to bootstrap API move memstring conversion globals to Convert BUG Fix error in CoreKernel nesting not un-nesting itself properly. commit bba979114624247cf463cf2a8c9e4be9a7c3a772 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 18:07:53 2017 +1200 API Create HTTPMiddleware and standardise middleware for request handling commit 2a10c2397bdc53001013f607b5d38087ce6c0730 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:42:42 2017 +1200 Fixed ORM tests commit d75a8d1d93398af4bd0432df9e4bc6295c15a3fe Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:15:07 2017 +1200 FIx i18n tests commit 06364af3c379c931889c4cc34dd920fee3db204a Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 16:59:34 2017 +1200 Fix controller namespace Move states to sub namespace commit 2a278e2953d2dbb19f78d91c919048e1fc935436 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 12:49:45 2017 +1200 Fix forms namespace commit b65c21241bee019730027071d815dbf7571197a4 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:56:48 2017 +1200 Update API usages commit d1d4375c95a264a6b63cbaefc2c1d12f808bfd82 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:41:44 2017 +1200 API Refactor $flush into HTPPApplication API Enforce health check in Controller::pushCurrent() API Better global backup / restore Updated Director::test() to use new API commit b220534f06732db4fa940d8724c2a85c0ba2495a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 22:05:57 2017 +1200 Move app nesting to a test state helper commit 603704165c08d0c1c81fd5e6bb9506326eeee17b Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 21:46:04 2017 +1200 Restore kernel stack to fix multi-level nesting commit 2f6336a15bf79dc8c2edd44cec1931da2dd51c28 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 17:23:21 2017 +1200 API Implement kernel nesting commit fc7188da7d6ad6785354bab61f08700454c81d91 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:43:13 2017 +1200 Fix core tests commit a0ae7235148fffd71f2f02d1fe7fe45bf3aa39eb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:23:52 2017 +1200 Fix manifest tests commit ca033952513633e182040d3d13e1caa9000ca184 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:00:00 2017 +1200 API Move extension management into test state commit c66d4339777663a8a04661fea32a0cf35b95d20f Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 14:10:59 2017 +1200 API Refactor SapphireTest state management into SapphireTestState API Remove Injector::unregisterAllObjects() API Remove FakeController commit f26ae75c6ecaafa0dec1093264e0187191e6764d Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 18:04:34 2017 +1200 Implement basic CLI application object commit 001d5596621404892de0a5413392379eff990641 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 17:39:38 2017 +1200 Remove references to SapphireTest::is_running_test() Upgrade various code commit de079c041dacd96bc4f4b66421fa2b2cc4c320f8 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 7 18:07:33 2017 +1200 API Implement APP object API Refactor of Session
2017-06-22 12:50:45 +02:00
* @var bool|null
2016-11-29 00:31:16 +01:00
*/
API Refactor bootstrap, request handling See https://github.com/silverstripe/silverstripe-framework/pull/7037 and https://github.com/silverstripe/silverstripe-framework/issues/6681 Squashed commit of the following: commit 8f65e5653211240650eaa4fa65bb83b45aae6d58 Author: Ingo Schommer <me@chillu.com> Date: Thu Jun 22 22:25:50 2017 +1200 Fixed upgrade guide spelling commit 76f95944fa89b0b540704b8d744329f690f9698c Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 16:38:34 2017 +1200 BUG Fix non-test class manifest including sapphiretest / functionaltest commit 9379834cb4b2e5177a2600049feec05bf111c16b Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:50:47 2017 +1200 BUG Fix nesting bug in Kernel commit 188ce35d82599360c40f0f2de29579c56fb90761 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:14:51 2017 +1200 BUG fix db bootstrapping issues commit 7ed4660e7a63915e8e974deeaba9807bc4d38b0d Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 14:49:07 2017 +1200 BUG Fix issue in DetailedErrorFormatter commit 738f50c497166f81ccbe3f40fbcff895ce71f82f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:49:19 2017 +1200 Upgrading notes on mysite/_config.php commit 6279d28e5e455916f902a2f963c014d8899f7fc7 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:43:28 2017 +1200 Update developer documentation commit 5c90d53a84ef0139c729396949a7857fae60436f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 10:48:44 2017 +1200 Update installer to not use global databaseConfig commit f9b2ba4755371f08bd95f6908ac612fcbb7ca205 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 21:04:39 2017 +1200 Fix behat issues commit 5b59a912b60282b4dad4ef10ed3b97c5d0a761ac Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 17:07:11 2017 +1200 Move HTTPApplication to SilverStripe\Control namespace commit e2c4a18f637bdd3d276619554de60ee8b4d95ced Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 16:29:03 2017 +1200 More documentation Fix up remaining tests Refactor temp DB into TempDatabase class so it’s available outside of unit tests. commit 5d235e64f341d6251bfe9f4833f15cc8593c5034 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 12:13:15 2017 +1200 API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals BUG Fix issue with SSViewer Fix Security / View tests commit d88d4ed4e48291cb65407f222f190064b1f1deeb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:39:43 2017 +1200 API Refactor AppKernel into CoreKernel commit f7946aec3391139ae1b4029c353c327a36552b36 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:00:40 2017 +1200 Docs and minor cleanup commit 12bd31f9366327650b5c0c0f96cd0327d44faf0a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 15:34:34 2017 +1200 API Remove OutputMiddleware API Move environment / global / ini management into Environment class API Move getTempFolder into TempFolder class API Implement HTTPRequestBuilder / CLIRequestBuilder BUG Restore SS_ALLOWED_HOSTS check in original location API CoreKernel now requires $basePath to be passed in API Refactor installer.php to use application to bootstrap API move memstring conversion globals to Convert BUG Fix error in CoreKernel nesting not un-nesting itself properly. commit bba979114624247cf463cf2a8c9e4be9a7c3a772 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 18:07:53 2017 +1200 API Create HTTPMiddleware and standardise middleware for request handling commit 2a10c2397bdc53001013f607b5d38087ce6c0730 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:42:42 2017 +1200 Fixed ORM tests commit d75a8d1d93398af4bd0432df9e4bc6295c15a3fe Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:15:07 2017 +1200 FIx i18n tests commit 06364af3c379c931889c4cc34dd920fee3db204a Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 16:59:34 2017 +1200 Fix controller namespace Move states to sub namespace commit 2a278e2953d2dbb19f78d91c919048e1fc935436 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 12:49:45 2017 +1200 Fix forms namespace commit b65c21241bee019730027071d815dbf7571197a4 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:56:48 2017 +1200 Update API usages commit d1d4375c95a264a6b63cbaefc2c1d12f808bfd82 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:41:44 2017 +1200 API Refactor $flush into HTPPApplication API Enforce health check in Controller::pushCurrent() API Better global backup / restore Updated Director::test() to use new API commit b220534f06732db4fa940d8724c2a85c0ba2495a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 22:05:57 2017 +1200 Move app nesting to a test state helper commit 603704165c08d0c1c81fd5e6bb9506326eeee17b Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 21:46:04 2017 +1200 Restore kernel stack to fix multi-level nesting commit 2f6336a15bf79dc8c2edd44cec1931da2dd51c28 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 17:23:21 2017 +1200 API Implement kernel nesting commit fc7188da7d6ad6785354bab61f08700454c81d91 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:43:13 2017 +1200 Fix core tests commit a0ae7235148fffd71f2f02d1fe7fe45bf3aa39eb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:23:52 2017 +1200 Fix manifest tests commit ca033952513633e182040d3d13e1caa9000ca184 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:00:00 2017 +1200 API Move extension management into test state commit c66d4339777663a8a04661fea32a0cf35b95d20f Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 14:10:59 2017 +1200 API Refactor SapphireTest state management into SapphireTestState API Remove Injector::unregisterAllObjects() API Remove FakeController commit f26ae75c6ecaafa0dec1093264e0187191e6764d Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 18:04:34 2017 +1200 Implement basic CLI application object commit 001d5596621404892de0a5413392379eff990641 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 17:39:38 2017 +1200 Remove references to SapphireTest::is_running_test() Upgrade various code commit de079c041dacd96bc4f4b66421fa2b2cc4c320f8 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 7 18:07:33 2017 +1200 API Implement APP object API Refactor of Session
2017-06-22 12:50:45 +02:00
protected $combinedFilesEnabled = null;
2016-11-29 00:31:16 +01:00
/**
* Determine if files should be combined automatically on dev mode.
*
* By default combined files will not be combined except in test or
* live environments. Turning this on will allow for pre-combining of files in development mode.
*
* @config
* @var bool
*/
private static $combine_in_dev = false;
/**
* Paths to all required JavaScript files relative to docroot
*
* @var array
*/
protected $javascript = array();
/**
* Map of included scripts to array of contained files.
* To be used alongside front-end combination mechanisms.
*
* @var array Map of providing filepath => array(provided filepaths)
*/
protected $providedJavascript = array();
/**
* Paths to all required CSS files relative to the docroot.
*
* @var array
*/
protected $css = array();
/**
* All custom javascript code that is inserted into the page's HTML
*
* @var array
*/
protected $customScript = array();
/**
* All custom CSS rules which are inserted directly at the bottom of the HTML <head> tag
*
* @var array
*/
protected $customCSS = array();
/**
* All custom HTML markup which is added before the closing <head> tag, e.g. additional
* metatags.
*
* @var array
*/
protected $customHeadTags = array();
/**
* Remembers the file paths or uniquenessIDs of all Requirements cleared through
* {@link clear()}, so that they can be restored later.
*
* @var array
*/
protected $disabled = array();
/**
* The file paths (relative to docroot) or uniquenessIDs of any included requirements which
* should be blocked when executing {@link inlcudeInHTML()}. This is useful, for example,
* to block scripts included by a superclass without having to override entire functions and
* duplicate a lot of code.
*
* Use {@link unblock()} or {@link unblock_all()} to revert changes.
*
* @var array
*/
protected $blocked = array();
/**
* A list of combined files registered via {@link combine_files()}. Keys are the output file
* names, values are lists of input files.
*
* @var array
*/
protected $combinedFiles = array();
/**
* Use the injected minification service to minify any javascript file passed to {@link combine_files()}.
2016-11-29 00:31:16 +01:00
*
* @var bool
*/
protected $minifyCombinedFiles = false;
2016-11-29 00:31:16 +01:00
/**
* Whether or not file headers should be written when combining files
*
* @var boolean
*/
protected $writeHeaderComment = true;
/**
* Where to save combined files. By default they're placed in assets/_combinedfiles, however
* this may be an issue depending on your setup, especially for CSS files which often contain
* relative paths.
*
* @var string
*/
protected $combinedFilesFolder = null;
/**
* Put all JavaScript includes at the bottom of the template before the closing <body> tag,
* rather than the default behaviour of placing them at the end of the <head> tag. This means
* script downloads won't block other HTTP requests, which can be a performance improvement.
*
* @var bool
*/
public $writeJavascriptToBody = true;
/**
* Force the JavaScript to the bottom of the page, even if there's a script tag in the body already
*
* @var boolean
*/
protected $forceJSToBottom = false;
/**
* Configures the default prefix for combined files.
*
* This defaults to `_combinedfiles`, and is the folder within the configured asset backend that
* combined files will be stored in. If using a backend shared with other systems, it is usually
* necessary to distinguish combined files from other assets.
*
* @config
* @var string
*/
private static $default_combined_files_folder = '_combinedfiles';
/**
* Flag to include the hash in the querystring instead of the filename for combined files.
*
* By default the `<hash>` of the source files is appended to the end of the combined file
* (prior to the file extension). If combined files are versioned in source control or running
* in a distributed environment (such as one where the newest version of a file may not always be
* immediately available) then it may sometimes be necessary to disable this. When this is set to true,
* the hash will instead be appended via a querystring parameter to enable cache busting, but not in
* the filename itself. I.e. `assets/_combinedfiles/name.js?m=<hash>`
*
* @config
* @var bool
*/
private static $combine_hash_querystring = false;
/**
* @var GeneratedAssetHandler
*/
protected $assetHandler = null;
/**
* @var Requirements_Minifier
*/
protected $minifier = null;
2016-11-29 00:31:16 +01:00
/**
* Gets the backend storage for generated files
*
* @return GeneratedAssetHandler
*/
public function getAssetHandler()
{
return $this->assetHandler;
}
/**
* Set a new asset handler for this backend
*
* @param GeneratedAssetHandler $handler
*/
public function setAssetHandler(GeneratedAssetHandler $handler)
{
$this->assetHandler = $handler;
}
/**
* Gets the minification service for this backend
*
* @deprecated 4.0.0:5.0.0
* @return Requirements_Minifier
*/
public function getMinifier()
{
return $this->minifier;
}
/**
* Set a new minification service for this backend
*
* @param Requirements_Minifier $minifier
*/
public function setMinifier(Requirements_Minifier $minifier = null)
{
$this->minifier = $minifier;
}
2016-11-29 00:31:16 +01:00
/**
* Enable or disable the combination of CSS and JavaScript files
*
* @param bool $enable
*/
public function setCombinedFilesEnabled($enable)
{
$this->combinedFilesEnabled = (bool)$enable;
}
/**
* Check if header comments are written
*
* @return bool
*/
public function getWriteHeaderComment()
{
return $this->writeHeaderComment;
}
/**
* Flag whether header comments should be written for each combined file
*
* @param bool $write
* @return $this
*/
public function setWriteHeaderComment($write)
{
$this->writeHeaderComment = $write;
return $this;
}
/**
* Set the folder to save combined files in. By default they're placed in _combinedfiles,
* however this may be an issue depending on your setup, especially for CSS files which often
* contain relative paths.
*
* This must not include any 'assets' prefix
*
* @param string $folder
*/
public function setCombinedFilesFolder($folder)
{
$this->combinedFilesFolder = $folder;
}
/**
* Retrieve the combined files folder prefix
*
* @return string
*/
public function getCombinedFilesFolder()
{
if ($this->combinedFilesFolder) {
return $this->combinedFilesFolder;
}
return Config::inst()->get(__CLASS__, 'default_combined_files_folder');
}
/**
* Set whether to add caching query params to the requests for file-based requirements.
* Eg: themes/myTheme/js/main.js?m=123456789. The parameter is a timestamp generated by
* filemtime. This has the benefit of allowing the browser to cache the URL infinitely,
* while automatically busting this cache every time the file is changed.
*
* @param bool
*/
public function setSuffixRequirements($var)
{
$this->suffixRequirements = $var;
}
/**
* Check whether we want to suffix requirements
*
* @return bool
*/
public function getSuffixRequirements()
{
return $this->suffixRequirements;
}
/**
* Set whether you want to write the JS to the body of the page rather than at the end of the
* head tag.
*
* @param bool
* @return $this
*/
public function setWriteJavascriptToBody($var)
{
$this->writeJavascriptToBody = $var;
return $this;
}
/**
* Check whether you want to write the JS to the body of the page rather than at the end of the
* head tag.
*
* @return bool
*/
public function getWriteJavascriptToBody()
{
return $this->writeJavascriptToBody;
}
/**
* Forces the JavaScript requirements to the end of the body, right before the closing tag
*
* @param bool
* @return $this
*/
public function setForceJSToBottom($var)
{
$this->forceJSToBottom = $var;
return $this;
}
/**
* Check if the JavaScript requirements are written to the end of the body, right before the closing tag
*
* @return bool
*/
public function getForceJSToBottom()
{
return $this->forceJSToBottom;
}
/**
* Check if minify files should be combined
2016-11-29 00:31:16 +01:00
*
* @return bool
*/
public function getMinifyCombinedFiles()
2016-11-29 00:31:16 +01:00
{
return $this->minifyCombinedFiles;
2016-11-29 00:31:16 +01:00
}
/**
* Set if combined files should be minified
2016-11-29 00:31:16 +01:00
*
* @param bool $minify
* @return $this
*/
public function setMinifyCombinedFiles($minify)
2016-11-29 00:31:16 +01:00
{
$this->minifyCombinedFiles = $minify;
2016-11-29 00:31:16 +01:00
return $this;
}
/**
* Register the given JavaScript file as required.
*
* @param string $file Either relative to docroot or in the form "vendor/package:resource"
2016-11-29 00:31:16 +01:00
* @param array $options List of options. Available options include:
* - 'provides' : List of scripts files included in this file
* - 'async' : Boolean value to set async attribute to script tag
* - 'defer' : Boolean value to set defer attribute to script tag
* - 'type' : Override script type= value.
*/
public function javascript($file, $options = array())
{
2017-10-03 01:20:49 +02:00
$file = ModuleResourceLoader::singleton()->resolvePath($file);
2016-11-29 00:31:16 +01:00
// Get type
$type = null;
if (isset($this->javascript[$file]['type'])) {
$type = $this->javascript[$file]['type'];
}
if (isset($options['type'])) {
$type = $options['type'];
}
// make sure that async/defer is set if it is set once even if file is included multiple times
$async = (
isset($options['async']) && isset($options['async']) == true
|| (
isset($this->javascript[$file])
&& isset($this->javascript[$file]['async'])
&& $this->javascript[$file]['async'] == true
)
);
$defer = (
isset($options['defer']) && isset($options['defer']) == true
|| (
isset($this->javascript[$file])
&& isset($this->javascript[$file]['defer'])
&& $this->javascript[$file]['defer'] == true
)
);
$this->javascript[$file] = array(
'async' => $async,
'defer' => $defer,
'type' => $type,
);
// Record scripts included in this file
if (isset($options['provides'])) {
$this->providedJavascript[$file] = array_values($options['provides']);
}
}
/**
* Remove a javascript requirement
*
* @param string $file
*/
protected function unsetJavascript($file)
{
unset($this->javascript[$file]);
}
/**
* Gets all scripts that are already provided by prior scripts.
* This follows these rules:
* - Files will not be considered provided if they are separately
* included prior to the providing file.
* - Providing files can be blocked, and don't provide anything
* - Provided files can't be blocked (you need to block the provider)
* - If a combined file includes files that are provided by prior
* scripts, then these should be excluded from the combined file.
* - If a combined file includes files that are provided by later
* scripts, then these files should be included in the combined
* file, but we can't block the later script either (possible double
* up of file).
*
* @return array Array of provided files (map of $path => $path)
*/
public function getProvidedScripts()
{
$providedScripts = array();
$includedScripts = array();
foreach ($this->javascript as $script => $options) {
// Ignore scripts that are explicitly blocked
if (isset($this->blocked[$script])) {
continue;
}
// At this point, the file is included.
// This might also be combined at this point, potentially.
$includedScripts[$script] = true;
// Record any files this provides, EXCEPT those already included by now
if (isset($this->providedJavascript[$script])) {
foreach ($this->providedJavascript[$script] as $provided) {
if (!isset($includedScripts[$provided])) {
$providedScripts[$provided] = $provided;
}
}
}
}
return $providedScripts;
}
/**
* Returns an array of required JavaScript, excluding blocked
* and duplicates of provided files.
*
* @return array
*/
public function getJavascript()
{
return array_diff_key(
$this->javascript,
$this->getBlocked(),
$this->getProvidedScripts()
);
}
/**
* Gets all javascript, including blocked files. Unwraps the array into a non-associative list
*
* @return array Indexed array of javascript files
*/
protected function getAllJavascript()
{
return $this->javascript;
}
/**
* Register the given JavaScript code into the list of requirements
*
* @param string $script The script content as a string (without enclosing <script> tag)
* @param string $uniquenessID A unique ID that ensures a piece of code is only added once
*/
public function customScript($script, $uniquenessID = null)
{
if ($uniquenessID) {
$this->customScript[$uniquenessID] = $script;
} else {
$this->customScript[] = $script;
}
}
/**
* Return all registered custom scripts
*
* @return array
*/
public function getCustomScripts()
{
return array_diff_key($this->customScript, $this->blocked);
}
/**
* Register the given CSS styles into the list of requirements
*
* @param string $script CSS selectors as a string (without enclosing <style> tag)
* @param string $uniquenessID A unique ID that ensures a piece of code is only added once
*/
public function customCSS($script, $uniquenessID = null)
{
if ($uniquenessID) {
$this->customCSS[$uniquenessID] = $script;
} else {
$this->customCSS[] = $script;
}
}
/**
* Return all registered custom CSS
*
* @return array
*/
public function getCustomCSS()
{
return array_diff_key($this->customCSS, $this->blocked);
}
/**
* Add the following custom HTML code to the <head> section of the page
*
* @param string $html Custom HTML code
* @param string $uniquenessID A unique ID that ensures a piece of code is only added once
*/
public function insertHeadTags($html, $uniquenessID = null)
{
if ($uniquenessID) {
$this->customHeadTags[$uniquenessID] = $html;
} else {
$this->customHeadTags[] = $html;
}
}
/**
* Return all custom head tags
*
* @return array
*/
public function getCustomHeadTags()
{
return array_diff_key($this->customHeadTags, $this->blocked);
}
/**
* Include the content of the given JavaScript file in the list of requirements. Dollar-sign
* variables will be interpolated with values from $vars similar to a .ss template.
*
* @param string $file The template file to load, relative to docroot
* @param string[] $vars The array of variables to interpolate.
* @param string $uniquenessID A unique ID that ensures a piece of code is only added once
*/
public function javascriptTemplate($file, $vars, $uniquenessID = null)
{
$file = ModuleResourceLoader::singleton()->resolvePath($file);
$absolutePath = Director::getAbsFile($file);
if (!file_exists($absolutePath)) {
throw new InvalidArgumentException("Javascript template file {$file} does not exist");
}
$script = file_get_contents($absolutePath);
2016-11-29 00:31:16 +01:00
$search = array();
$replace = array();
if ($vars) {
foreach ($vars as $k => $v) {
$search[] = '$' . $k;
$replace[] = str_replace("\\'", "'", Convert::raw2js($v));
}
}
$script = str_replace($search, $replace, $script);
$this->customScript($script, $uniquenessID);
}
/**
* Register the given stylesheet into the list of requirements.
*
* @param string $file The CSS file to load, relative to site root
* @param string $media Comma-separated list of media types to use in the link tag
* (e.g. 'screen,projector')
*/
public function css($file, $media = null)
{
2017-10-03 01:20:49 +02:00
$file = ModuleResourceLoader::singleton()->resolvePath($file);
$this->css[$file] = [
2016-11-29 00:31:16 +01:00
"media" => $media
];
2016-11-29 00:31:16 +01:00
}
/**
* Remove a css requirement
*
* @param string $file
*/
protected function unsetCSS($file)
{
unset($this->css[$file]);
}
/**
* Get the list of registered CSS file requirements, excluding blocked files
*
* @return array Associative array of file to spec
*/
public function getCSS()
{
return array_diff_key($this->css, $this->blocked);
}
/**
* Gets all CSS files requirements, including blocked
*
* @return array Associative array of file to spec
*/
protected function getAllCSS()
{
return $this->css;
}
/**
* Gets the list of all blocked files
*
* @return array
*/
public function getBlocked()
{
return $this->blocked;
}
/**
* Clear either a single or all requirements
*
* Caution: Clearing single rules added via customCSS and customScript only works if you
* originally specified a $uniquenessID.
*
* @param string|int $fileOrID
*/
public function clear($fileOrID = null)
{
2017-08-29 00:24:41 +02:00
$types = [
'javascript',
'css',
'customScript',
'customCSS',
'customHeadTags',
'combinedFiles',
];
foreach ($types as $type) {
if ($fileOrID) {
2016-11-29 00:31:16 +01:00
if (isset($this->{$type}[$fileOrID])) {
$this->disabled[$type][$fileOrID] = $this->{$type}[$fileOrID];
unset($this->{$type}[$fileOrID]);
}
2017-08-29 00:24:41 +02:00
} else {
$this->disabled[$type] = $this->{$type};
$this->{$type} = [];
2016-11-29 00:31:16 +01:00
}
}
}
/**
* Restore requirements cleared by call to Requirements::clear
*/
public function restore()
{
2017-08-29 00:24:41 +02:00
$types = [
'javascript',
'css',
'customScript',
'customCSS',
'customHeadTags',
'combinedFiles',
];
foreach ($types as $type) {
$this->{$type} = $this->disabled[$type];
}
2016-11-29 00:31:16 +01:00
}
/**
* Block inclusion of a specific file
*
* The difference between this and {@link clear} is that the calling order does not matter;
* {@link clear} must be called after the initial registration, whereas {@link block} can be
* used in advance. This is useful, for example, to block scripts included by a superclass
* without having to override entire functions and duplicate a lot of code.
*
* Note that blocking should be used sparingly because it's hard to trace where an file is
* being blocked from.
*
* @param string|int $fileOrID Relative path from webroot, module resource reference or
* requirement API ID
2016-11-29 00:31:16 +01:00
*/
public function block($fileOrID)
{
if (is_string($fileOrID)) {
$fileOrID = ModuleResourceLoader::singleton()->resolvePath($fileOrID);
}
2016-11-29 00:31:16 +01:00
$this->blocked[$fileOrID] = $fileOrID;
}
/**
* Remove an item from the block list
*
* @param string|int $fileOrID
*/
public function unblock($fileOrID)
{
unset($this->blocked[$fileOrID]);
}
/**
* Removes all items from the block list
*/
public function unblockAll()
{
$this->blocked = array();
}
/**
* Update the given HTML content with the appropriate include tags for the registered
* requirements. Needs to receive a valid HTML/XHTML template in the $content parameter,
* including a head and body tag.
*
* @param string $content HTML content that has already been parsed from the $templateFile
* through {@link SSViewer}
* @return string HTML content augmented with the requirements tags
*/
public function includeInHTML($content)
{
if (func_num_args() > 1) {
Deprecation::notice(
'5.0',
'$templateFile argument is deprecated. includeInHTML takes a sole $content parameter now.'
);
$content = func_get_arg(1);
}
// Skip if content isn't injectable, or there is nothing to inject
$tagsAvailable = preg_match('#</head\b#', $content);
$hasFiles = $this->css || $this->javascript || $this->customCSS || $this->customScript || $this->customHeadTags;
if (!$tagsAvailable || !$hasFiles) {
return $content;
}
$requirements = '';
$jsRequirements = '';
// Combine files - updates $this->javascript and $this->css
$this->processCombinedFiles();
// Script tags for js links
2016-11-29 00:31:16 +01:00
foreach ($this->getJavascript() as $file => $attributes) {
// Build html attributes
$htmlAttributes = [
'type' => isset($attributes['type']) ? $attributes['type'] : "application/javascript",
'src' => $this->pathForFile($file),
];
if (!empty($attributes['async'])) {
$htmlAttributes['async'] = 'async';
}
if (!empty($attributes['defer'])) {
$htmlAttributes['defer'] = 'defer';
2016-11-29 00:31:16 +01:00
}
$jsRequirements .= HTML::createTag('script', $htmlAttributes);
$jsRequirements .= "\n";
2016-11-29 00:31:16 +01:00
}
// Add all inline JavaScript *after* including external files they might rely on
foreach ($this->getCustomScripts() as $script) {
$jsRequirements .= HTML::createTag(
'script',
[ 'type' => 'application/javascript' ],
"//<![CDATA[\n{$script}\n//]]>"
);
$jsRequirements .= "\n";
2016-11-29 00:31:16 +01:00
}
// CSS file links
2016-11-29 00:31:16 +01:00
foreach ($this->getCSS() as $file => $params) {
$htmlAttributes = [
'rel' => 'stylesheet',
'type' => 'text/css',
'href' => $this->pathForFile($file),
];
if (!empty($params['media'])) {
$htmlAttributes['media'] = $params['media'];
2016-11-29 00:31:16 +01:00
}
$requirements .= HTML::createTag('link', $htmlAttributes);
$requirements .= "\n";
2016-11-29 00:31:16 +01:00
}
// Literal custom CSS content
2016-11-29 00:31:16 +01:00
foreach ($this->getCustomCSS() as $css) {
$requirements .= HTML::createTag('style', ['type' => 'text/css'], "\n{$css}\n");
$requirements .= "\n";
2016-11-29 00:31:16 +01:00
}
foreach ($this->getCustomHeadTags() as $customHeadTag) {
$requirements .= "{$customHeadTag}\n";
2016-11-29 00:31:16 +01:00
}
// Inject CSS into body
$content = $this->insertTagsIntoHead($requirements, $content);
// Inject scripts
if ($this->getForceJSToBottom()) {
$content = $this->insertScriptsAtBottom($jsRequirements, $content);
} elseif ($this->getWriteJavascriptToBody()) {
$content = $this->insertScriptsIntoBody($jsRequirements, $content);
} else {
$content = $this->insertTagsIntoHead($jsRequirements, $content);
}
return $content;
}
/**
* Given a block of HTML, insert the given scripts at the bottom before
* the closing </body> tag
*
* @param string $jsRequirements String containing one or more javascript <script /> tags
* @param string $content HTML body
* @return string Merged HTML
*/
protected function insertScriptsAtBottom($jsRequirements, $content)
{
// Forcefully put the scripts at the bottom of the body instead of before the first
// script tag.
$content = preg_replace(
'/(<\/body[^>]*>)/i',
$this->escapeReplacement($jsRequirements) . '\\1',
$content
);
return $content;
}
/**
* Given a block of HTML, insert the given scripts inside the <body></body>
*
* @param string $jsRequirements String containing one or more javascript <script /> tags
* @param string $content HTML body
* @return string Merged HTML
*/
protected function insertScriptsIntoBody($jsRequirements, $content)
{
// If your template already has script tags in the body, then we try to put our script
// tags just before those. Otherwise, we put it at the bottom.
$bodyTagPosition = stripos($content, '<body');
$scriptTagPosition = stripos($content, '<script', $bodyTagPosition);
$commentTags = array();
$canWriteToBody = ($scriptTagPosition !== false)
&&
// Check that the script tag is not inside a html comment tag
!(
preg_match('/.*(?|(<!--)|(-->))/U', $content, $commentTags, 0, $scriptTagPosition)
&&
$commentTags[1] == '-->'
);
if ($canWriteToBody) {
// Insert content before existing script tags
$content = substr($content, 0, $scriptTagPosition)
. $jsRequirements
. substr($content, $scriptTagPosition);
} else {
// Insert content at bottom of page otherwise
$content = $this->insertScriptsAtBottom($jsRequirements, $content);
}
return $content;
}
/**
* Given a block of HTML, insert the given code inside the <head></head> block
*
* @param string $jsRequirements String containing one or more html tags
* @param string $content HTML body
* @return string Merged HTML
*/
protected function insertTagsIntoHead($jsRequirements, $content)
{
$content = preg_replace(
'/(<\/head>)/i',
$this->escapeReplacement($jsRequirements) . '\\1',
$content
);
return $content;
}
/**
* Safely escape a literal string for use in preg_replace replacement
*
* @param string $replacement
* @return string
*/
protected function escapeReplacement($replacement)
{
return addcslashes($replacement, '\\$');
}
/**
* Attach requirements inclusion to X-Include-JS and X-Include-CSS headers on the given
* HTTP Response
*
* @param HTTPResponse $response
*/
public function includeInResponse(HTTPResponse $response)
{
$this->processCombinedFiles();
$jsRequirements = array();
$cssRequirements = array();
foreach ($this->getJavascript() as $file => $attributes) {
$path = $this->pathForFile($file);
if ($path) {
$jsRequirements[] = str_replace(',', '%2C', $path);
}
}
if (count($jsRequirements)) {
$response->addHeader('X-Include-JS', implode(',', $jsRequirements));
}
foreach ($this->getCSS() as $file => $params) {
$path = $this->pathForFile($file);
if ($path) {
$path = str_replace(',', '%2C', $path);
$cssRequirements[] = isset($params['media']) ? "$path:##:$params[media]" : $path;
}
}
if (count($cssRequirements)) {
$response->addHeader('X-Include-CSS', implode(',', $cssRequirements));
}
}
/**
* Add i18n files from the given javascript directory. SilverStripe expects that the given
* directory will contain a number of JavaScript files named by language: en_US.js, de_DE.js,
* etc.
*
* @param string $langDir The JavaScript lang directory, relative to the site root, e.g.,
* 'framework/javascript/lang'
* @param bool $return Return all relative file paths rather than including them in
* requirements
*
* @return array|null All relative files if $return is true, or null otherwise
*/
public function add_i18n_javascript($langDir, $return = false)
{
$langDir = ModuleResourceLoader::singleton()->resolvePath($langDir);
2016-11-29 00:31:16 +01:00
$files = array();
$candidates = array(
'en',
'en_US',
i18n::getData()->langFromLocale(i18n::config()->get('default_locale')),
i18n::config()->get('default_locale'),
i18n::getData()->langFromLocale(i18n::get_locale()),
i18n::get_locale(),
strtolower(DBField::create_field('Locale', i18n::get_locale())->RFC1766()),
strtolower(DBField::create_field('Locale', i18n::config()->get('default_locale'))->RFC1766())
2016-11-29 00:31:16 +01:00
);
$candidates = array_map(
function ($candidate) {
return $candidate . '.js';
},
$candidates
);
2016-11-29 00:31:16 +01:00
foreach ($candidates as $candidate) {
$relativePath = Path::join($langDir, $candidate);
$absolutePath = Director::getAbsFile($relativePath);
if (file_exists($absolutePath)) {
$files[] = $relativePath;
2016-11-29 00:31:16 +01:00
}
}
if ($return) {
return $files;
}
foreach ($files as $file) {
$this->javascript($file);
}
return null;
2016-11-29 00:31:16 +01:00
}
/**
* Finds the path for specified file
*
* @param string $fileOrUrl
* @return string|bool
*/
protected function pathForFile($fileOrUrl)
{
// Since combined urls could be root relative, treat them as urls here.
if (preg_match('{^(//)|(http[s]?:)}', $fileOrUrl) || Director::is_root_relative_url($fileOrUrl)) {
return $fileOrUrl;
} else {
return Injector::inst()->get(ResourceURLGenerator::class)->urlForResource($fileOrUrl);
2016-11-29 00:31:16 +01:00
}
}
/**
* Concatenate several css or javascript files into a single dynamically generated file. This
* increases performance by fewer HTTP requests.
*
* The combined file is regenerated based on every file modification time. Optionally a
* rebuild can be triggered by appending ?flush=1 to the URL.
*
* All combined files will have a comment on the start of each concatenated file denoting their
* original position.
*
* CAUTION: You're responsible for ensuring that the load order for combined files is
* retained - otherwise combining JavaScript files can lead to functional errors in the
* JavaScript logic, and combining CSS can lead to incorrect inheritance. You can also
* only include each file once across all includes and combinations in a single page load.
*
* CAUTION: Combining CSS Files discards any "media" information.
*
* Example for combined JavaScript:
* <code>
* Requirements::combine_files(
* 'foobar.js',
* array(
* 'mysite/javascript/foo.js',
* 'mysite/javascript/bar.js',
* ),
* array(
* 'async' => true,
* 'defer' => true,
* )
* );
* </code>
*
* Example for combined CSS:
* <code>
* Requirements::combine_files(
* 'foobar.css',
* array(
* 'mysite/javascript/foo.css',
* 'mysite/javascript/bar.css',
* ),
* array(
* 'media' => 'print',
* )
* );
* </code>
*
* @param string $combinedFileName Filename of the combined file relative to docroot
* @param array $files Array of filenames relative to docroot
* @param array $options Array of options for combining files. Available options are:
* - 'media' : If including CSS Files, you can specify a media type
* - 'async' : If including JavaScript Files, boolean value to set async attribute to script tag
* - 'defer' : If including JavaScript Files, boolean value to set defer attribute to script tag
*/
public function combineFiles($combinedFileName, $files, $options = array())
{
if (is_string($options)) {
Deprecation::notice('4.0', 'Parameter media is deprecated. Use options array instead.');
$options = array('media' => $options);
}
// Skip this combined files if already included
if (isset($this->combinedFiles[$combinedFileName])) {
return;
}
// Add all files to necessary type list
$paths = array();
$combinedType = null;
foreach ($files as $file) {
// Get file details
list($path, $type) = $this->parseCombinedFile($file);
if ($type === 'javascript') {
$type = 'js';
}
if ($combinedType && $type && $combinedType !== $type) {
throw new InvalidArgumentException(
"Cannot mix js and css files in same combined file {$combinedFileName}"
);
}
switch ($type) {
case 'css':
$this->css($path, (isset($options['media']) ? $options['media'] : null));
break;
case 'js':
$this->javascript($path, $options);
break;
default:
throw new InvalidArgumentException("Invalid combined file type: {$type}");
}
$combinedType = $type;
$paths[] = $path;
}
// Duplicate check
foreach ($this->combinedFiles as $existingCombinedFilename => $combinedItem) {
$existingFiles = $combinedItem['files'];
$duplicates = array_intersect($existingFiles, $paths);
if ($duplicates) {
throw new InvalidArgumentException(sprintf(
"Requirements_Backend::combine_files(): Already included file(s) %s in combined file '%s'",
implode(',', $duplicates),
$existingCombinedFilename
));
}
}
$this->combinedFiles[$combinedFileName] = array(
'files' => $paths,
'type' => $combinedType,
'options' => $options,
);
}
/**
* Return path and type of given combined file
*
* @param string|array $file Either a file path, or an array spec
* @return array array with two elements, path and type of file
*/
protected function parseCombinedFile($file)
{
// Array with path and type keys
if (is_array($file) && isset($file['path']) && isset($file['type'])) {
return array($file['path'], $file['type']);
}
// Extract value from indexed array
if (is_array($file)) {
$path = array_shift($file);
// See if there's a type specifier
if ($file) {
$type = array_shift($file);
return array($path, $type);
}
// Otherwise convent to string
$file = $path;
}
$type = File::get_file_extension($file);
return array($file, $type);
}
/**
* Return all combined files; keys are the combined file names, values are lists of
* associative arrays with 'files', 'type', and 'media' keys for details about this
* combined file.
*
* @return array
*/
public function getCombinedFiles()
{
return array_diff_key($this->combinedFiles, $this->blocked);
}
/**
* Includes all combined files, including blocked ones
*
* @return array
*/
protected function getAllCombinedFiles()
{
return $this->combinedFiles;
}
/**
* Clears all combined files
*/
public function deleteAllCombinedFiles()
{
$combinedFolder = $this->getCombinedFilesFolder();
if ($combinedFolder) {
$this->getAssetHandler()->removeContent($combinedFolder);
}
}
/**
* Clear all registered CSS and JavaScript file combinations
*/
public function clearCombinedFiles()
{
$this->combinedFiles = array();
}
/**
* Do the heavy lifting involved in combining the combined files.
*/
public function processCombinedFiles()
{
// Check if combining is enabled
if (!$this->getCombinedFilesEnabled()) {
return;
}
// Before scripts are modified, detect files that are provided by preceding ones
$providedScripts = $this->getProvidedScripts();
// Process each combined files
foreach ($this->getAllCombinedFiles() as $combinedFile => $combinedItem) {
$fileList = $combinedItem['files'];
$type = $combinedItem['type'];
$options = $combinedItem['options'];
// Generate this file, unless blocked
$combinedURL = null;
if (!isset($this->blocked[$combinedFile])) {
// Filter files for blocked / provided
$filteredFileList = array_diff(
$fileList,
$this->getBlocked(),
$providedScripts
);
$combinedURL = $this->getCombinedFileURL($combinedFile, $filteredFileList, $type);
}
// Replace all existing files, injecting the combined file at the position of the first item
// in order to preserve inclusion order.
// Note that we iterate across blocked files in order to get the correct order, and validate
// that the file is included in the correct location (regardless of which files are blocked).
$included = false;
switch ($type) {
case 'css': {
$newCSS = array(); // Assoc array of css file => spec
foreach ($this->getAllCSS() as $css => $spec) {
if (!in_array($css, $fileList)) {
$newCSS[$css] = $spec;
} elseif (!$included && $combinedURL) {
$newCSS[$combinedURL] = array('media' => (isset($options['media']) ? $options['media'] : null));
$included = true;
}
// If already included, or otherwise blocked, then don't add into CSS
}
$this->css = $newCSS;
break;
}
case 'js': {
// Assoc array of file => attributes
$newJS = array();
foreach ($this->getAllJavascript() as $script => $attributes) {
if (!in_array($script, $fileList)) {
$newJS[$script] = $attributes;
} elseif (!$included && $combinedURL) {
$newJS[$combinedURL] = $options;
$included = true;
}
// If already included, or otherwise blocked, then don't add into scripts
}
$this->javascript = $newJS;
break;
}
}
}
}
/**
* Given a set of files, combine them (as necessary) and return the url
*
* @param string $combinedFile Filename for this combined file
* @param array $fileList List of files to combine
* @param string $type Either 'js' or 'css'
* @return string|null URL to this resource, if there are files to combine
* @throws Exception
2016-11-29 00:31:16 +01:00
*/
protected function getCombinedFileURL($combinedFile, $fileList, $type)
{
// Skip empty lists
if (empty($fileList)) {
return null;
}
// Generate path (Filename)
$hashQuerystring = Config::inst()->get(static::class, 'combine_hash_querystring');
if (!$hashQuerystring) {
$combinedFile = $this->hashedCombinedFilename($combinedFile, $fileList);
}
$combinedFileID = File::join_paths($this->getCombinedFilesFolder(), $combinedFile);
// Send file combination request to the backend, with an optional callback to perform regeneration
$minify = $this->getMinifyCombinedFiles();
if ($minify && !$this->minifier) {
throw new Exception(
sprintf(
API Refactor bootstrap, request handling See https://github.com/silverstripe/silverstripe-framework/pull/7037 and https://github.com/silverstripe/silverstripe-framework/issues/6681 Squashed commit of the following: commit 8f65e5653211240650eaa4fa65bb83b45aae6d58 Author: Ingo Schommer <me@chillu.com> Date: Thu Jun 22 22:25:50 2017 +1200 Fixed upgrade guide spelling commit 76f95944fa89b0b540704b8d744329f690f9698c Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 16:38:34 2017 +1200 BUG Fix non-test class manifest including sapphiretest / functionaltest commit 9379834cb4b2e5177a2600049feec05bf111c16b Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:50:47 2017 +1200 BUG Fix nesting bug in Kernel commit 188ce35d82599360c40f0f2de29579c56fb90761 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:14:51 2017 +1200 BUG fix db bootstrapping issues commit 7ed4660e7a63915e8e974deeaba9807bc4d38b0d Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 14:49:07 2017 +1200 BUG Fix issue in DetailedErrorFormatter commit 738f50c497166f81ccbe3f40fbcff895ce71f82f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:49:19 2017 +1200 Upgrading notes on mysite/_config.php commit 6279d28e5e455916f902a2f963c014d8899f7fc7 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:43:28 2017 +1200 Update developer documentation commit 5c90d53a84ef0139c729396949a7857fae60436f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 10:48:44 2017 +1200 Update installer to not use global databaseConfig commit f9b2ba4755371f08bd95f6908ac612fcbb7ca205 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 21:04:39 2017 +1200 Fix behat issues commit 5b59a912b60282b4dad4ef10ed3b97c5d0a761ac Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 17:07:11 2017 +1200 Move HTTPApplication to SilverStripe\Control namespace commit e2c4a18f637bdd3d276619554de60ee8b4d95ced Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 16:29:03 2017 +1200 More documentation Fix up remaining tests Refactor temp DB into TempDatabase class so it’s available outside of unit tests. commit 5d235e64f341d6251bfe9f4833f15cc8593c5034 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 12:13:15 2017 +1200 API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals BUG Fix issue with SSViewer Fix Security / View tests commit d88d4ed4e48291cb65407f222f190064b1f1deeb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:39:43 2017 +1200 API Refactor AppKernel into CoreKernel commit f7946aec3391139ae1b4029c353c327a36552b36 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:00:40 2017 +1200 Docs and minor cleanup commit 12bd31f9366327650b5c0c0f96cd0327d44faf0a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 15:34:34 2017 +1200 API Remove OutputMiddleware API Move environment / global / ini management into Environment class API Move getTempFolder into TempFolder class API Implement HTTPRequestBuilder / CLIRequestBuilder BUG Restore SS_ALLOWED_HOSTS check in original location API CoreKernel now requires $basePath to be passed in API Refactor installer.php to use application to bootstrap API move memstring conversion globals to Convert BUG Fix error in CoreKernel nesting not un-nesting itself properly. commit bba979114624247cf463cf2a8c9e4be9a7c3a772 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 18:07:53 2017 +1200 API Create HTTPMiddleware and standardise middleware for request handling commit 2a10c2397bdc53001013f607b5d38087ce6c0730 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:42:42 2017 +1200 Fixed ORM tests commit d75a8d1d93398af4bd0432df9e4bc6295c15a3fe Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:15:07 2017 +1200 FIx i18n tests commit 06364af3c379c931889c4cc34dd920fee3db204a Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 16:59:34 2017 +1200 Fix controller namespace Move states to sub namespace commit 2a278e2953d2dbb19f78d91c919048e1fc935436 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 12:49:45 2017 +1200 Fix forms namespace commit b65c21241bee019730027071d815dbf7571197a4 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:56:48 2017 +1200 Update API usages commit d1d4375c95a264a6b63cbaefc2c1d12f808bfd82 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:41:44 2017 +1200 API Refactor $flush into HTPPApplication API Enforce health check in Controller::pushCurrent() API Better global backup / restore Updated Director::test() to use new API commit b220534f06732db4fa940d8724c2a85c0ba2495a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 22:05:57 2017 +1200 Move app nesting to a test state helper commit 603704165c08d0c1c81fd5e6bb9506326eeee17b Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 21:46:04 2017 +1200 Restore kernel stack to fix multi-level nesting commit 2f6336a15bf79dc8c2edd44cec1931da2dd51c28 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 17:23:21 2017 +1200 API Implement kernel nesting commit fc7188da7d6ad6785354bab61f08700454c81d91 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:43:13 2017 +1200 Fix core tests commit a0ae7235148fffd71f2f02d1fe7fe45bf3aa39eb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:23:52 2017 +1200 Fix manifest tests commit ca033952513633e182040d3d13e1caa9000ca184 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:00:00 2017 +1200 API Move extension management into test state commit c66d4339777663a8a04661fea32a0cf35b95d20f Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 14:10:59 2017 +1200 API Refactor SapphireTest state management into SapphireTestState API Remove Injector::unregisterAllObjects() API Remove FakeController commit f26ae75c6ecaafa0dec1093264e0187191e6764d Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 18:04:34 2017 +1200 Implement basic CLI application object commit 001d5596621404892de0a5413392379eff990641 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 17:39:38 2017 +1200 Remove references to SapphireTest::is_running_test() Upgrade various code commit de079c041dacd96bc4f4b66421fa2b2cc4c320f8 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 7 18:07:33 2017 +1200 API Implement APP object API Refactor of Session
2017-06-22 12:50:45 +02:00
<<<MESSAGE
Cannot minify files without a minification service defined.
Set %s::minifyCombinedFiles to false, or inject a %s service on
%s.properties.minifier
MESSAGE
,
__CLASS__,
Requirements_Minifier::class,
__CLASS__
)
);
}
2016-11-29 00:31:16 +01:00
$combinedURL = $this
->getAssetHandler()
->getContentURL(
$combinedFileID,
function () use ($fileList, $minify, $type) {
// Physically combine all file content
$combinedData = '';
foreach ($fileList as $file) {
$filePath = Director::getAbsFile($file);
if (!file_exists($filePath)) {
throw new InvalidArgumentException("Combined file {$file} does not exist");
}
$fileContent = file_get_contents($filePath);
2016-11-29 00:31:16 +01:00
// Use configured minifier
if ($minify) {
$fileContent = $this->minifier->minify($fileContent, $type, $file);
2016-11-29 00:31:16 +01:00
}
if ($this->writeHeaderComment) {
// Write a header comment for each file for easier identification and debugging.
$combinedData .= "/****** FILE: $file *****/\n";
}
$combinedData .= $fileContent . "\n";
}
return $combinedData;
}
);
// If the name isn't hashed, we will need to append the querystring m= parameter instead
// Since url won't be automatically suffixed, add it in here
if ($hashQuerystring && $this->getSuffixRequirements()) {
$hash = $this->hashOfFiles($fileList);
$q = stripos($combinedURL, '?') === false ? '?' : '&';
$combinedURL .= "{$q}m={$hash}";
}
return $combinedURL;
}
/**
* Given a filename and list of files, generate a new filename unique to these files
*
* @param string $combinedFile
* @param array $fileList
* @return string
*/
protected function hashedCombinedFilename($combinedFile, $fileList)
{
$name = pathinfo($combinedFile, PATHINFO_FILENAME);
$hash = $this->hashOfFiles($fileList);
$extension = File::get_file_extension($combinedFile);
return $name . '-' . substr($hash, 0, 7) . '.' . $extension;
}
/**
* Check if combined files are enabled
*
* @return bool
*/
public function getCombinedFilesEnabled()
{
API Refactor bootstrap, request handling See https://github.com/silverstripe/silverstripe-framework/pull/7037 and https://github.com/silverstripe/silverstripe-framework/issues/6681 Squashed commit of the following: commit 8f65e5653211240650eaa4fa65bb83b45aae6d58 Author: Ingo Schommer <me@chillu.com> Date: Thu Jun 22 22:25:50 2017 +1200 Fixed upgrade guide spelling commit 76f95944fa89b0b540704b8d744329f690f9698c Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 16:38:34 2017 +1200 BUG Fix non-test class manifest including sapphiretest / functionaltest commit 9379834cb4b2e5177a2600049feec05bf111c16b Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:50:47 2017 +1200 BUG Fix nesting bug in Kernel commit 188ce35d82599360c40f0f2de29579c56fb90761 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 15:14:51 2017 +1200 BUG fix db bootstrapping issues commit 7ed4660e7a63915e8e974deeaba9807bc4d38b0d Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 14:49:07 2017 +1200 BUG Fix issue in DetailedErrorFormatter commit 738f50c497166f81ccbe3f40fbcff895ce71f82f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:49:19 2017 +1200 Upgrading notes on mysite/_config.php commit 6279d28e5e455916f902a2f963c014d8899f7fc7 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 11:43:28 2017 +1200 Update developer documentation commit 5c90d53a84ef0139c729396949a7857fae60436f Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 22 10:48:44 2017 +1200 Update installer to not use global databaseConfig commit f9b2ba4755371f08bd95f6908ac612fcbb7ca205 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 21:04:39 2017 +1200 Fix behat issues commit 5b59a912b60282b4dad4ef10ed3b97c5d0a761ac Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 17:07:11 2017 +1200 Move HTTPApplication to SilverStripe\Control namespace commit e2c4a18f637bdd3d276619554de60ee8b4d95ced Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 16:29:03 2017 +1200 More documentation Fix up remaining tests Refactor temp DB into TempDatabase class so it’s available outside of unit tests. commit 5d235e64f341d6251bfe9f4833f15cc8593c5034 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 21 12:13:15 2017 +1200 API HTTPRequestBuilder::createFromEnvironment() now cleans up live globals BUG Fix issue with SSViewer Fix Security / View tests commit d88d4ed4e48291cb65407f222f190064b1f1deeb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:39:43 2017 +1200 API Refactor AppKernel into CoreKernel commit f7946aec3391139ae1b4029c353c327a36552b36 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 16:00:40 2017 +1200 Docs and minor cleanup commit 12bd31f9366327650b5c0c0f96cd0327d44faf0a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 20 15:34:34 2017 +1200 API Remove OutputMiddleware API Move environment / global / ini management into Environment class API Move getTempFolder into TempFolder class API Implement HTTPRequestBuilder / CLIRequestBuilder BUG Restore SS_ALLOWED_HOSTS check in original location API CoreKernel now requires $basePath to be passed in API Refactor installer.php to use application to bootstrap API move memstring conversion globals to Convert BUG Fix error in CoreKernel nesting not un-nesting itself properly. commit bba979114624247cf463cf2a8c9e4be9a7c3a772 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 18:07:53 2017 +1200 API Create HTTPMiddleware and standardise middleware for request handling commit 2a10c2397bdc53001013f607b5d38087ce6c0730 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:42:42 2017 +1200 Fixed ORM tests commit d75a8d1d93398af4bd0432df9e4bc6295c15a3fe Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 17:15:07 2017 +1200 FIx i18n tests commit 06364af3c379c931889c4cc34dd920fee3db204a Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 16:59:34 2017 +1200 Fix controller namespace Move states to sub namespace commit 2a278e2953d2dbb19f78d91c919048e1fc935436 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 19 12:49:45 2017 +1200 Fix forms namespace commit b65c21241bee019730027071d815dbf7571197a4 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:56:48 2017 +1200 Update API usages commit d1d4375c95a264a6b63cbaefc2c1d12f808bfd82 Author: Damian Mooyman <damian@silverstripe.com> Date: Thu Jun 15 18:41:44 2017 +1200 API Refactor $flush into HTPPApplication API Enforce health check in Controller::pushCurrent() API Better global backup / restore Updated Director::test() to use new API commit b220534f06732db4fa940d8724c2a85c0ba2495a Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 22:05:57 2017 +1200 Move app nesting to a test state helper commit 603704165c08d0c1c81fd5e6bb9506326eeee17b Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 21:46:04 2017 +1200 Restore kernel stack to fix multi-level nesting commit 2f6336a15bf79dc8c2edd44cec1931da2dd51c28 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 17:23:21 2017 +1200 API Implement kernel nesting commit fc7188da7d6ad6785354bab61f08700454c81d91 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:43:13 2017 +1200 Fix core tests commit a0ae7235148fffd71f2f02d1fe7fe45bf3aa39eb Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:23:52 2017 +1200 Fix manifest tests commit ca033952513633e182040d3d13e1caa9000ca184 Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 15:00:00 2017 +1200 API Move extension management into test state commit c66d4339777663a8a04661fea32a0cf35b95d20f Author: Damian Mooyman <damian@silverstripe.com> Date: Tue Jun 13 14:10:59 2017 +1200 API Refactor SapphireTest state management into SapphireTestState API Remove Injector::unregisterAllObjects() API Remove FakeController commit f26ae75c6ecaafa0dec1093264e0187191e6764d Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 18:04:34 2017 +1200 Implement basic CLI application object commit 001d5596621404892de0a5413392379eff990641 Author: Damian Mooyman <damian@silverstripe.com> Date: Mon Jun 12 17:39:38 2017 +1200 Remove references to SapphireTest::is_running_test() Upgrade various code commit de079c041dacd96bc4f4b66421fa2b2cc4c320f8 Author: Damian Mooyman <damian@silverstripe.com> Date: Wed Jun 7 18:07:33 2017 +1200 API Implement APP object API Refactor of Session
2017-06-22 12:50:45 +02:00
if (isset($this->combinedFilesEnabled)) {
return $this->combinedFilesEnabled;
2016-11-29 00:31:16 +01:00
}
// Non-dev sites are always combined
if (!Director::isDev()) {
return true;
}
// Fallback to default
return Config::inst()->get(__CLASS__, 'combine_in_dev');
}
/**
* For a given filelist, determine some discriminating value to determine if
* any of these files have changed.
*
* @param array $fileList List of files
* @return string SHA1 bashed file hash
*/
protected function hashOfFiles($fileList)
{
// Get hash based on hash of each file
$hash = '';
foreach ($fileList as $file) {
$absolutePath = Director::getAbsFile($file);
if (file_exists($absolutePath)) {
$hash .= sha1_file($absolutePath);
2016-11-29 00:31:16 +01:00
} else {
throw new InvalidArgumentException("Combined file {$file} does not exist");
}
}
return sha1($hash);
}
/**
* Registers the given themeable stylesheet as required.
*
* A CSS file in the current theme path name 'themename/css/$name.css' is first searched for,
* and it that doesn't exist and the module parameter is set then a CSS file with that name in
* the module is used.
*
* @param string $name The name of the file - eg '/css/File.css' would have the name 'File'
* @param string $media Comma-separated list of media types to use in the link tag
* (e.g. 'screen,projector')
*/
public function themedCSS($name, $media = null)
{
$path = ThemeResourceLoader::inst()->findThemedCSS($name, SSViewer::get_themes());
2016-11-29 00:31:16 +01:00
if ($path) {
$this->css($path, $media);
} else {
2017-10-03 01:20:49 +02:00
throw new InvalidArgumentException(
"The css file doesn't exist. Please check if the file $name.css exists in any context or search for "
2016-11-29 00:31:16 +01:00
. "themedCSS references calling this file in your templates."
);
}
}
/**
* Registers the given themeable javascript as required.
*
* A javascript file in the current theme path name 'themename/javascript/$name.js' is first searched for,
* and it that doesn't exist and the module parameter is set then a javascript file with that name in
* the module is used.
*
* @param string $name The name of the file - eg '/js/File.js' would have the name 'File'
* @param string $type Comma-separated list of types to use in the script tag
* (e.g. 'text/javascript,text/ecmascript')
*/
public function themedJavascript($name, $type = null)
{
$path = ThemeResourceLoader::inst()->findThemedJavascript($name, SSViewer::get_themes());
2016-11-29 00:31:16 +01:00
if ($path) {
$opts = [];
if ($type) {
$opts['type'] = $type;
}
$this->javascript($path, $opts);
} else {
2017-10-03 01:20:49 +02:00
throw new InvalidArgumentException(
"The javascript file doesn't exist. Please check if the file $name.js exists in any "
2016-11-29 00:31:16 +01:00
. "context or search for themedJavascript references calling this file in your templates."
);
}
}
/**
* Output debugging information.
*/
public function debug()
{
Debug::show($this->javascript);
Debug::show($this->css);
Debug::show($this->customCSS);
Debug::show($this->customScript);
Debug::show($this->customHeadTags);
Debug::show($this->combinedFiles);
}
}