mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API Implement new module sorting pattern
This commit is contained in:
parent
695e0483aa
commit
2b266276c2
28
_config/modules.yml
Normal file
28
_config/modules.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
Name: coremodulesorter
|
||||||
|
---
|
||||||
|
SilverStripe\Core\Injector\Injector:
|
||||||
|
SilverStripe\Core\Manifest\PrioritySorter.modulesorter:
|
||||||
|
class: SilverStripe\Core\Manifest\PrioritySorter
|
||||||
|
properties:
|
||||||
|
RestKey: $other_modules
|
||||||
|
---
|
||||||
|
Name: modules-other
|
||||||
|
---
|
||||||
|
SilverStripe\Core\Manifest\ModuleManifest:
|
||||||
|
module_priority:
|
||||||
|
- $other_modules
|
||||||
|
---
|
||||||
|
Name: modules-project
|
||||||
|
Before: '*'
|
||||||
|
---
|
||||||
|
SilverStripe\Core\Manifest\ModuleManifest:
|
||||||
|
module_priority:
|
||||||
|
- $project
|
||||||
|
---
|
||||||
|
Name: modules-framework
|
||||||
|
After: modules-other
|
||||||
|
---
|
||||||
|
SilverStripe\Core\Manifest\ModuleManifest:
|
||||||
|
module_priority:
|
||||||
|
- silverstripe\framework
|
@ -43,20 +43,59 @@ The manifest is created whenever you flush your SilverStripe cache by appending
|
|||||||
example by visiting `http://yoursite.com/?flush=1`. When your include the `flush=1` flag, the manifest class will search
|
example by visiting `http://yoursite.com/?flush=1`. When your include the `flush=1` flag, the manifest class will search
|
||||||
your entire project for the appropriate `.ss` files located in `template` directory and save that information for later.
|
your entire project for the appropriate `.ss` files located in `template` directory and save that information for later.
|
||||||
|
|
||||||
It will each and prioritize templates in the following priority:
|
|
||||||
|
|
||||||
1. mysite (or other name given to site folder)
|
|
||||||
2. module-specific themes (e.g. themes/simple_blog)
|
|
||||||
3. themes (e.g. themes/simple)
|
|
||||||
4. modules (e.g. blog)
|
|
||||||
5. framework
|
|
||||||
|
|
||||||
<div class="warning">
|
<div class="warning">
|
||||||
Whenever you add or remove template files, rebuild the manifest by visiting `http://yoursite.com/?flush=1`. You can
|
Whenever you add or remove template files, rebuild the manifest by visiting `http://yoursite.com/?flush=1`. You can
|
||||||
flush the cache from any page, (.com/home?flush=1, .com/admin?flush=1, etc.). Flushing the cache can be slow, so you
|
flush the cache from any page, (.com/home?flush=1, .com/admin?flush=1, etc.). Flushing the cache can be slow, so you
|
||||||
only need to do it when you're developing new templates.
|
only need to do it when you're developing new templates.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## Template Priority
|
||||||
|
|
||||||
|
The order in which templates are selected from themes can be explicitly declared
|
||||||
|
through configuration. To specify the order you want, make a list of the module
|
||||||
|
names under `SilverStripe\Core\Manifest\ModuleManifest.module_priority` in a
|
||||||
|
configuration YAML file.
|
||||||
|
|
||||||
|
|
||||||
|
*some-module/_config.yml*
|
||||||
|
```yml
|
||||||
|
SilverStripe\Core\Manifest\ModuleManifest:
|
||||||
|
module_priority:
|
||||||
|
- 'example/module-one'
|
||||||
|
- 'example/module-two'
|
||||||
|
- '$other_modules'
|
||||||
|
- 'example/module-three'
|
||||||
|
```
|
||||||
|
|
||||||
|
The placeholder `$other_modules` is used to mark where all of the modules not specified
|
||||||
|
in the list should appear. (In alphabetical order of their containing directory names).
|
||||||
|
|
||||||
|
In this example, the module named `example/module-one` has the highest level of precedence,
|
||||||
|
followed by `example/module-two`. The module `example/module-three` is guaranteed the lowest
|
||||||
|
level of precedence.
|
||||||
|
|
||||||
|
### Defining a "project"
|
||||||
|
|
||||||
|
It is a good idea to define one of your modules as the `project`. Commonly, this is the
|
||||||
|
`mysite/` module, but there is nothing compulsory about that module name. The "project"
|
||||||
|
module can be specified as a variable in the `module_priorities` list, as well.
|
||||||
|
|
||||||
|
*some-module/_config.yml*
|
||||||
|
```yml
|
||||||
|
SilverStripe\Core\Manifest\ModuleManifest:
|
||||||
|
project: 'myapp'
|
||||||
|
module_priority:
|
||||||
|
- '$project'
|
||||||
|
- '$other_modules'
|
||||||
|
```
|
||||||
|
|
||||||
|
### About module "names"
|
||||||
|
|
||||||
|
Module names are derived their local `composer.json` files using the following precedence:
|
||||||
|
* The value of the `name` attribute in `composer.json`
|
||||||
|
* The value of `extras.installer_name` in `composer.json`
|
||||||
|
* The basename of the directory that contains the module
|
||||||
|
|
||||||
## Nested Layouts through `$Layout`
|
## Nested Layouts through `$Layout`
|
||||||
|
|
||||||
SilverStripe has basic support for nested layouts through a fixed template variable named `$Layout`. It's used for
|
SilverStripe has basic support for nested layouts through a fixed template variable named `$Layout`. It's used for
|
||||||
|
@ -50,7 +50,7 @@ you should call `->activate()` on the kernel instance you would like to unnest t
|
|||||||
|
|
||||||
# Application
|
# Application
|
||||||
|
|
||||||
An application represents a basic excution controller for the top level application entry point.
|
An application represents a basic execution controller for the top level application entry point.
|
||||||
The role of the application is to:
|
The role of the application is to:
|
||||||
|
|
||||||
- Control bootstrapping of a provided kernel instance
|
- Control bootstrapping of a provided kernel instance
|
||||||
|
@ -26,6 +26,7 @@ use SilverStripe\Logging\ErrorHandler;
|
|||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\View\ThemeManifest;
|
use SilverStripe\View\ThemeManifest;
|
||||||
use SilverStripe\View\ThemeResourceLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
use SilverStripe\Dev\Deprecation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple Kernel container
|
* Simple Kernel container
|
||||||
@ -116,7 +117,7 @@ class CoreKernel implements Kernel
|
|||||||
$themeResourceLoader = ThemeResourceLoader::inst();
|
$themeResourceLoader = ThemeResourceLoader::inst();
|
||||||
$themeResourceLoader->addSet('$default', new ThemeManifest(
|
$themeResourceLoader->addSet('$default', new ThemeManifest(
|
||||||
$basePath,
|
$basePath,
|
||||||
project(),
|
null, // project is defined in config, and this argument is deprecated
|
||||||
$manifestCacheFactory
|
$manifestCacheFactory
|
||||||
));
|
));
|
||||||
$this->setThemeResourceLoader($themeResourceLoader);
|
$this->setThemeResourceLoader($themeResourceLoader);
|
||||||
@ -196,8 +197,15 @@ class CoreKernel implements Kernel
|
|||||||
*/
|
*/
|
||||||
protected function bootConfigs()
|
protected function bootConfigs()
|
||||||
{
|
{
|
||||||
|
global $project;
|
||||||
|
$projectBefore = $project;
|
||||||
|
$config = ModuleManifest::config();
|
||||||
// After loading all other app manifests, include _config.php files
|
// After loading all other app manifests, include _config.php files
|
||||||
$this->getModuleLoader()->getManifest()->activateConfig();
|
$this->getModuleLoader()->getManifest()->activateConfig();
|
||||||
|
if ($project && $project !== $projectBefore) {
|
||||||
|
Deprecation::notice('5.0', '$project global is deprecated');
|
||||||
|
$config->set('project', $project);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -498,10 +506,15 @@ class CoreKernel implements Kernel
|
|||||||
$config->setFlush(true);
|
$config->setFlush(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// tell modules to sort, now that config is available
|
||||||
|
$this->getModuleLoader()->getManifest()->sort();
|
||||||
|
|
||||||
// Find default templates
|
// Find default templates
|
||||||
$defaultSet = $this->getThemeResourceLoader()->getSet('$default');
|
$defaultSet = $this->getThemeResourceLoader()->getSet('$default');
|
||||||
if ($defaultSet instanceof ThemeManifest) {
|
if ($defaultSet instanceof ThemeManifest) {
|
||||||
|
$defaultSet->setProject(
|
||||||
|
ModuleManifest::config()->get('project')
|
||||||
|
);
|
||||||
$defaultSet->init($this->getIncludeTests(), $flush);
|
$defaultSet->init($this->getIncludeTests(), $flush);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,27 +323,8 @@ class ClassManifest
|
|||||||
*/
|
*/
|
||||||
public function getOwnerModule($class)
|
public function getOwnerModule($class)
|
||||||
{
|
{
|
||||||
$path = realpath($this->getItemPath($class));
|
$path = $this->getItemPath($class);
|
||||||
if (!$path) {
|
return ModuleLoader::inst()->getManifest()->getModuleByPath($path);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var Module $rootModule */
|
|
||||||
$rootModule = null;
|
|
||||||
|
|
||||||
// Find based on loaded modules
|
|
||||||
$modules = ModuleLoader::inst()->getManifest()->getModules();
|
|
||||||
foreach ($modules as $module) {
|
|
||||||
// Leave root module as fallback
|
|
||||||
if (empty($module->getRelativePath())) {
|
|
||||||
$rootModule = $module;
|
|
||||||
} elseif (stripos($path, realpath($module->getPath())) === 0) {
|
|
||||||
return $module;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to top level module
|
|
||||||
return $rootModule;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,12 +5,18 @@ namespace SilverStripe\Core\Manifest;
|
|||||||
use LogicException;
|
use LogicException;
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use SilverStripe\Core\Cache\CacheFactory;
|
use SilverStripe\Core\Cache\CacheFactory;
|
||||||
|
use SilverStripe\Core\Config\Configurable;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class which builds a manifest of configuration items
|
* A utility class which builds a manifest of configuration items
|
||||||
*/
|
*/
|
||||||
class ModuleManifest
|
class ModuleManifest
|
||||||
{
|
{
|
||||||
|
use Configurable;
|
||||||
|
|
||||||
|
const PROJECT_KEY = '$project';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base path used when building the manifest
|
* The base path used when building the manifest
|
||||||
*
|
*
|
||||||
@ -42,7 +48,7 @@ class ModuleManifest
|
|||||||
*
|
*
|
||||||
* @var Module[]
|
* @var Module[]
|
||||||
*/
|
*/
|
||||||
protected $modules = array();
|
protected $modules = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a path as a module
|
* Adds a path as a module
|
||||||
@ -105,8 +111,8 @@ class ModuleManifest
|
|||||||
// build cache from factory
|
// build cache from factory
|
||||||
if ($this->cacheFactory) {
|
if ($this->cacheFactory) {
|
||||||
$this->cache = $this->cacheFactory->create(
|
$this->cache = $this->cacheFactory->create(
|
||||||
CacheInterface::class.'.modulemanifest',
|
CacheInterface::class . '.modulemanifest',
|
||||||
[ 'namespace' => 'modulemanifest' . ($includeTests ? '_tests' : '') ]
|
['namespace' => 'modulemanifest' . ($includeTests ? '_tests' : '')]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +130,10 @@ class ModuleManifest
|
|||||||
*/
|
*/
|
||||||
public function activateConfig()
|
public function activateConfig()
|
||||||
{
|
{
|
||||||
foreach ($this->getModules() as $module) {
|
$modules = $this->getModules();
|
||||||
|
// Work in reverse priority, so the higher priority modules get later execution
|
||||||
|
/** @var Module $module */
|
||||||
|
foreach (array_reverse($modules) as $module) {
|
||||||
$module->activate();
|
$module->activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,4 +234,66 @@ class ModuleManifest
|
|||||||
{
|
{
|
||||||
return $this->modules;
|
return $this->modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort modules sorted by priority
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function sort()
|
||||||
|
{
|
||||||
|
$order = static::config()->uninherited('module_priority');
|
||||||
|
$project = static::config()->get('project');
|
||||||
|
/* @var PrioritySorter $sorter */
|
||||||
|
$sorter = Injector::inst()->createWithArgs(
|
||||||
|
PrioritySorter::class . '.modulesorter',
|
||||||
|
[
|
||||||
|
$this->modules,
|
||||||
|
$order ?: []
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($project) {
|
||||||
|
$sorter->setVariable(self::PROJECT_KEY, $project);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->modules = $sorter->getSortedList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get module that contains the given path
|
||||||
|
*
|
||||||
|
* @param string $path Full filesystem path to the given file
|
||||||
|
* @return Module The module, or null if not a path in any module
|
||||||
|
*/
|
||||||
|
public function getModuleByPath($path)
|
||||||
|
{
|
||||||
|
// Ensure path exists
|
||||||
|
$path = realpath($path);
|
||||||
|
if (!$path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Module $rootModule */
|
||||||
|
$rootModule = null;
|
||||||
|
|
||||||
|
// Find based on loaded modules
|
||||||
|
$modules = ModuleLoader::inst()->getManifest()->getModules();
|
||||||
|
foreach ($modules as $module) {
|
||||||
|
// Check if path is in module
|
||||||
|
if (stripos($path, realpath($module->getPath())) !== 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is the root module, keep looking in case there is a more specific module later
|
||||||
|
if (empty($module->getRelativePath())) {
|
||||||
|
$rootModule = $module;
|
||||||
|
} else {
|
||||||
|
return $module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to top level module
|
||||||
|
return $rootModule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
212
src/Core/Manifest/PrioritySorter.php
Normal file
212
src/Core/Manifest/PrioritySorter.php
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Core\Manifest;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Injector\Injectable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts an associative array of items given a list of priorities,
|
||||||
|
* where priorities are the keys of the items in the order they are desired.
|
||||||
|
* Allows user-defined variables, and a "rest" key to symbolise all remaining items.
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* $myItems = [
|
||||||
|
* 'product-one' => new Product(...),
|
||||||
|
* 'product-two' => new Product(...),
|
||||||
|
* 'product-three' => new Product(...),
|
||||||
|
* 'product-four' => new Product(...),
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* $priorities = [
|
||||||
|
* '$featured',
|
||||||
|
* 'product-two',
|
||||||
|
* '...rest',
|
||||||
|
* ];
|
||||||
|
*
|
||||||
|
* $sorter = new PrioritySorter($items, $priorities);
|
||||||
|
* $sorter->setVariable('$featured', 'product-three');
|
||||||
|
* $sorter->getSortedList();
|
||||||
|
*
|
||||||
|
* [
|
||||||
|
* 'product-three' => [object] Product,
|
||||||
|
* 'product-two' => [object] Product,
|
||||||
|
* 'product-one' => [object] Product,
|
||||||
|
* 'product-four' => [object] Product
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class PrioritySorter
|
||||||
|
{
|
||||||
|
use Injectable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key that is used to denote all remaining items that have not
|
||||||
|
* been specified in priorities
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $restKey = '...rest';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of variables to their values
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $variables = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An associative array of items, whose keys can be used in the $priorities list
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An indexed array of keys in the $items list, reflecting the desired sort
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $priorities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The keys of the $items array
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $names;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PrioritySorter constructor.
|
||||||
|
* @param array $items
|
||||||
|
* @param array $priorities
|
||||||
|
*/
|
||||||
|
public function __construct(array $items = [], array $priorities = [])
|
||||||
|
{
|
||||||
|
$this->setItems($items);
|
||||||
|
$this->priorities = $priorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the items and returns a new version of $this->items
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSortedList()
|
||||||
|
{
|
||||||
|
$this->addVariables();
|
||||||
|
|
||||||
|
// Find all items that don't have their order specified by the config system
|
||||||
|
$unspecified = array_diff($this->names, $this->priorities);
|
||||||
|
|
||||||
|
if (!empty($unspecified)) {
|
||||||
|
$this->includeRest($unspecified);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sortedList = [];
|
||||||
|
foreach ($this->priorities as $itemName) {
|
||||||
|
if (isset($this->items[$itemName])) {
|
||||||
|
$sortedList[$itemName] = $this->items[$itemName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sortedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the priorities for the items
|
||||||
|
*
|
||||||
|
* @param array $priorities An array of keys used in $this->items
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setPriorities(array $priorities)
|
||||||
|
{
|
||||||
|
$this->priorities = $priorities;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list of all items
|
||||||
|
*
|
||||||
|
* @param array $items
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setItems(array $items)
|
||||||
|
{
|
||||||
|
$this->items = $items;
|
||||||
|
$this->names = array_keys($items);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a variable for replacination, e.g. addVariable->('$project', 'myproject')
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param $value
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setVariable($name, $value)
|
||||||
|
{
|
||||||
|
$this->variables[$name] = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key used for "all other items"
|
||||||
|
*
|
||||||
|
* @param $key
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setRestKey($key)
|
||||||
|
{
|
||||||
|
$this->restKey = $key;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If variables are defined, interpolate their values
|
||||||
|
*/
|
||||||
|
protected function addVariables()
|
||||||
|
{
|
||||||
|
// Remove variables from the list
|
||||||
|
$varValues = array_values($this->variables);
|
||||||
|
$this->names = array_filter($this->names, function ($name) use ($varValues) {
|
||||||
|
return !in_array($name, $varValues);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Replace variables with their values
|
||||||
|
$this->priorities = array_map(function ($name) {
|
||||||
|
return $this->resolveValue($name);
|
||||||
|
}, $this->priorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the "rest" key exists in the order array,
|
||||||
|
* replace it by the unspecified items
|
||||||
|
*/
|
||||||
|
protected function includeRest(array $list)
|
||||||
|
{
|
||||||
|
$otherItemsIndex = false;
|
||||||
|
if ($this->restKey) {
|
||||||
|
$otherItemsIndex = array_search($this->restKey, $this->priorities);
|
||||||
|
}
|
||||||
|
if ($otherItemsIndex !== false) {
|
||||||
|
array_splice($this->priorities, $otherItemsIndex, 1, $list);
|
||||||
|
} else {
|
||||||
|
// Otherwise just jam them on the end
|
||||||
|
$this->priorities = array_merge($this->priorities, $list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure variables get converted to their values
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function resolveValue($name)
|
||||||
|
{
|
||||||
|
return isset($this->variables[$name]) ? $this->variables[$name] : $name;
|
||||||
|
}
|
||||||
|
}
|
@ -108,13 +108,7 @@ class Deprecation
|
|||||||
|
|
||||||
$callingfile = realpath($backtrace[1]['file']);
|
$callingfile = realpath($backtrace[1]['file']);
|
||||||
|
|
||||||
$modules = ModuleLoader::inst()->getManifest()->getModules();
|
return ModuleLoader::inst()->getManifest()->getModuleByPath($callingfile);
|
||||||
foreach ($modules as $module) {
|
|
||||||
if (strpos($callingfile, realpath($module->getPath())) === 0) {
|
|
||||||
return $module;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,9 @@ namespace SilverStripe\Forms\HTMLEditor;
|
|||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
|
use SilverStripe\Core\Manifest\Module;
|
||||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
|
use SilverStripe\Dev\Deprecation;
|
||||||
use SilverStripe\i18n\i18n;
|
use SilverStripe\i18n\i18n;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
@ -191,13 +193,23 @@ class TinyMCEConfig extends HTMLEditorConfig
|
|||||||
* - themes
|
* - themes
|
||||||
* - skins
|
* - skins
|
||||||
*
|
*
|
||||||
* If left blank defaults to [admin dir]/tinyme
|
* Supports vendor/module:path
|
||||||
*
|
*
|
||||||
* @config
|
* @config
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $base_dir = null;
|
private static $base_dir = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra editor.css file paths.
|
||||||
|
*
|
||||||
|
* Supports vendor/module:path syntax
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $editor_css = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TinyMCE JS settings
|
* TinyMCE JS settings
|
||||||
*
|
*
|
||||||
@ -555,7 +567,7 @@ class TinyMCEConfig extends HTMLEditorConfig
|
|||||||
$settings['document_base_url'] = Director::absoluteBaseURL();
|
$settings['document_base_url'] = Director::absoluteBaseURL();
|
||||||
|
|
||||||
// https://www.tinymce.com/docs/api/class/tinymce.editormanager/#baseURL
|
// https://www.tinymce.com/docs/api/class/tinymce.editormanager/#baseURL
|
||||||
$tinyMCEBaseURL = $this->getAdminModule()->getResourceURL('thirdparty/tinymce');
|
$tinyMCEBaseURL = Controller::join_links(Director::baseURL(), $this->getTinyMCEPath());
|
||||||
$settings['baseURL'] = $tinyMCEBaseURL;
|
$settings['baseURL'] = $tinyMCEBaseURL;
|
||||||
|
|
||||||
// map all plugins to absolute urls for loading
|
// map all plugins to absolute urls for loading
|
||||||
@ -615,13 +627,15 @@ class TinyMCEConfig extends HTMLEditorConfig
|
|||||||
$editor = array();
|
$editor = array();
|
||||||
|
|
||||||
// Add standard editor.css
|
// Add standard editor.css
|
||||||
$editor[] = $this->getAdminModule()->getResourceURL('client/dist/styles/editor.css');
|
foreach ($this->config()->get('editor_css') as $editorCSS) {
|
||||||
|
$editor[] = Director::absoluteURL($this->resolvePath($editorCSS));
|
||||||
|
}
|
||||||
|
|
||||||
// Themed editor.css
|
// Themed editor.css
|
||||||
$themes = $this->config()->get('user_themes') ?: SSViewer::get_themes();
|
$themes = $this->config()->get('user_themes') ?: SSViewer::get_themes();
|
||||||
$themedEditor = ThemeResourceLoader::inst()->findThemedCSS('editor', $themes);
|
$themedEditor = ThemeResourceLoader::inst()->findThemedCSS('editor', $themes);
|
||||||
if ($themedEditor) {
|
if ($themedEditor) {
|
||||||
$editor[] = Director::absoluteURL($themedEditor, Director::BASE);
|
$editor[] = Director::absoluteURL($themedEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $editor;
|
return $editor;
|
||||||
@ -685,32 +699,46 @@ class TinyMCEConfig extends HTMLEditorConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string|false
|
* @return string
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function getTinyMCEPath()
|
public function getTinyMCEPath()
|
||||||
{
|
{
|
||||||
$configDir = static::config()->get('base_dir');
|
$configDir = static::config()->get('base_dir');
|
||||||
if ($configDir) {
|
if ($configDir) {
|
||||||
return $configDir;
|
return $this->resolvePath($configDir);
|
||||||
}
|
|
||||||
|
|
||||||
if ($admin = $this->getAdminModule()) {
|
|
||||||
return $admin->getRelativeResourcePath('thirdparty/tinymce');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception(sprintf(
|
throw new Exception(sprintf(
|
||||||
'If the silverstripe/admin module is not installed,
|
'If the silverstripe/admin module is not installed you must set the TinyMCE path in %s.base_dir',
|
||||||
you must set the TinyMCE path in %s.base_dir',
|
|
||||||
__CLASS__
|
__CLASS__
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \SilverStripe\Core\Manifest\Module
|
* @return Module
|
||||||
|
* @deprecated 4.0..5.0
|
||||||
*/
|
*/
|
||||||
protected function getAdminModule()
|
protected function getAdminModule()
|
||||||
{
|
{
|
||||||
|
Deprecation::notice('5.0', 'Set base_dir or editor_css config instead');
|
||||||
return ModuleLoader::getModule('silverstripe/admin');
|
return ModuleLoader::getModule('silverstripe/admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand resource path to a relative filesystem path
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function resolvePath($path)
|
||||||
|
{
|
||||||
|
if (preg_match('#(?<module>[^/]+/[^/]+)\s*:\s*(?<path>[^:]+)#', $path, $results)) {
|
||||||
|
$module = ModuleLoader::getModule($results['module']);
|
||||||
|
if ($module) {
|
||||||
|
return $module->getRelativeResourcePath($results['path']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\View;
|
|||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use SilverStripe\Core\Cache\CacheFactory;
|
use SilverStripe\Core\Cache\CacheFactory;
|
||||||
use SilverStripe\Core\Manifest\ManifestFileFinder;
|
use SilverStripe\Core\Manifest\ManifestFileFinder;
|
||||||
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class which builds a manifest of all themes (which is really just a directory called "templates")
|
* A class which builds a manifest of all themes (which is really just a directory called "templates")
|
||||||
@ -62,7 +63,7 @@ class ThemeManifest implements ThemeList
|
|||||||
* @param string $project Path to application code
|
* @param string $project Path to application code
|
||||||
* @param CacheFactory $cacheFactory Cache factory to generate backend cache with
|
* @param CacheFactory $cacheFactory Cache factory to generate backend cache with
|
||||||
*/
|
*/
|
||||||
public function __construct($base, $project, CacheFactory $cacheFactory = null)
|
public function __construct($base, $project = null, CacheFactory $cacheFactory = null)
|
||||||
{
|
{
|
||||||
$this->base = $base;
|
$this->base = $base;
|
||||||
$this->project = $project;
|
$this->project = $project;
|
||||||
@ -116,6 +117,9 @@ class ThemeManifest implements ThemeList
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \string[]
|
||||||
|
*/
|
||||||
public function getThemes()
|
public function getThemes()
|
||||||
{
|
{
|
||||||
return $this->themes;
|
return $this->themes;
|
||||||
@ -137,7 +141,11 @@ class ThemeManifest implements ThemeList
|
|||||||
));
|
));
|
||||||
|
|
||||||
$this->themes = [];
|
$this->themes = [];
|
||||||
$finder->find($this->base);
|
|
||||||
|
$modules = ModuleLoader::inst()->getManifest()->getModules();
|
||||||
|
foreach ($modules as $module) {
|
||||||
|
$finder->find($module->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->cache) {
|
if ($this->cache) {
|
||||||
$this->cache->set($this->cacheKey, $this->themes);
|
$this->cache->set($this->cacheKey, $this->themes);
|
||||||
@ -156,19 +164,20 @@ class ThemeManifest implements ThemeList
|
|||||||
if ($basename !== self::TEMPLATES_DIR) {
|
if ($basename !== self::TEMPLATES_DIR) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$dir = trim(substr(dirname($pathname), strlen($this->base)), '/\\');
|
||||||
// We only want part of the full path, so split into directories
|
$this->themes[] = "/".$dir;
|
||||||
$parts = explode('/', $pathname);
|
|
||||||
// Take the end (the part relative to base), except the very last directory
|
|
||||||
$themeParts = array_slice($parts, -$depth, $depth-1);
|
|
||||||
// Then join again
|
|
||||||
$path = '/'.implode('/', $themeParts);
|
|
||||||
|
|
||||||
// If this is in the project, add to beginning of list. Else add to end.
|
|
||||||
if ($themeParts && $themeParts[0] == $this->project) {
|
|
||||||
array_unshift($this->themes, $path);
|
|
||||||
} else {
|
|
||||||
array_push($this->themes, $path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the project
|
||||||
|
*
|
||||||
|
* @param string $project
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setProject($project)
|
||||||
|
{
|
||||||
|
$this->project = $project;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,11 @@ class ThemeResourceLoader
|
|||||||
*/
|
*/
|
||||||
private static $instance;
|
private static $instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base path of the application
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $base;
|
protected $base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,7 +206,6 @@ class ThemeResourceLoader
|
|||||||
|
|
||||||
$tail = array_pop($parts);
|
$tail = array_pop($parts);
|
||||||
$head = implode('/', $parts);
|
$head = implode('/', $parts);
|
||||||
|
|
||||||
$themePaths = $this->getThemePaths($themes);
|
$themePaths = $this->getThemePaths($themes);
|
||||||
foreach ($themePaths as $themePath) {
|
foreach ($themePaths as $themePath) {
|
||||||
// Join path
|
// Join path
|
||||||
|
@ -5,10 +5,12 @@ namespace SilverStripe\i18n\Data;
|
|||||||
use SilverStripe\Core\Config\Configurable;
|
use SilverStripe\Core\Config\Configurable;
|
||||||
use SilverStripe\Core\Injector\Injectable;
|
use SilverStripe\Core\Injector\Injectable;
|
||||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
|
use SilverStripe\Core\Manifest\ModuleManifest;
|
||||||
use SilverStripe\Core\Resettable;
|
use SilverStripe\Core\Resettable;
|
||||||
use SilverStripe\i18n\i18n;
|
use SilverStripe\i18n\i18n;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
use SilverStripe\View\ThemeResourceLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
|
use SilverStripe\Dev\Deprecation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data sources for localisation strings. I.e. yml files stored
|
* Data sources for localisation strings. I.e. yml files stored
|
||||||
@ -34,43 +36,21 @@ class Sources implements Resettable
|
|||||||
*/
|
*/
|
||||||
public function getSortedModules()
|
public function getSortedModules()
|
||||||
{
|
{
|
||||||
// Get list of module => path pairs, and then just the names
|
$i18nOrder = Sources::config()->uninherited('module_priority');
|
||||||
$modules = ModuleLoader::inst()->getManifest()->getModules();
|
$sortedModules = [];
|
||||||
$moduleNames = array_keys($modules);
|
if ($i18nOrder) {
|
||||||
|
Deprecation::notice('5.0', sprintf(
|
||||||
// Remove the "project" module from the list - we'll add it back specially later if needed
|
'%s.module_priority is deprecated. Use %s.module_priority instead.',
|
||||||
global $project;
|
__CLASS__,
|
||||||
if (($idx = array_search($project, $moduleNames)) !== false) {
|
ModuleManifest::class
|
||||||
array_splice($moduleNames, $idx, 1);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the order from the config system (lowest to highest)
|
foreach (ModuleLoader::inst()->getManifest()->getModules() as $module) {
|
||||||
$order = Sources::config()->uninherited('module_priority');
|
$sortedModules[$module->getName()] = $module->getPath();
|
||||||
|
};
|
||||||
|
|
||||||
// Find all modules that don't have their order specified by the config system
|
return $sortedModules;
|
||||||
$unspecified = array_diff($moduleNames, $order);
|
|
||||||
|
|
||||||
// If the placeholder "other_modules" exists in the order array, replace it by the unspecified modules
|
|
||||||
if (($idx = array_search('other_modules', $order)) !== false) {
|
|
||||||
array_splice($order, $idx, 1, $unspecified);
|
|
||||||
} else {
|
|
||||||
// Otherwise just jam them on the front
|
|
||||||
array_splice($order, 0, 0, $unspecified);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put the project at end (highest priority)
|
|
||||||
if (!in_array($project, $order)) {
|
|
||||||
$order[] = $project;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sortedModulePaths = array();
|
|
||||||
foreach ($order as $module) {
|
|
||||||
if (isset($modules[$module])) {
|
|
||||||
$sortedModulePaths[$module] = $modules[$module]->getPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$sortedModulePaths = array_reverse($sortedModulePaths, true);
|
|
||||||
return $sortedModulePaths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\i18n\i18n;
|
use SilverStripe\i18n\i18n;
|
||||||
|
use SilverStripe\Core\Manifest\ModuleManifest;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// HELPER FUNCTIONS
|
// HELPER FUNCTIONS
|
||||||
@ -35,12 +36,7 @@ function singleton($className)
|
|||||||
|
|
||||||
function project()
|
function project()
|
||||||
{
|
{
|
||||||
global $project;
|
return ModuleManifest::config()->get('project');
|
||||||
// Set default project
|
|
||||||
if (empty($project) && file_exists(BASE_PATH . '/mysite')) {
|
|
||||||
$project = 'mysite';
|
|
||||||
}
|
|
||||||
return $project;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
97
tests/php/Core/Manifest/PrioritySorterTest.php
Normal file
97
tests/php/Core/Manifest/PrioritySorterTest.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\Core\Tests\Manifest;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Manifest\PrioritySorter;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
|
||||||
|
class PrioritySorterTest extends SapphireTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var PrioritySorter
|
||||||
|
*/
|
||||||
|
protected $sorter;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$modules = [
|
||||||
|
'module/one' => 'I am module one',
|
||||||
|
'module/two' => 'I am module two',
|
||||||
|
'module/three' => 'I am module three',
|
||||||
|
'module/four' => 'I am module four',
|
||||||
|
'module/five' => 'I am module five',
|
||||||
|
];
|
||||||
|
$this->sorter = new PrioritySorter($modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModuleSortingWithNoVarsAndNoRest()
|
||||||
|
{
|
||||||
|
$this->sorter->setPriorities([
|
||||||
|
'module/three',
|
||||||
|
'module/one',
|
||||||
|
'module/two',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$result = $this->sorter->getSortedList();
|
||||||
|
$keys = array_keys($result);
|
||||||
|
$this->assertEquals('module/three', $keys[0]);
|
||||||
|
$this->assertEquals('module/one', $keys[1]);
|
||||||
|
$this->assertEquals('module/two', $keys[2]);
|
||||||
|
$this->assertEquals('module/four', $keys[3]);
|
||||||
|
$this->assertEquals('module/five', $keys[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModuleSortingWithVarsAndNoRest()
|
||||||
|
{
|
||||||
|
$this->sorter->setPriorities([
|
||||||
|
'module/three',
|
||||||
|
'$project',
|
||||||
|
])
|
||||||
|
->setVariable('$project', 'module/one');
|
||||||
|
|
||||||
|
$result = $this->sorter->getSortedList();
|
||||||
|
$keys = array_keys($result);
|
||||||
|
$this->assertEquals('module/three', $keys[0]);
|
||||||
|
$this->assertEquals('module/one', $keys[1]);
|
||||||
|
$this->assertEquals('module/two', $keys[2]);
|
||||||
|
$this->assertEquals('module/four', $keys[3]);
|
||||||
|
$this->assertEquals('module/five', $keys[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModuleSortingWithNoVarsAndWithRest()
|
||||||
|
{
|
||||||
|
$this->sorter->setPriorities([
|
||||||
|
'module/two',
|
||||||
|
'$other_modules',
|
||||||
|
'module/four',
|
||||||
|
])
|
||||||
|
->setRestKey('$other_modules');
|
||||||
|
$result = $this->sorter->getSortedList();
|
||||||
|
$keys = array_keys($result);
|
||||||
|
$this->assertEquals('module/two', $keys[0]);
|
||||||
|
$this->assertEquals('module/one', $keys[1]);
|
||||||
|
$this->assertEquals('module/three', $keys[2]);
|
||||||
|
$this->assertEquals('module/five', $keys[3]);
|
||||||
|
$this->assertEquals('module/four', $keys[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModuleSortingWithVarsAndWithRest()
|
||||||
|
{
|
||||||
|
$this->sorter->setPriorities([
|
||||||
|
'module/two',
|
||||||
|
'other_modules',
|
||||||
|
'$project',
|
||||||
|
])
|
||||||
|
->setVariable('$project', 'module/four')
|
||||||
|
->setRestKey('other_modules');
|
||||||
|
|
||||||
|
$result = $this->sorter->getSortedList();
|
||||||
|
$keys = array_keys($result);
|
||||||
|
$this->assertEquals('module/two', $keys[0]);
|
||||||
|
$this->assertEquals('module/one', $keys[1]);
|
||||||
|
$this->assertEquals('module/three', $keys[2]);
|
||||||
|
$this->assertEquals('module/five', $keys[3]);
|
||||||
|
$this->assertEquals('module/four', $keys[4]);
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Core\Tests\Manifest;
|
namespace SilverStripe\Core\Tests\Manifest;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
use SilverStripe\View\ThemeResourceLoader;
|
use SilverStripe\View\ThemeResourceLoader;
|
||||||
use SilverStripe\View\ThemeManifest;
|
use SilverStripe\View\ThemeManifest;
|
||||||
use SilverStripe\Dev\SapphireTest;
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\Core\Manifest\ModuleManifest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for the {@link TemplateLoader} class.
|
* Tests for the {@link TemplateLoader} class.
|
||||||
@ -35,14 +37,29 @@ class ThemeResourceLoaderTest extends SapphireTest
|
|||||||
|
|
||||||
// Fake project root
|
// Fake project root
|
||||||
$this->base = dirname(__FILE__) . '/fixtures/templatemanifest';
|
$this->base = dirname(__FILE__) . '/fixtures/templatemanifest';
|
||||||
|
ModuleManifest::config()->set('module_priority', ['$project', '$other_modules']);
|
||||||
|
ModuleManifest::config()->set('project', 'myproject');
|
||||||
|
|
||||||
|
$moduleManifest = new ModuleManifest($this->base);
|
||||||
|
$moduleManifest->init();
|
||||||
|
$moduleManifest->sort();
|
||||||
|
ModuleLoader::inst()->pushManifest($moduleManifest);
|
||||||
|
|
||||||
// New ThemeManifest for that root
|
// New ThemeManifest for that root
|
||||||
$this->manifest = new ThemeManifest($this->base, 'myproject');
|
$this->manifest = new ThemeManifest($this->base);
|
||||||
|
$this->manifest->setProject('myproject');
|
||||||
$this->manifest->init();
|
$this->manifest->init();
|
||||||
// New Loader for that root
|
// New Loader for that root
|
||||||
$this->loader = new ThemeResourceLoader($this->base);
|
$this->loader = new ThemeResourceLoader($this->base);
|
||||||
$this->loader->addSet('$default', $this->manifest);
|
$this->loader->addSet('$default', $this->manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
ModuleLoader::inst()->popManifest();
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that 'main' and 'Layout' templates are loaded from module
|
* Test that 'main' and 'Layout' templates are loaded from module
|
||||||
*/
|
*/
|
||||||
|
@ -115,7 +115,9 @@ class DeprecationTest extends SapphireTest
|
|||||||
|
|
||||||
protected function callThatOriginatesFromFramework()
|
protected function callThatOriginatesFromFramework()
|
||||||
{
|
{
|
||||||
$this->assertEquals('silverstripe/framework', TestDeprecation::get_module()->getName());
|
$module = TestDeprecation::get_module();
|
||||||
|
$this->assertNotNull($module);
|
||||||
|
$this->assertEquals('silverstripe/framework', $module->getName());
|
||||||
$this->assertNull(Deprecation::notice('2.0', 'Deprecation test passed'));
|
$this->assertNull(Deprecation::notice('2.0', 'Deprecation test passed'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ class HTMLEditorConfigTest extends SapphireTest
|
|||||||
// Plugin specified with standard location
|
// Plugin specified with standard location
|
||||||
$this->assertContains('plugin4', array_keys($plugins));
|
$this->assertContains('plugin4', array_keys($plugins));
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'/subdir/silverstripe-admin/thirdparty/tinymce/plugins/plugin4/plugin.min.js',
|
'/subdir/test/thirdparty/tinymce/plugins/plugin4/plugin.min.js',
|
||||||
$plugins['plugin4']
|
$plugins['plugin4']
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -109,12 +109,15 @@ class HTMLEditorConfigTest extends SapphireTest
|
|||||||
|
|
||||||
public function testPluginCompression()
|
public function testPluginCompression()
|
||||||
{
|
{
|
||||||
|
// This test requires the real tiny_mce_gzip.php file
|
||||||
$module = ModuleLoader::inst()->getManifest()->getModule('silverstripe/admin');
|
$module = ModuleLoader::inst()->getManifest()->getModule('silverstripe/admin');
|
||||||
if (!$module) {
|
if (!$module) {
|
||||||
$this->markTestSkipped('No silverstripe/admin module loaded');
|
$this->markTestSkipped('No silverstripe/admin module loaded');
|
||||||
}
|
}
|
||||||
TinyMCEConfig::config()->remove('base_dir');
|
TinyMCEConfig::config()->set('base_dir', 'silverstripe/admin:thirdparty/tinymce');
|
||||||
Config::modify()->set(Director::class, 'alternate_base_url', 'http://mysite.com/subdir');
|
Config::modify()->set(Director::class, 'alternate_base_url', 'http://mysite.com/subdir');
|
||||||
|
|
||||||
|
// Build new config
|
||||||
$c = new TinyMCEConfig();
|
$c = new TinyMCEConfig();
|
||||||
$c->setTheme('modern');
|
$c->setTheme('modern');
|
||||||
$c->setOption('language', 'es');
|
$c->setOption('language', 'es');
|
||||||
|
Loading…
Reference in New Issue
Block a user