Merge branch '4.0' into 4

This commit is contained in:
Daniel Hensby 2017-12-05 12:14:22 +00:00
commit eb55c27124
No known key found for this signature in database
GPG Key ID: B00D1E9767F0B06E
49 changed files with 321 additions and 75 deletions

View File

@ -1,7 +1,17 @@
inherit: true
build:
environment:
variables:
# Must match actual branch, not alias. E.g. 4.x-dev rather than 4.1.x-dev for 4 branch, but 4.0.x-dev for 4.0 branch
COMPOSER_ROOT_VERSION: 4.x-dev
nodes:
analysis:
tests:
override: [php-scrutinizer-run]
filter:
excluded_paths:
- thirdparty/*
- parsers/*
- docs/*
- images/*
paths:
- src/*
- tests/*

View File

@ -42,6 +42,11 @@ matrix:
- DB=MYSQL
- PDO=1
- PHPUNIT_TEST=framework
- php: nightly
env:
- DB=MYSQL
- PDO=1
- PHPUNIT_TEST=framework
- php: 7.0
env:
- DB=MYSQL
@ -54,6 +59,12 @@ matrix:
env:
- DB=MYSQL
- BEHAT_TEST=cms
allow_failures:
- php: nightly
env:
- DB=MYSQL
- PDO=1
- PHPUNIT_TEST=framework
before_script:
# Init PHP

View File

@ -22,3 +22,6 @@ SilverStripe ships with default rewriting rules specific to your web server. Apa
routing requests to the framework, they also prevent access to sensitive files in the webroot,
for example YAML configuration files. Please refer to the [secure coding](/developer_guides/security/secure_coding/#filesystem) documentation for details.
</div>
## Related Lessons
* [Up and running: Setting up a local SilverStripe dev environment](https://www.silverstripe.org/learn/lessons/v4/up-and-running-setting-up-a-local-silverstripe-dev-environment-1)

View File

@ -100,4 +100,4 @@ by using a `flush=1` query parameter. See the ["Manifests" documentation](/devel
## Best Practices
### Making /assets readonly
See [Secure coding](/developer_guides/security/secure_coding#filesystem)
See [Secure coding](/developer_guides/security/secure_coding#filesystem)

View File

@ -64,6 +64,15 @@ ready for download or installation on a cloud platform.
If you run into trouble, see [common-problems](installation/common_problems) or post to the
[SilverStripe forums](http://silverstripe.org/community/forums/).
## Related
## Related Lessons
* [Up and running](https://www.silverstripe.org/learn/lessons/v4/up-and-running-setting-up-a-local-silverstripe-dev-environment-1)
* [Creating your first theme](https://www.silverstripe.org/learn/lessons/v4/creating-your-first-theme-1)
* [Migrating static templates into your theme](https://www.silverstripe.org/learn/lessons/v4/migrating-static-templates-into-your-theme-1)
* [Working with multiple templates](https://www.silverstripe.org/learn/lessons/v4/working-with-multiple-templates-1)
## Related Documentation
* [Module installation](/developer_guides/extending/modules)

View File

@ -403,4 +403,4 @@ We use the normal tactic of putting the data into an unordered list and using CS
In this tutorial we have explored custom php forms, and displayed result sets through Grouped Lists. We have briefly covered the different approaches to creating and using forms. Whether you decide to use the [userforms module](http://addons.silverstripe.org/add-ons/silverstripe/userforms) or create a form in PHP depends on the situation and flexibility required.
[Next Tutorial >>](/tutorials/site_search)
[Next Tutorial >>](/tutorials/site_search)

View File

@ -744,6 +744,11 @@ record #2 in Page refers to the same object as record #2 in [SiteTree](api:Silve
To retrieve a news article, SilverStripe joins the [SiteTree](api:SilverStripe\CMS\Model\SiteTree), [Page](api:SilverStripe\CMS\Model\SiteTree\Page) and NewsPage tables by their ID fields.
## Related Lessons
* [Introduction to the ORM](https://www.silverstripe.org/learn/lessons/v4/introduction-to-the-orm-1)
* [Adding custom fields to a page](https://www.silverstripe.org/learn/lessons/v4/adding-custom-fields-to-a-page-1)
## Related Documentation
* [Data Types and Casting](/developer_guides/model/data_types_and_casting)

View File

@ -479,6 +479,10 @@ As these lists are not backed by the database, most of the filtering methods on
this type. As such, an `UnsavedRelationList` should only be used for setting a relation before saving an object, not
for displaying the objects contained in the relation.
## Related Lessons
* [Working with data relationships -- has_many](https://www.silverstripe.org/learn/lessons/v4/working-with-data-relationships-has-many-1)
* [Working with data relationships -- many_many](https://www.silverstripe.org/learn/lessons/v4/working-with-data-relationships-many-many-1)
## Related Documentation
* [Introduction to the Data Model and ORM](data_model_and_orm)

View File

@ -92,6 +92,9 @@ echo $list->Count();
// returns '2'
```
## Related Lessons
* [Lists and pagination](https://www.silverstripe.org/learn/lessons/v4/lists-and-pagination-1)
## API Documentation
* [SS_List](api:SilverStripe\ORM\SS_List)

View File

@ -89,3 +89,6 @@ class Player extends DataObject
Note: There are no separate methods for *onBeforeCreate* and *onBeforeUpdate*. Please check `$this->isInDb()` to toggle
these two modes, as shown in the example above.
</div>
## Related Lessons
* [Working with data relationships - $has_many](https://www.silverstripe.org/learn/lessons/v4/working-with-data-relationships-has-many-1)

View File

@ -61,6 +61,10 @@ $players = Player::get()->filter([
]);
```
## Related Lessons
* [Introduction to ModelAdmin](https://www.silverstripe.org/learn/lessons/v4/introduction-to-modeladmin-1)
* [Building a search form](https://www.silverstripe.org/learn/lessons/v4/building-a-search-form-1)
## API Documentation
* [SearchFilter](api:SilverStripe\ORM\Filters\SearchFilter)

View File

@ -291,7 +291,11 @@ $players = Player::get();
$map = $players->map('Name', 'NameWithBirthyear');
```
## Related
## Related Lessons
* [Building custom SQL](https://www.silverstripe.org/learn/lessons/v4/beyond-the-orm-building-custom-sql-1)
## Related Documentation
* [Introduction to the Data Model and ORM](data_model_and_orm)

View File

@ -551,7 +551,10 @@ for adding notes for other developers but for things you don't want published in
$EditForm <%-- Some hidden comment about the form --%>
```
## Related
## Related Lessons
* [Creating your first theme](https://www.silverstripe.org/learn/lessons/v4/creating-your-first-theme-1)
## Related Documentation
[CHILDREN]
@ -563,3 +566,5 @@ $EditForm <%-- Some hidden comment about the form --%>
* [SSViewer](api:SilverStripe\View\SSViewer)
* [ThemeManifest](api:SilverStripe\View\ThemeManifest)

View File

@ -365,7 +365,10 @@ Placing it just below `$Content` is a good default.
You can add your own forms by implementing new form instances (see the [Forms tutorial](/tutorials/forms)).
## Related
## Related Lessons
* [Adding dynamic content](https://www.silverstripe.org/learn/lessons/v4/adding-dynamic-content-1)
## Related Documentation
* [Casting and Formating Variables](casting)
* [Template Inheritance](template_inheritance)

View File

@ -392,6 +392,10 @@ $file = ModuleResourceLoader::singleton()
->resolveURL('silverstripe/admin:client/dist/images/spinner.gif');
```
## Related Lessons
* [Creating your first theme](https://www.silverstripe.org/learn/lessons/v4/creating-your-first-theme-1)
* [AJAX behaviour and ViewableData](https://www.silverstripe.org/learn/lessons/v4/ajax-behaviour-and-viewabledata-1)
## API Documentation
* [Requirements](api:SilverStripe\View\Requirements)

View File

@ -99,3 +99,9 @@ class PageController extends ContentController
}
```
## Related Lessons
* [Controller actions/DataObjects as pages](https://www.silverstripe.org/learn/lessons/v4/controller-actions-dataobjects-as-pages-1)
* [AJAX behaviour and ViewableData](https://www.silverstripe.org/learn/lessons/v4/ajax-behaviour-and-viewabledata-1)
* [Dealing with arbitrary template data](https://www.silverstripe.org/learn/lessons/v4/dealing-with-arbitrary-template-data-1)
* [Creating filtered views](https://www.silverstripe.org/learn/lessons/v4/creating-filtered-views-1)

View File

@ -180,3 +180,6 @@ Module names are derived their local `composer.json` files using the following p
* 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
## Related Lessons
* [Working with multiple templates](https://www.silverstripe.org/learn/lessons/v4/working-with-multiple-templates-1)

View File

@ -103,3 +103,7 @@ The final step is to [submit your theme to Packagist](https://packagist.org/abou
* [Themes Listing on silverstripe.org](http://addons.silverstripe.org/add-ons?search=&type=theme)
* [Themes Forum on silverstripe.org](https://www.silverstripe.org/community/forums/themes-2/)
* [Themes repositories on github.com](http://github.com/silverstripe-themes)
## Related Lessons
* [Creating your first theme](https://www.silverstripe.org/learn/lessons/v4/creating-your-first-theme-1)
* [Migrating static templates into your theme](https://www.silverstripe.org/learn/lessons/v4/migrating-static-templates-into-your-theme-1)

View File

@ -167,3 +167,7 @@ Text / HTMLText methods:
version of emails.
* `$LimitSentences(<num>)` Will limit to the first `<num>` sentences in the content. If called on
HTML content this will have all HTML stripped and converted to plain text.
## Related Lessons
* [Dealing with arbitrary template data](https://www.silverstripe.org/learn/lessons/v4/dealing-with-arbitrary-template-data-1)

View File

@ -113,6 +113,8 @@ list.
| `$Link` | Links to the current controller URL, setting this page as current via a GET parameter |
| `$CurrentBool` | Returns true if you're currently on that page |
## Related Lessons
* [Lists and pagination](https://www.silverstripe.org/learn/lessons/v4/lists-and-pagination-1)
## API Documentation

View File

@ -15,3 +15,6 @@ templates from your controllers.
## How to's
[CHILDREN Folder=How_Tos]
## Related Lessons
* [Migrating static templates into your theme](https://www.silverstripe.org/learn/lessons/v4/migrating-static-templates-into-your-theme-1)

View File

@ -174,6 +174,10 @@ public function Link($action = null)
The [Controller::join_links()](api:SilverStripe\Control\Controller::join_links()) is optional, but makes `Link()` more flexible by allowing an `$action` argument, and concatenates the path segments with slashes. The action should map to a method on your controller.
</div>
## Related Lessons
* [Controller actions/DataObjects as pages](https://www.silverstripe.org/learn/lessons/v4/controller-actions-dataobjects-as-pages-1)
* [Creating filtered views](https://www.silverstripe.org/learn/lessons/v4/creating-filtered-views-1)
## Related Documentation
* [Execution Pipeline](../execution_pipeline)

View File

@ -213,6 +213,9 @@ Director:
'feed': 'FeedController'
```
## Related Lessons
* [Creating filtered views](https://www.silverstripe.org/learn/lessons/v4/creating-filtered-views-1)
* [Controller actions / DataObjects as pages](https://www.silverstripe.org/learn/lessons/v4/controller-actions-dataobjects-as-pages-1)
## Links
* [Controller](api:SilverStripe\Control\Controller) API documentation

View File

@ -346,6 +346,9 @@ $validator = new SilverStripe\Forms\RequiredFields([
$form = new Form($this, 'MyForm', $fields, $actions, $validator);
```
## Related Lessons
* [Intoduction to frontend forms](https://www.silverstripe.org/learn/lessons/v4/introduction-to-frontend-forms-1)
## API Documentation
* [Form](api:SilverStripe\Forms\Form)

View File

@ -307,6 +307,10 @@ class Page extends SiteTree
```
## Related Lessons
* [Intoduction to frontend forms](https://www.silverstripe.org/learn/lessons/v4/introduction-to-frontend-forms-1)
## API Documentation
* [RequiredFields](api:SilverStripe\Forms\RequiredFields)

View File

@ -351,3 +351,6 @@ That is, the fragment will be included if all Only rules match, except if all Ex
## API Documentation
* [Config](api:SilverStripe\Core\Config\Config)
## Related Lessons
* [DataExtensions and SiteConfig](https://www.silverstripe.org/learn/lessons/v4/data-extensions-and-siteconfig-1)

View File

@ -81,3 +81,7 @@ provide the users a place to configure settings then the `SiteConfig` panel is t
## API Documentation
* [SiteConfig](api:SilverStripe\SiteConfig\SiteConfig)
## Related Lessons
* [DataExtensions and SiteConfig](https://www.silverstripe.org/learn/lessons/v4/data-extensions-and-siteconfig-1)

View File

@ -11,3 +11,7 @@ For more information see our docs on [Environment Management](../../getting_star
Data which isn't sensitive that can be in version control but is mostly static such as constants is best suited to be
included through the [Configuration API](configuration) based on the standard environment types (dev / test / live).
## Related Lessons
* [Up and running](https://www.silverstripe.org/learn/lessons/v4/up-and-running-setting-up-a-local-silverstripe-dev-environment-1)
* [Advanced environment configuration](https://www.silverstripe.org/learn/lessons/v4/advanced-environment-configuration-1)

View File

@ -311,6 +311,10 @@ public function getCMSFields()
}
```
## Related Lessons
* [DataExtensions and SiteConfig](https://www.silverstripe.org/learn/lessons/v4/data-extensions-and-siteconfig-1)
## Related Documentaion
* [Injector](injector/)

View File

@ -81,4 +81,5 @@ if (Director::isLive()) {
}
```
## Related Lessons
* [Advanced environment configuration](https://www.silverstripe.org/learn/lessons/v4/advanced-environment-configuration-1)

View File

@ -265,3 +265,6 @@ In SilverStripe 3, logging was based on the Zend Log module. Customisations were
This function no longer works, and any Zend Log writers will need to be replaced with Monolog handlers. Fortunately,
a range of handlers are available, both in the core package and in add-ons. See the
[Monolog documentation](https://github.com/Seldaek/monolog/blob/master/doc/01-usage.md) for more information.
## Related Lessons
* [Advanced environment configuration](https://www.silverstripe.org/learn/lessons/v4/advanced-environment-configuration-1)

View File

@ -202,3 +202,6 @@ storage.
SilverStripe\Assets\File:
keep_archived_assets: true
```
## Related Lessons
* [Working with files and images](https://www.silverstripe.org/learn/lessons/v4/working-with-files-and-images-1)

View File

@ -214,3 +214,7 @@ SilverStripe\Core\Injector\Injector:
* [Image](api:SilverStripe\Assets\Image)
* [DBFile](api:SilverStripe\Assets\Storage\DBFile)
* [ImageManipulation](api:SilverStripe\Assets\ImageManipulation)
## Related Lessons
* [Working with files and images](https://www.silverstripe.org/learn/lessons/v4/working-with-files-and-images-1)

View File

@ -360,6 +360,9 @@ class MyAdmin extends ModelAdmin
}
```
## Related Lessons
* [Intoduction to ModelAdmin](https://www.silverstripe.org/learn/lessons/v4/introduction-to-modeladmin-1)
## Related Documentation
* [GridField](../forms/field_types/gridfield)

View File

@ -359,7 +359,7 @@ class CoreKernel implements Kernel
}
// Allow database adapters to handle their own configuration
DatabaseAdapterRegistry::autoconfigure();
DatabaseAdapterRegistry::autoconfigure($databaseConfig);
return $databaseConfig;
}

View File

@ -3,6 +3,7 @@
namespace SilverStripe\Dev\Install;
use InvalidArgumentException;
use SilverStripe\Dev\Deprecation;
/**
* This class keeps track of the available database adapters
@ -111,7 +112,7 @@ class DatabaseAdapterRegistry
/**
* Detects all _register_database.php files and invokes them.
* Searches through vendor/ folder only,
* Searches through vendor/*\/* folders only,
* does not support "legacy" folder location in webroot
*/
public static function autodiscover()
@ -131,10 +132,19 @@ class DatabaseAdapterRegistry
* Called by ConfigureFromEnv.php.
* Searches through vendor/ folder only,
* does not support "legacy" folder location in webroot
*
* @param array $config Config to update. If not provided fall back to global $databaseConfig.
* In 5.0.0 this will be mandatory and the global will be removed.
*/
public static function autoconfigure()
public static function autoconfigure(&$config = null)
{
// Search through all composer packages in vendor
if (!isset($config)) {
Deprecation::notice('5.0', 'Configuration via global is deprecated');
global $databaseConfig;
} else {
$databaseConfig = $config;
}
// Search through all composer packages in vendor, updating $databaseConfig
foreach (glob(BASE_PATH . '/vendor/*', GLOB_ONLYDIR) as $vendor) {
foreach (glob($vendor . '/*', GLOB_ONLYDIR) as $directory) {
if (file_exists($directory . '/_configure_database.php')) {
@ -142,6 +152,8 @@ class DatabaseAdapterRegistry
}
}
}
// Update modified variable
$config = $databaseConfig;
}
/**

View File

@ -227,8 +227,9 @@ class InstallRequirements
/**
* Check everything except the database
*/
public function check()
public function check($originalIni)
{
$this->originalIni = $originalIni;
$this->errors = [];
$isApache = $this->isApache();
$isIIS = $this->isIIS();

View File

@ -66,7 +66,7 @@ $theme = $config->getTheme($_REQUEST);
// Check requirements
$req = new InstallRequirements();
$req->check();
$req->check($originalIni);
if ($req->isIIS()) {
$webserverConfigFile = 'web.config';

View File

@ -74,49 +74,49 @@ class TinyMCEConfig extends HTMLEditorConfig
'fa_PK' => 'fa',
'fi_FI' => 'fi',
'fi_SE' => 'fi',
'fr_BE' => 'fr',
'fr_BF' => 'fr',
'fr_BI' => 'fr',
'fr_BJ' => 'fr',
'fr_CA' => 'fr_ca',
'fr_CF' => 'fr',
'fr_CG' => 'fr',
'fr_CH' => 'fr',
'fr_CI' => 'fr',
'fr_CM' => 'fr',
'fr_DJ' => 'fr',
'fr_DZ' => 'fr',
'fr_FR' => 'fr',
'fr_GA' => 'fr',
'fr_GF' => 'fr',
'fr_GN' => 'fr',
'fr_GP' => 'fr',
'fr_HT' => 'fr',
'fr_KM' => 'fr',
'fr_LU' => 'fr',
'fr_MA' => 'fr',
'fr_MC' => 'fr',
'fr_MG' => 'fr',
'fr_ML' => 'fr',
'fr_MQ' => 'fr',
'fr_MU' => 'fr',
'fr_NC' => 'fr',
'fr_NE' => 'fr',
'fr_PF' => 'fr',
'fr_PM' => 'fr',
'fr_RE' => 'fr',
'fr_RW' => 'fr',
'fr_SC' => 'fr',
'fr_SN' => 'fr',
'fr_SY' => 'fr',
'fr_TD' => 'fr',
'fr_TG' => 'fr',
'fr_TN' => 'fr',
'fr_VU' => 'fr',
'fr_WF' => 'fr',
'fr_YT' => 'fr',
'fr_GB' => 'fr',
'fr_US' => 'fr',
'fr_BE' => 'fr_FR',
'fr_BF' => 'fr_FR',
'fr_BI' => 'fr_FR',
'fr_BJ' => 'fr_FR',
'fr_CA' => 'fr_FR',
'fr_CF' => 'fr_FR',
'fr_CG' => 'fr_FR',
'fr_CH' => 'fr_FR',
'fr_CI' => 'fr_FR',
'fr_CM' => 'fr_FR',
'fr_DJ' => 'fr_FR',
'fr_DZ' => 'fr_FR',
'fr_FR' => 'fr_FR',
'fr_GA' => 'fr_FR',
'fr_GF' => 'fr_FR',
'fr_GN' => 'fr_FR',
'fr_GP' => 'fr_FR',
'fr_HT' => 'fr_FR',
'fr_KM' => 'fr_FR',
'fr_LU' => 'fr_FR',
'fr_MA' => 'fr_FR',
'fr_MC' => 'fr_FR',
'fr_MG' => 'fr_FR',
'fr_ML' => 'fr_FR',
'fr_MQ' => 'fr_FR',
'fr_MU' => 'fr_FR',
'fr_NC' => 'fr_FR',
'fr_NE' => 'fr_FR',
'fr_PF' => 'fr_FR',
'fr_PM' => 'fr_FR',
'fr_RE' => 'fr_FR',
'fr_RW' => 'fr_FR',
'fr_SC' => 'fr_FR',
'fr_SN' => 'fr_FR',
'fr_SY' => 'fr_FR',
'fr_TD' => 'fr_FR',
'fr_TG' => 'fr_FR',
'fr_TN' => 'fr_FR',
'fr_VU' => 'fr_FR',
'fr_WF' => 'fr_FR',
'fr_YT' => 'fr_FR',
'fr_GB' => 'fr_FR',
'fr_US' => 'fr_FR',
'he_IL' => 'he',
'hu_HU' => 'hu',
'hu_AT' => 'hu',

View File

@ -899,8 +899,7 @@ abstract class DBSchemaManager
*
* @param string $tableName The name of the table.
* @param string $indexName The name of the index.
* @param string $indexSpec The specification of the index, see {@link SS_Database::requireIndex()}
* for more details.
* @param array $indexSpec The specification of the index, see Database::requireIndex() for more details.
* @todo Find out where this is called from - Is it even used? Aren't indexes always dropped and re-added?
*/
abstract public function alterIndex($tableName, $indexName, $indexSpec);

View File

@ -6,6 +6,7 @@ use Exception;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\FieldType\DBComposite;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
@ -126,6 +127,7 @@ class DataObjectSchema
}
return null;
}
/**
* Returns the root class (the first to extend from DataObject) for the
* passed class.
@ -301,11 +303,26 @@ class DataObjectSchema
$table = Config::inst()->get($class, 'table_name', Config::UNINHERITED);
// Generate default table name
if (!$table) {
$separator = DataObjectSchema::config()->uninherited('table_namespace_separator');
$table = str_replace('\\', $separator, trim($class, '\\'));
if ($table) {
return $table;
}
if (strpos($class, '\\') === false) {
return $class;
}
if (!ClassInfo::classImplements($class, TestOnly::class)) {
trigger_error(
"It is recommended to define a table_name for your '$class'." .
' Not defining a table_name may cause subsequent table names to be too long and may not be supported' .
' by your current database engine, the generated naming scheme will also change when upgrading to' .
' SilverStripe 5.0 and potentially break.',
E_USER_WARNING
);
}
$separator = DataObjectSchema::config()->uninherited('table_namespace_separator');
$table = str_replace('\\', $separator, trim($class, '\\'));
return $table;
}

View File

@ -2,6 +2,7 @@
namespace SilverStripe\Security\MemberAuthenticator;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\RequestHandler;
@ -109,6 +110,14 @@ class LogoutHandler extends RequestHandler
return $this->redirect($backURL);
}
return $this->redirect(Security::config()->get('login_url'));
$link = Security::config()->get('login_url');
$referer = $this->getReturnReferer();
if ($referer) {
$link = Controller::join_links($link, '?' . http_build_query([
'BackURL' => Director::makeRelative($referer)
]));
}
return $this->redirect($link);
}
}

View File

@ -3,9 +3,12 @@
namespace SilverStripe\View;
use Exception;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Manifest\ModuleResourceLoader;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\ArrayLib;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
@ -586,6 +589,35 @@ class ViewableData implements IteratorAggregate
return $this;
}
/**
* Return the directory if the current active theme (relative to the site root).
*
* This method is useful for things such as accessing theme images from your template without hardcoding the theme
* page - e.g. <img src="$ThemeDir/images/something.gif">.
*
* This method should only be used when a theme is currently active. However, it will fall over to the current
* project directory.
*
* @return string URL to the current theme
* @deprecated 4.0.0..5.0.0 Use $resourcePath or $resourceURL template helpers instead
*/
public function ThemeDir()
{
Deprecation::notice('5.0', 'Use $resourcePath or $resourceURL template helpers instead');
$themes = SSViewer::get_themes();
foreach ($themes as $theme) {
// Skip theme sets
if (strpos($theme, '$') === 0) {
continue;
}
// Map theme path to url
$themePath = ThemeResourceLoader::inst()->getPath($theme);
return ModuleResourceLoader::resourceURL($themePath);
}
return project();
}
/**
* Get part of the current classes ancestry to be used as a CSS class.
*

View File

@ -793,7 +793,7 @@ class IntlLocales implements Locales, Resettable
'pl' => 'pl_PL',
'pon' => 'pon_FM',
'ps' => 'ps_AF',
'pt' => 'pt_BR',
'pt' => 'pt_PT',
'qu' => 'qu_PE',
'rm' => 'rm_CH',
'rn' => 'rn_BI',

View File

@ -558,6 +558,7 @@ class i18nTextCollector
$inNamespace = false;
$inClass = false; // after `class` but before `{`
$inArrayClosedBy = false; // Set to the expected closing token, or false if not in array
$inSelf = false; // Tracks progress of collecting self::class
$currentEntity = array();
$currentClass = []; // Class components
$previousToken = null;
@ -584,10 +585,20 @@ class i18nTextCollector
if ($id === T_CLASS) {
// Skip if previous token was '::'. E.g. 'Object::class'
if (is_array($previousToken) && $previousToken[0] === T_DOUBLE_COLON) {
if ($inSelf) {
// Handle self::class by allowing logic further down
// for __CLASS__ to handle an array of class parts
$id = T_CLASS_C;
$inSelf = false;
} else {
// Don't handle other ::class definitions. We can't determine which
// class was invoked, so parent::class is not possible at this point.
continue;
}
} else {
$inClass = true;
continue;
}
$inClass = true;
continue;
}
if ($inClass && $id === T_STRING) {
$currentClass[] = $text;
@ -614,7 +625,7 @@ class i18nTextCollector
// If inside this translation, some elements might be unreachable
if (in_array($id, [T_VARIABLE, T_STATIC]) ||
($id === T_STRING && in_array($text, ['self', 'static', 'parent']))
($id === T_STRING && in_array($text, ['static', 'parent']))
) {
// Un-collectable strings such as _t(static::class.'.KEY').
// Should be provided by i18nEntityProvider instead
@ -625,6 +636,12 @@ class i18nTextCollector
continue;
}
// Start collecting self::class declarations
if ($id === T_STRING && $text === 'self') {
$inSelf = true;
continue;
}
// Check text
if ($id == T_CONSTANT_ENCAPSED_STRING) {
// Fixed quoting escapes, and remove leading/trailing quotes
@ -648,7 +665,7 @@ class i18nTextCollector
throw new LogicException("Invalid string escape: " .$text);
}
} elseif ($id === T_CLASS_C) {
// Evaluate __CLASS__ . '.KEY' concatenation
// Evaluate __CLASS__ . '.KEY' and self::class concatenation
$text = implode('\\', $currentClass);
} else {
continue;

View File

@ -2,7 +2,9 @@
namespace SilverStripe\Core\Tests\ClassInfoTest;
class ChildClass extends BaseClass
use SilverStripe\Dev\TestOnly;
class ChildClass extends BaseClass implements TestOnly
{
}

View File

@ -5,6 +5,7 @@ namespace SilverStripe\View\Tests;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\View\ArrayData;
use SilverStripe\View\SSViewer;
use SilverStripe\View\ViewableData;
/**
@ -204,4 +205,19 @@ class ViewableDataTest extends SapphireTest
$this->assertSame($failover, $container->getFailover(), 'getFailover() returned a different object');
$this->assertFalse($container->hasMethod('testMethod'), 'testMethod() incorrectly reported as existing');
}
public function testThemeDir()
{
$themes = [
"silverstripe/framework:/tests/php/View/ViewableDataTest/testtheme",
SSViewer::DEFAULT_THEME
];
SSViewer::set_themes($themes);
$data = new ViewableData();
$this->assertContains(
'tests/php/View/ViewableDataTest/testtheme',
$data->ThemeDir()
);
}
}

View File

@ -323,13 +323,21 @@ class MyClass extends Base implements SomeService {
"Slash=\\\\, Quote=\\""
);
}
public function getMagicConstantStringFromSelf()
{
return _t(
self::class . '.SELF_CLASS',
'Self Class'
);
}
}
PHP;
$this->assertEquals(
[
'SilverStripe\\Framework\\Core\\MyClass.NEWLINES' => "New Lines",
'SilverStripe\\Framework\\MyClass.ANOTHER_STRING' => 'Slash=\\, Quote=\'',
'SilverStripe\\Framework\\MyClass.DOUBLE_STRING' => 'Slash=\\, Quote="'
'SilverStripe\\Framework\\MyClass.DOUBLE_STRING' => 'Slash=\\, Quote="',
'SilverStripe\\Framework\\Core\\MyClass.SELF_CLASS' => 'Self Class',
],
$c->collectFromCode($php, null, $mymodule)
);
@ -434,7 +442,7 @@ PHP;
$php = <<<PHP
_t(static::class.'.KEY1', 'Default');
_t(self::class.'.KEY2', 'Default');
_t(parent::class.'.KEY1', 'Default');
_t('Collectable.KEY4', 'Default');
PHP;