mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge branch '4.3' into 4
This commit is contained in:
commit
64c2938c96
@ -959,6 +959,9 @@ warnings:
|
|||||||
'Object':
|
'Object':
|
||||||
message: 'Replaced with traits'
|
message: 'Replaced with traits'
|
||||||
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#object-replace'
|
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#object-replace'
|
||||||
|
'SS_Object':
|
||||||
|
message: 'Replaced with traits'
|
||||||
|
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#object-replace'
|
||||||
'SS_Log':
|
'SS_Log':
|
||||||
message: 'Replaced with a PSR-3 logger'
|
message: 'Replaced with a PSR-3 logger'
|
||||||
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#psr3-logging'
|
url: 'https://docs.silverstripe.org/en/4/changelogs/4.0.0#psr3-logging'
|
||||||
|
@ -55,15 +55,35 @@ coding conventions.
|
|||||||
|
|
||||||
A pattern library is a collection of user interface design elements, this helps developers and designers collaborate and to provide a quick preview of elements as they were intended without the need to build an entire interface to see it.
|
A pattern library is a collection of user interface design elements, this helps developers and designers collaborate and to provide a quick preview of elements as they were intended without the need to build an entire interface to see it.
|
||||||
Components built in React and used by the CMS are actively being added to the pattern library.
|
Components built in React and used by the CMS are actively being added to the pattern library.
|
||||||
|
The pattern library can be used to preview React components without including them in the SilverStripe CMS.
|
||||||
|
|
||||||
To access the pattern library, starting from your project root:
|
### Viewing the latest pattern library
|
||||||
|
|
||||||
```
|
The easiest way to access the pattern library is to view it online. The pattern library for the latest SilverStripe 4 development branch is automatically built and deployed. Note that this may include new components that are not yet available in a stable release.
|
||||||
cd vendor/silverstripe/admin && yarn pattern-lib
|
|
||||||
|
[Browse the SilverStripe pattern library online](https://silverstripe.github.io/silverstripe-admin).
|
||||||
|
|
||||||
|
### Running the pattern library
|
||||||
|
|
||||||
|
If you're developing a new React component, running the pattern library locally is a good way to interact with it.
|
||||||
|
|
||||||
|
The pattern library is built from the `silverstripe/admin` module, but it also requires `silverstripe/asset-admin`, `silversrtipe/cms` and `silverstripe/campaign-admin`.
|
||||||
|
|
||||||
|
To run the pattern library locally, you'll need a SilverStripe project based on `silverstripe/recipe-cms` and `yarn` installed locally. The pattern library requires the JS source files so you'll need to use the `--prefer-source` flag when installing your dependencies with Composer.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer install --prefer-source
|
||||||
|
(cd vendor/silverstripe/asset-admin && yarn install)
|
||||||
|
(cd vendor/silverstripe/campaign-admin && yarn install)
|
||||||
|
(cd vendor/silverstripe/cms && yarn install)
|
||||||
|
cd vendor/silverstripe/admin && yarn install && yarn pattern-lib
|
||||||
```
|
```
|
||||||
|
|
||||||
Then browse to `http://localhost:6006/`
|
The pattern library will be available at [http://localhost:6006](http://localhost:6006). The JS source files will be watched, so every time you make a change to a JavaScript file, the pattern library will automatically update itself.
|
||||||
|
|
||||||
|
If you want to build a static version of the pattern library, you can replace `yarn pattern-lib` with `yarn build-storybook`. This will output the pattern library files to a `storybook-static` folder.
|
||||||
|
|
||||||
|
The SilverStripe pattern library is built using the [StoryBook JS library](https://storybook.js.org/). You can read the StoryBook documentation to learn about more advanced features and customisation options.
|
||||||
|
|
||||||
## The Admin URL
|
## The Admin URL
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
- Take care with `stageChildren()` overrides. `Hierarchy::numChildren() ` results will only make use of `stageChildren()` customisations that are applied to the base class and don't include record-specific behaviour.
|
- Take care with `stageChildren()` overrides. `Hierarchy::numChildren() ` results will only make use of `stageChildren()` customisations that are applied to the base class and don't include record-specific behaviour.
|
||||||
- New React-based search UI for the CMS, Asset-Admin, GridFields and ModelAdmins.
|
- New React-based search UI for the CMS, Asset-Admin, GridFields and ModelAdmins.
|
||||||
- A new `GridFieldLazyLoader` component can be added to `GridField`. This will delay the fetching of data until the user access the container Tab of the GridField.
|
- A new `GridFieldLazyLoader` component can be added to `GridField`. This will delay the fetching of data until the user access the container Tab of the GridField.
|
||||||
|
- `SilverStripe\VersionedAdmin\Controllers\CMSPageHistoryViewerController` is now the default CMS history controller and `SilverStripe\CMS\Controllers\CMSPageHistoryController` has been deprecated.
|
||||||
|
|
||||||
## Upgrading {#upgrading}
|
## Upgrading {#upgrading}
|
||||||
|
|
||||||
@ -25,6 +26,12 @@ To enable the legacy search API on a `GridFieldFilterHeader`, you can either:
|
|||||||
* set the `useLegacyFilterHeader` property to `true`,
|
* set the `useLegacyFilterHeader` property to `true`,
|
||||||
* or pass `true` to the first argument of its constructor.
|
* or pass `true` to the first argument of its constructor.
|
||||||
|
|
||||||
|
To force the legacy search API on all instances of `GridFieldFilterHeader`, you can set it in your [configuration file](../../configuration):
|
||||||
|
```yml
|
||||||
|
SilverStripe\Forms\GridField\GridFieldFilterHeader:
|
||||||
|
force_legacy: true
|
||||||
|
```
|
||||||
|
|
||||||
```php
|
```php
|
||||||
public function getCMSFields()
|
public function getCMSFields()
|
||||||
{
|
{
|
||||||
@ -41,3 +48,23 @@ public function getCMSFields()
|
|||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Keep using the legacy `CMSPageHistoryController`
|
||||||
|
|
||||||
|
To keep using the old CMS history controller for every page type, add the following entry to your YML config.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
SilverStripe\Core\Injector\Injector:
|
||||||
|
SilverStripe\CMS\Controllers\CMSPageHistoryController:
|
||||||
|
class: SilverStripe\CMS\Controllers\CMSPageHistoryController
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to use both CMS history controllers in different contexts, you can implement your own _Factory_ class.
|
||||||
|
```yml
|
||||||
|
SilverStripe\Core\Injector\Injector:
|
||||||
|
SilverStripe\CMS\Controllers\CMSPageHistoryController:
|
||||||
|
factory:
|
||||||
|
App\MySite\MyCustomControllerFactory
|
||||||
|
```
|
||||||
|
|
||||||
|
[Implementing a _Factory_ with the Injector](/developer_guides/extending/injector/#factories)
|
||||||
|
@ -564,6 +564,7 @@ class Convert
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn a memory string, such as 512M into an actual number of bytes.
|
* Turn a memory string, such as 512M into an actual number of bytes.
|
||||||
|
* Preserves integer values like "1024" or "-1"
|
||||||
*
|
*
|
||||||
* @param string $memString A memory limit string, such as "64M"
|
* @param string $memString A memory limit string, such as "64M"
|
||||||
* @return float
|
* @return float
|
||||||
@ -573,7 +574,7 @@ class Convert
|
|||||||
// Remove non-unit characters from the size
|
// Remove non-unit characters from the size
|
||||||
$unit = preg_replace('/[^bkmgtpezy]/i', '', $memString);
|
$unit = preg_replace('/[^bkmgtpezy]/i', '', $memString);
|
||||||
// Remove non-numeric characters from the size
|
// Remove non-numeric characters from the size
|
||||||
$size = preg_replace('/[^0-9\.]/', '', $memString);
|
$size = preg_replace('/[^0-9\.\-]/', '', $memString);
|
||||||
|
|
||||||
if ($unit) {
|
if ($unit) {
|
||||||
// Find the position of the unit in the ordered string which is the power
|
// Find the position of the unit in the ordered string which is the power
|
||||||
|
@ -13,6 +13,7 @@ use SilverStripe\Core\ClassInfo;
|
|||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Core\Environment;
|
use SilverStripe\Core\Environment;
|
||||||
use SilverStripe\Dev\Deprecation;
|
use SilverStripe\Dev\Deprecation;
|
||||||
|
use SilverStripe\ORM\DataObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple injection manager that manages creating objects and injecting
|
* A simple injection manager that manages creating objects and injecting
|
||||||
@ -581,6 +582,14 @@ class Injector implements ContainerInterface
|
|||||||
$constructorParams = $spec['constructor'];
|
$constructorParams = $spec['constructor'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're dealing with a DataObject singleton without specific constructor params, pass through Singleton
|
||||||
|
// flag as second argument
|
||||||
|
if ((!$type || $type !== self::PROTOTYPE)
|
||||||
|
&& empty($constructorParams)
|
||||||
|
&& is_subclass_of($class, DataObject::class)) {
|
||||||
|
$constructorParams = array(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
$factory = isset($spec['factory']) ? $this->get($spec['factory']) : $this->getObjectCreator();
|
$factory = isset($spec['factory']) ? $this->get($spec['factory']) : $this->getObjectCreator();
|
||||||
$object = $factory->create($class, $constructorParams);
|
$object = $factory->create($class, $constructorParams);
|
||||||
|
|
||||||
|
@ -113,11 +113,13 @@ class GridField extends FormField
|
|||||||
protected $readonlyComponents = [
|
protected $readonlyComponents = [
|
||||||
GridField_ActionMenu::class,
|
GridField_ActionMenu::class,
|
||||||
GridFieldConfig_RecordViewer::class,
|
GridFieldConfig_RecordViewer::class,
|
||||||
|
GridFieldButtonRow::class,
|
||||||
GridFieldDataColumns::class,
|
GridFieldDataColumns::class,
|
||||||
GridFieldDetailForm::class,
|
GridFieldDetailForm::class,
|
||||||
GridFieldLazyLoader::class,
|
GridFieldLazyLoader::class,
|
||||||
GridFieldPageCount::class,
|
GridFieldPageCount::class,
|
||||||
GridFieldPaginator::class,
|
GridFieldPaginator::class,
|
||||||
|
GridFieldFilterHeader::class,
|
||||||
GridFieldSortableHeader::class,
|
GridFieldSortableHeader::class,
|
||||||
GridFieldToolbarHeader::class,
|
GridFieldToolbarHeader::class,
|
||||||
GridFieldViewButton::class,
|
GridFieldViewButton::class,
|
||||||
@ -241,16 +243,22 @@ class GridField extends FormField
|
|||||||
{
|
{
|
||||||
$copy = clone $this;
|
$copy = clone $this;
|
||||||
$copy->setReadonly(true);
|
$copy->setReadonly(true);
|
||||||
|
$copyConfig = $copy->getConfig();
|
||||||
|
|
||||||
// get the whitelist for allowable readonly components
|
// get the whitelist for allowable readonly components
|
||||||
$allowedComponents = $this->getReadonlyComponents();
|
$allowedComponents = $this->getReadonlyComponents();
|
||||||
foreach ($this->getConfig()->getComponents() as $component) {
|
foreach ($this->getConfig()->getComponents() as $component) {
|
||||||
// if a component doesn't exist, remove it from the readonly version.
|
// if a component doesn't exist, remove it from the readonly version.
|
||||||
if (!in_array(get_class($component), $allowedComponents)) {
|
if (!in_array(get_class($component), $allowedComponents)) {
|
||||||
$copy->getConfig()->removeComponent($component);
|
$copyConfig->removeComponent($component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As the edit button may have been removed, add a view button if it doesn't have one
|
||||||
|
if (!$copyConfig->getComponentByType(GridFieldViewButton::class)) {
|
||||||
|
$copyConfig->addComponent(new GridFieldViewButton);
|
||||||
|
}
|
||||||
|
|
||||||
return $copy;
|
return $copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,6 +298,18 @@ class GridField extends FormField
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $readonly
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setReadonly($readonly)
|
||||||
|
{
|
||||||
|
parent::setReadonly($readonly);
|
||||||
|
$this->getState()->Readonly = $readonly;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ArrayList
|
* @return ArrayList
|
||||||
*/
|
*/
|
||||||
@ -1009,6 +1029,9 @@ class GridField extends FormField
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($request->getHeader('X-Pjax') === 'CurrentField') {
|
if ($request->getHeader('X-Pjax') === 'CurrentField') {
|
||||||
|
if ($this->getState()->Readonly === true) {
|
||||||
|
$this->performDisabledTransformation();
|
||||||
|
}
|
||||||
return $this->FieldHolder();
|
return $this->FieldHolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ use LogicException;
|
|||||||
use SilverStripe\Admin\LeftAndMain;
|
use SilverStripe\Admin\LeftAndMain;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\HTTPResponse;
|
use SilverStripe\Control\HTTPResponse;
|
||||||
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
use SilverStripe\Dev\Deprecation;
|
use SilverStripe\Dev\Deprecation;
|
||||||
use SilverStripe\Forms\FieldGroup;
|
use SilverStripe\Forms\FieldGroup;
|
||||||
@ -43,6 +44,16 @@ class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvi
|
|||||||
*/
|
*/
|
||||||
public $useLegacyFilterHeader = false;
|
public $useLegacyFilterHeader = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces all filter components to revert to displaying the legacy
|
||||||
|
* table header style rather than the react driven search box
|
||||||
|
*
|
||||||
|
* @deprecated 4.3.0:5.0.0 Will be removed in 5.0
|
||||||
|
* @config
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $force_legacy = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \SilverStripe\ORM\Search\SearchContext
|
* @var \SilverStripe\ORM\Search\SearchContext
|
||||||
*/
|
*/
|
||||||
@ -76,7 +87,7 @@ class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $useLegacy
|
* @param bool $useLegacy This will be removed in 5.0
|
||||||
* @param callable|null $updateSearchContext This will be removed in 5.0
|
* @param callable|null $updateSearchContext This will be removed in 5.0
|
||||||
* @param callable|null $updateSearchForm This will be removed in 5.0
|
* @param callable|null $updateSearchForm This will be removed in 5.0
|
||||||
*/
|
*/
|
||||||
@ -85,7 +96,7 @@ class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvi
|
|||||||
callable $updateSearchContext = null,
|
callable $updateSearchContext = null,
|
||||||
callable $updateSearchForm = null
|
callable $updateSearchForm = null
|
||||||
) {
|
) {
|
||||||
$this->useLegacyFilterHeader = $useLegacy;
|
$this->useLegacyFilterHeader = Config::inst()->get(self::class, 'force_legacy') || $useLegacy;
|
||||||
$this->updateSearchContextCallback = $updateSearchContext;
|
$this->updateSearchContextCallback = $updateSearchContext;
|
||||||
$this->updateSearchFormCallback = $updateSearchForm;
|
$this->updateSearchFormCallback = $updateSearchForm;
|
||||||
}
|
}
|
||||||
@ -154,7 +165,7 @@ class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvi
|
|||||||
* If the GridField has a filterable datalist, return an array of actions
|
* If the GridField has a filterable datalist, return an array of actions
|
||||||
*
|
*
|
||||||
* @param GridField $gridField
|
* @param GridField $gridField
|
||||||
* @return array
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||||
{
|
{
|
||||||
@ -163,14 +174,13 @@ class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvi
|
|||||||
}
|
}
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldFilterHeader;
|
$state = $gridField->State->GridFieldFilterHeader;
|
||||||
|
$state->Columns = null;
|
||||||
if ($actionName === 'filter') {
|
if ($actionName === 'filter') {
|
||||||
if (isset($data['filter'][$gridField->getName()])) {
|
if (isset($data['filter'][$gridField->getName()])) {
|
||||||
foreach ($data['filter'][$gridField->getName()] as $key => $filter) {
|
foreach ($data['filter'][$gridField->getName()] as $key => $filter) {
|
||||||
$state->Columns->$key = $filter;
|
$state->Columns->$key = $filter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($actionName === 'reset') {
|
|
||||||
$state->Columns = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,12 +203,10 @@ class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvi
|
|||||||
|
|
||||||
$filterArguments = $columns->toArray();
|
$filterArguments = $columns->toArray();
|
||||||
$dataListClone = clone($dataList);
|
$dataListClone = clone($dataList);
|
||||||
foreach ($filterArguments as $columnName => $value) {
|
$results = $this->getSearchContext($gridField)
|
||||||
if ($dataList->canFilterBy($columnName) && $value) {
|
->getQuery($filterArguments, false, false, $dataListClone);
|
||||||
$dataListClone = $dataListClone->filter($columnName . ':PartialMatch', $value);
|
|
||||||
}
|
return $results;
|
||||||
}
|
|
||||||
return $dataListClone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -337,9 +345,11 @@ class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvi
|
|||||||
$field->addExtraClass('stacked');
|
$field->addExtraClass('stacked');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$name = $gridField->Title ?: singleton($gridField->getModelClass())->i18n_plural_name();
|
||||||
|
|
||||||
$this->searchForm = $form = new Form(
|
$this->searchForm = $form = new Form(
|
||||||
$gridField,
|
$gridField,
|
||||||
"SearchForm",
|
$name . "SearchForm",
|
||||||
$searchFields,
|
$searchFields,
|
||||||
new FieldList()
|
new FieldList()
|
||||||
);
|
);
|
||||||
|
@ -101,6 +101,7 @@ class GridField_FormAction extends FormAction
|
|||||||
// will strip it from the requests
|
// will strip it from the requests
|
||||||
'name' => 'action_gridFieldAlterAction' . '?' . http_build_query($actionData),
|
'name' => 'action_gridFieldAlterAction' . '?' . http_build_query($actionData),
|
||||||
'data-url' => $this->gridField->Link(),
|
'data-url' => $this->gridField->Link(),
|
||||||
|
'type' => "button",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@ abstract class HTMLEditorConfig
|
|||||||
// Create new instance if unconfigured
|
// Create new instance if unconfigured
|
||||||
if (!isset(self::$configs[$identifier])) {
|
if (!isset(self::$configs[$identifier])) {
|
||||||
self::$configs[$identifier] = static::create();
|
self::$configs[$identifier] = static::create();
|
||||||
|
self::$configs[$identifier]->setOption('editorIdentifier', $identifier);
|
||||||
}
|
}
|
||||||
return self::$configs[$identifier];
|
return self::$configs[$identifier];
|
||||||
}
|
}
|
||||||
@ -98,6 +99,7 @@ abstract class HTMLEditorConfig
|
|||||||
{
|
{
|
||||||
if ($config) {
|
if ($config) {
|
||||||
self::$configs[$identifier] = $config;
|
self::$configs[$identifier] = $config;
|
||||||
|
self::$configs[$identifier]->setOption('editorIdentifier', $identifier);
|
||||||
} else {
|
} else {
|
||||||
unset(self::$configs[$identifier]);
|
unset(self::$configs[$identifier]);
|
||||||
}
|
}
|
||||||
|
@ -130,11 +130,13 @@ class TinyMCECombinedGenerator implements TinyMCEScriptGenerator, Flushable
|
|||||||
|
|
||||||
// Register vars for config
|
// Register vars for config
|
||||||
$baseDirJS = Convert::raw2js(Director::absoluteBaseURL());
|
$baseDirJS = Convert::raw2js(Director::absoluteBaseURL());
|
||||||
|
$name = Convert::raw2js($this->checkName($config));
|
||||||
$buffer = [];
|
$buffer = [];
|
||||||
$buffer[] = <<<SCRIPT
|
$buffer[] = <<<SCRIPT
|
||||||
(function() {
|
(function() {
|
||||||
var baseTag = window.document.getElementsByTagName('base');
|
var baseTag = window.document.getElementsByTagName('base');
|
||||||
var baseURL = baseTag.length ? baseTag[0].baseURI : '$baseDirJS';
|
var baseURL = baseTag.length ? baseTag[0].baseURI : '$baseDirJS';
|
||||||
|
var editorIdentifier = '$name';
|
||||||
SCRIPT;
|
SCRIPT;
|
||||||
$buffer[] = <<<SCRIPT
|
$buffer[] = <<<SCRIPT
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -94,7 +94,7 @@ class SingleLookupField extends SingleSelectField
|
|||||||
return $label;
|
return $label;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $value;
|
return parent::Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -576,6 +576,7 @@ XML
|
|||||||
public function memString2BytesProvider()
|
public function memString2BytesProvider()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
['-1', (float)-1],
|
||||||
['2048', (float)(2 * 1024)],
|
['2048', (float)(2 * 1024)],
|
||||||
['2k', (float)(2 * 1024)],
|
['2k', (float)(2 * 1024)],
|
||||||
['512M', (float)(512 * 1024 * 1024)],
|
['512M', (float)(512 * 1024 * 1024)],
|
||||||
|
@ -9,6 +9,13 @@ use SilverStripe\Forms\HTMLEditor\TinyMCEConfig;
|
|||||||
|
|
||||||
class TinyMCEConfigTest extends SapphireTest
|
class TinyMCEConfigTest extends SapphireTest
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public function testEditorIdentifier()
|
||||||
|
{
|
||||||
|
$config = TinyMCEConfig::get('myconfig');
|
||||||
|
$this->assertEquals('myconfig', $config->getOption('editorIdentifier'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that all TinyMCEConfig.tinymce_lang are valid
|
* Ensure that all TinyMCEConfig.tinymce_lang are valid
|
||||||
*/
|
*/
|
||||||
|
@ -66,6 +66,51 @@ class DataObjectTest extends SapphireTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideSingletons
|
||||||
|
*/
|
||||||
|
public function testSingleton($inst, $defaultValue, $altDefaultValue)
|
||||||
|
{
|
||||||
|
$inst = $inst();
|
||||||
|
// Test that populateDefaults() isn't called on singletons
|
||||||
|
// which can lead to SQL errors during build, and endless loops
|
||||||
|
if ($defaultValue) {
|
||||||
|
$this->assertEquals($defaultValue, $inst->MyFieldWithDefault);
|
||||||
|
} else {
|
||||||
|
$this->assertEmpty($inst->MyFieldWithDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($altDefaultValue) {
|
||||||
|
$this->assertEquals($altDefaultValue, $inst->MyFieldWithAltDefault);
|
||||||
|
} else {
|
||||||
|
$this->assertEmpty($inst->MyFieldWithAltDefault);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideSingletons()
|
||||||
|
{
|
||||||
|
// because PHPUnit evalutes test providers *before* setUp methods
|
||||||
|
// any extensions added in the setUp methods won't be available
|
||||||
|
// we must return closures to generate the arguments at run time
|
||||||
|
return array(
|
||||||
|
'create() static method' => array(function () {
|
||||||
|
return DataObjectTest\Fixture::create();
|
||||||
|
}, 'Default Value', 'Default Value'),
|
||||||
|
'New object creation' => array(function () {
|
||||||
|
return new DataObjectTest\Fixture();
|
||||||
|
}, 'Default Value', 'Default Value'),
|
||||||
|
'singleton() function' => array(function () {
|
||||||
|
return singleton(DataObjectTest\Fixture::class);
|
||||||
|
}, null, null),
|
||||||
|
'singleton() static method' => array(function () {
|
||||||
|
return DataObjectTest\Fixture::singleton();
|
||||||
|
}, null, null),
|
||||||
|
'Manual constructor args' => array(function () {
|
||||||
|
return new DataObjectTest\Fixture(null, true);
|
||||||
|
}, null, null),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testDb()
|
public function testDb()
|
||||||
{
|
{
|
||||||
$schema = DataObject::getSchema();
|
$schema = DataObject::getSchema();
|
||||||
|
Loading…
Reference in New Issue
Block a user