Merge branch '4' into 5

This commit is contained in:
Sabina Talipova 2022-11-22 11:41:53 +13:00
commit a52c7795c7
73 changed files with 550 additions and 278 deletions

View File

@ -1,6 +1,5 @@
<?php
use SilverStripe\Dev\Deprecation;
use SilverStripe\View\Shortcodes\EmbedShortcodeProvider;
use SilverStripe\View\Parsers\ShortcodeParser;
@ -14,6 +13,3 @@ use SilverStripe\View\Parsers\ShortcodeParser;
ShortcodeParser::get('default')
->register('embed', [EmbedShortcodeProvider::class, 'handle_shortcode']);
// Set to 5.0.0 to show APIs marked for removal at that version
Deprecation::notification_version('4.0.0');

View File

@ -2,14 +2,14 @@
Name: basei18n
Before: '#defaulti18n'
---
SilverStripe\i18n\Data\Sources:
SilverStripe\Core\Manifest\ModuleManifest:
module_priority:
- silverstripe\admin
- silverstripe\framework
---
Name: defaulti18n
---
SilverStripe\i18n\Data\Sources:
SilverStripe\Core\Manifest\ModuleManifest:
module_priority:
- other_modules
---

View File

@ -200,12 +200,9 @@ class CookieJar implements Cookie_Backend
/**
* Get the correct samesite value - Session cookies use a different configuration variable.
*
* @deprecated 4.12.0 The relevant methods will include a `$sameSite` parameter instead.
*/
private function getSameSite(string $name): string
{
Deprecation::notice('4.12.0', 'The relevant methods will include a `$sameSite` parameter instead.');
if ($name === session_name()) {
return Session::config()->get('cookie_samesite');
}

View File

@ -228,7 +228,7 @@ class Director implements TemplateGlobalProvider
? $cookies
: Injector::inst()->createWithArgs(Cookie_Backend::class, [$cookies ?: []]);
$newVars['_COOKIE'] = $cookieJar->getAll(false);
Cookie::config()->update('report_errors', false);
Cookie::config()->set('report_errors', false);
Injector::inst()->registerService($cookieJar, Cookie_Backend::class);
// Backup requirements

View File

@ -126,7 +126,7 @@ class HTTP
if (preg_match('/^\w+:/', $url ?? '')) {
return $url;
}
return Director::absoluteURL($url, true);
return Director::absoluteURL($url);
});
}
@ -474,6 +474,8 @@ class HTTP
* Ensure that all deprecated HTTP cache settings are respected
*
* @deprecated 4.2.0 Use HTTPCacheControlMiddleware instead
* Simply delete this method in CMS 5 and the calls to it from HTTPCacheControlMiddleware
*
* @throws \LogicException
* @param HTTPRequest $request
* @param HTTPResponse $response
@ -491,32 +493,32 @@ class HTTP
// if http caching is disabled by config, disable it - used on dev environments due to frequently changing
// templates and other data. will be overridden by forced publicCache(true) or privateCache(true) calls
if ($config->get('disable_http_cache')) {
Deprecation::notice('5.0', 'Use HTTPCacheControlMiddleware.defaultState/.defaultForcingLevel instead');
$cacheControlMiddleware->disableCache();
}
Deprecation::withNoReplacement(function () use ($config, $cacheControlMiddleware) {
if ($config->get('disable_http_cache')) {
$cacheControlMiddleware->disableCache();
}
});
// if no caching ajax requests, disable ajax if is ajax request
if (!$config->get('cache_ajax_requests') && Director::is_ajax()) {
Deprecation::notice(
'5.0',
'HTTP.cache_ajax_requests config is deprecated. Use HTTPCacheControlMiddleware::disableCache() instead'
);
$cacheControlMiddleware->disableCache();
}
Deprecation::withNoReplacement(function () use ($config, $cacheControlMiddleware) {
if (!$config->get('cache_ajax_requests') && Director::is_ajax()) {
$cacheControlMiddleware->disableCache();
}
});
// Pass vary to middleware
$configVary = $config->get('vary');
$configVary = Deprecation::withNoReplacement(function () use ($config) {
return $config->get('vary');
});
if ($configVary) {
Deprecation::notice('5.0', 'Use HTTPCacheControlMiddleware.defaultVary instead');
$cacheControlMiddleware->addVary($configVary);
}
// Pass cache_control to middleware
$configCacheControl = $config->get('cache_control');
$configCacheControl = Deprecation::withNoReplacement(function () use ($config) {
return $config->get('cache_control');
});
if ($configCacheControl) {
Deprecation::notice('5.0', 'Use HTTPCacheControlMiddleware API instead');
$supportedDirectives = ['max-age', 'no-cache', 'no-store', 'must-revalidate'];
if ($foundUnsupported = array_diff(array_keys($configCacheControl ?? []), $supportedDirectives)) {
throw new \LogicException(

View File

@ -2,10 +2,12 @@
namespace SilverStripe\Control\Middleware;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\BaseKernel;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Flushable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Kernel;
/**
* Triggers a call to flush() on all implementors of Flushable.
@ -14,7 +16,9 @@ class FlushMiddleware implements HTTPMiddleware
{
public function process(HTTPRequest $request, callable $delegate)
{
if (Director::isManifestFlushed()) {
/** @var BaseKernel $kernel */
$kernel = Injector::inst()->get(Kernel::class);
if ((method_exists($kernel, 'isFlushed') && $kernel->isFlushed())) {
// Disable cache when flushing
HTTPCacheControlMiddleware::singleton()->disableCache(true);

View File

@ -12,6 +12,7 @@ use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Resettable;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Dev\Deprecation;
class HTTPCacheControlMiddleware implements HTTPMiddleware, Resettable
{
@ -51,7 +52,9 @@ class HTTPCacheControlMiddleware implements HTTPMiddleware, Resettable
$this->augmentState($request, $response);
// Update state based on deprecated HTTP settings
HTTP::augmentState($request, $response);
Deprecation::withNoReplacement(function () use ($request, $response) {
HTTP::augmentState($request, $response);
});
// Add all headers to this response object
$this->applyToResponse($response);

View File

@ -2,10 +2,10 @@
namespace SilverStripe\Control\Middleware\URLSpecialsMiddleware;
use SilverStripe\Core\BaseKernel;
use SilverStripe\Core\Kernel;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Startup\ScheduledFlushDiscoverer;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
/**
@ -30,11 +30,12 @@ trait FlushScheduler
{
$flush = array_key_exists('flush', $request->getVars() ?? []) || ($request->getURL() === 'dev/build');
if (!$flush || Director::isManifestFlushed()) {
/** @var BaseKernel $kernel */
$kernel = Injector::inst()->get(Kernel::class);
if (!$flush || (method_exists($kernel, 'isFlushed') && $kernel->isFlushed())) {
return false;
}
$kernel = Injector::inst()->get(Kernel::class);
ScheduledFlushDiscoverer::scheduleFlush($kernel);
return true;

View File

@ -222,7 +222,7 @@ class RSSFeed extends ViewableData
public function outputToBrowser()
{
$prevState = SSViewer::config()->uninherited('source_file_comments');
SSViewer::config()->update('source_file_comments', false);
SSViewer::config()->set('source_file_comments', false);
$response = Controller::curr()->getResponse();
@ -236,7 +236,7 @@ class RSSFeed extends ViewableData
$response->addHeader("Content-Type", "application/rss+xml; charset=utf-8");
SSViewer::config()->update('source_file_comments', $prevState);
SSViewer::config()->set('source_file_comments', $prevState);
return $this->renderWith($this->getTemplates());
}

View File

@ -29,7 +29,9 @@ class RequestProcessor implements HTTPMiddleware
*/
public function __construct($filters = [])
{
Deprecation::notice('4.0.1', 'Use HTTPMiddleware directly instead.', Deprecation::SCOPE_CLASS);
Deprecation::withNoReplacement(function () {
Deprecation::notice('4.0.1', 'Use HTTPMiddleware directly instead.', Deprecation::SCOPE_CLASS);
});
$this->filters = $filters;
}

View File

@ -586,13 +586,11 @@ class Session
* Recursively apply the changes represented in $data to $dest.
* Used to update $_SESSION
*
* @deprecated 4.1.0 Use recursivelyApplyChanges() instead
* @param array $data
* @param array $dest
*/
protected function recursivelyApply($data, &$dest)
{
Deprecation::notice('4.1.0', 'Use recursivelyApplyChanges() instead');
foreach ($data as $k => $v) {
if (is_array($v)) {
if (!isset($dest[$k]) || !is_array($dest[$k])) {

View File

@ -82,7 +82,10 @@ class SimpleResourceURLGenerator implements ResourceURLGenerator
// Determine lookup mechanism based on existence of public/ folder.
// From 5.0 onwards only resolvePublicResource() will be used.
if (!Director::publicDir()) {
list($exists, $absolutePath, $relativePath) = $this->resolveUnsecuredResource($relativePath);
$ret = Deprecation::withNoReplacement(function () use ($relativePath) {
return $this->resolveUnsecuredResource($relativePath);
});
list($exists, $absolutePath, $relativePath) = $ret;
} else {
list($exists, $absolutePath, $relativePath) = $this->resolvePublicResource($relativePath);
}

View File

@ -180,10 +180,24 @@ abstract class BaseKernel implements Kernel
protected function bootManifests($flush)
{
// Setup autoloader
$this->getClassLoader()->init($this->getIncludeTests(), $flush);
$ignoredCIConfigs = Deprecation::withNoReplacement(function () {
return $this->getIgnoredCIConfigs();
});
// Find modules
$this->getModuleLoader()->init($this->getIncludeTests(), $flush);
Deprecation::withNoReplacement(function () use ($flush, $ignoredCIConfigs) {
$this->getClassLoader()->init(
$this->getIncludeTests(),
$flush,
$ignoredCIConfigs
);
// Find modules
$this->getModuleLoader()->init(
$this->getIncludeTests(),
$flush,
$ignoredCIConfigs
);
});
// Flush config
if ($flush) {
@ -201,7 +215,13 @@ abstract class BaseKernel implements Kernel
$defaultSet->setProject(
ModuleManifest::config()->get('project')
);
$defaultSet->init($this->getIncludeTests(), $flush);
Deprecation::withNoReplacement(function () use ($defaultSet, $flush, $ignoredCIConfigs) {
$defaultSet->init(
$this->getIncludeTests(),
$flush,
$ignoredCIConfigs
);
});
}
}
@ -247,12 +267,9 @@ abstract class BaseKernel implements Kernel
* Get the environment type
*
* @return string
*
* @deprecated 4.12.0 Use Director::get_environment_type() instead
*/
public function getEnvironment()
{
Deprecation::notice('4.12.0', 'Use Director::get_environment_type() instead');
// Check set
if ($this->enviroment) {
return $this->enviroment;

View File

@ -275,7 +275,7 @@ class Convert
/**
* Convert a JSON string into an array.
*
* @deprecated 4.4.0 Use json_decode() instead
* @deprecated 4.4.0 Use json_decode($val, true) instead
* @param string $val JSON string to convert
* @return array|boolean
*/

View File

@ -126,7 +126,9 @@ class ClassLoader
foreach ($this->manifests as $manifest) {
/** @var ClassManifest $instance */
$instance = $manifest['instance'];
$instance->init($includeTests, $forceRegen);
Deprecation::withNoReplacement(function () use ($instance, $includeTests, $forceRegen, $ignoredCIConfigs) {
$instance->init($includeTests, $forceRegen, $ignoredCIConfigs);
});
}
$this->registerAutoloader();

View File

@ -291,7 +291,9 @@ class ClassManifest
}
// Build
$this->regenerate($includeTests);
Deprecation::withNoReplacement(function () use ($includeTests, $ignoredCIConfigs) {
$this->regenerate($includeTests, $ignoredCIConfigs);
});
}
/**

View File

@ -5,6 +5,7 @@ namespace SilverStripe\Dev;
use BadMethodCallException;
use SilverStripe\Control\Director;
use SilverStripe\Core\Environment;
use SilverStripe\Core\Injector\InjectionCreator;
use SilverStripe\Core\Injector\InjectorLoader;
use SilverStripe\Core\Manifest\Module;
@ -21,19 +22,7 @@ use SilverStripe\Core\Manifest\Module;
*
* This class abstracts the above pattern and adds a way to do that.
*
* Each call to notice passes a version that the notice will be valid from. Additionally this class has a notion of the
* version it should use when deciding whether to raise the notice. If that version is equal to or greater than the
* notices version (and SilverStripe is in dev mode) a deprecation message will be raised.
*
* Normally the checking version will be the release version of SilverStripe, but a developer can choose to set it to a
* future version, to see how their code will behave in future versions.
*
* Modules can also set the version for calls they make - either setting it to a future version in order to ensure
* forwards compatibility or setting it backwards if a module has not yet removed references to deprecated methods.
*
* When set per-module, only direct calls to deprecated methods from those modules are considered - if the module
* calls a non-module method which then calls a deprecated method, that call will use the global check version, not
* the module specific check version.
* Each call to notice passes a version that the notice will be valid from.
*/
class Deprecation
{
@ -58,10 +47,22 @@ class Deprecation
* must be available before this to avoid infinite loops.
*
* @var boolean|null
* @deprecated 4.12.0 Use $is_enabled instead
* @deprecated 4.12.0 Use $currentlyEnabled instead
*/
protected static $enabled = null;
/**
* @var array
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
protected static $module_version_overrides = [];
/**
* @var array
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
public static $notice_level = E_USER_DEPRECATED;
/**
* Must be configured outside of the config API, as deprecation API
* must be available before this to avoid infinite loops.
@ -70,48 +71,64 @@ class Deprecation
*
* @internal - Marked as internal so this and other private static's are not treated as config
*/
private static bool $is_enabled = false;
/**
* @var array
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
*/
protected static $module_version_overrides = [];
private static bool $currentlyEnabled = false;
/**
* @internal
*/
private static bool $inside_notice = false;
private static bool $insideNotice = false;
/**
* @var array
* @deprecated 4.12.0 Will be removed without equivalent functionality to replace it
* @internal
*/
public static $notice_level = E_USER_DEPRECATED;
private static bool $insideWithNoReplacement = false;
/**
* Buffer of user_errors to be raised when enabled() is called
*
* This is used when setting deprecated config via yaml, before Deprecation::enable() has been called in _config.php
* Deprecated config set via yaml will only be shown in the browser when using ?flush=1
* It will not show in CLI when running dev/build flush=1
* Buffer of user_errors to be raised
*
* @internal
*/
private static array $user_error_message_buffer = [];
private static array $userErrorMessageBuffer = [];
public static function enable(): void
/**
* @internal
*/
private static bool $haveSetShutdownFunction = false;
/**
* @internal
*/
private static bool $showNoReplacementNotices = false;
public static function enable(bool $showNoReplacementNotices = false): void
{
static::$is_enabled = true;
foreach (self::$user_error_message_buffer as $message) {
user_error($message, E_USER_DEPRECATED);
}
self::$user_error_message_buffer = [];
static::$currentlyEnabled = true;
static::$showNoReplacementNotices = $showNoReplacementNotices;
}
public static function disable(): void
{
static::$is_enabled = false;
static::$currentlyEnabled = false;
}
/**
* Used to wrap deprecated methods and deprecated config get()/set() that will be removed
* in the next major version with no replacement. This is done to surpress deprecation notices
* by for calls from the vendor dir to deprecated code that projects have no ability to change
*
* @return mixed
*/
public static function withNoReplacement(callable $func)
{
if (self::$insideWithNoReplacement) {
return $func();
}
self::$insideWithNoReplacement = true;
try {
return $func();
} finally {
self::$insideWithNoReplacement = false;
}
}
/**
@ -159,12 +176,19 @@ class Deprecation
if (!$level) {
$level = 1;
}
$called = $backtrace ? $backtrace[$level] : [];
if (isset($called['class'])) {
return $called['class'] . $called['type'] . $called['function'];
$newLevel = $level;
// handle call_user_func
if ($level === 4 && strpos($backtrace[2]['function'] ?? '', 'call_user_func') !== false) {
$newLevel = 5;
} elseif (strpos($backtrace[$level]['function'] ?? '', 'call_user_func') !== false) {
$newLevel = $level + 1;
}
return $called['function'] ?? '';
// handle InjectionCreator
if ($level == 4 && ($backtrace[$newLevel]['class'] ?? '') === InjectionCreator::class) {
$newLevel = $newLevel + 4;
}
$called = $backtrace[$newLevel] ?? [];
return ($called['class'] ?? '') . ($called['type'] ?? '') . ($called['function'] ?? '');
}
/**
@ -179,12 +203,12 @@ class Deprecation
// noop
}
private static function get_is_enabled(): bool
public static function isEnabled(): bool
{
if (!Director::isDev()) {
return false;
}
return static::$is_enabled || Environment::getEnv('SS_DEPRECATION_ENABLED');
return static::$currentlyEnabled || Environment::getEnv('SS_DEPRECATION_ENABLED');
}
/**
@ -199,6 +223,24 @@ class Deprecation
// noop
}
public static function outputNotices(): void
{
if (!self::isEnabled()) {
return;
}
// using a while loop with array_shift() to ensure that self::$userErrorMessageBuffer will have
// have values removed from it before calling user_error()
while (count(self::$userErrorMessageBuffer)) {
$arr = array_shift(self::$userErrorMessageBuffer);
$message = $arr['message'];
$calledInsideWithNoReplacement = $arr['calledInsideWithNoReplacement'];
if ($calledInsideWithNoReplacement && !self::$showNoReplacementNotices) {
continue;
}
user_error($message, E_USER_DEPRECATED);
}
}
/**
* Raise a notice indicating the method is deprecated if the version passed as the second argument is greater
* than or equal to the check version set via ::notification_version
@ -209,22 +251,23 @@ class Deprecation
*/
public static function notice($atVersion, $string = '', $scope = Deprecation::SCOPE_METHOD)
{
if (static::$inside_notice) {
if (static::$insideNotice) {
return;
}
static::$inside_notice = true;
static::$insideNotice = true;
// try block needs to wrap all code in case anything inside the try block
// calls something else that calls Deprecation::notice()
try {
if ($scope === self::SCOPE_CONFIG) {
if (self::get_is_enabled()) {
user_error($string, E_USER_DEPRECATED);
} else {
self::$user_error_message_buffer[] = $string;
}
// Deprecated config set via yaml will only be shown in the browser when using ?flush=1
// It will not show in CLI when running dev/build flush=1
self::$userErrorMessageBuffer[] = [
'message' => $string,
'calledInsideWithNoReplacement' => self::$insideWithNoReplacement
];
} else {
if (!self::get_is_enabled()) {
// Do not add to self::$user_error_message_buffer, as the backtrace is too expensive
if (!self::isEnabled()) {
// Do not add to self::$userErrorMessageBuffer, as the backtrace is too expensive
return;
}
@ -234,7 +277,7 @@ class Deprecation
// Get the calling scope
if ($scope == Deprecation::SCOPE_METHOD) {
$backtrace = debug_backtrace(0);
$caller = self::get_called_method_from_trace($backtrace);
$caller = self::get_called_method_from_trace($backtrace, 1);
} elseif ($scope == Deprecation::SCOPE_CLASS) {
$backtrace = debug_backtrace(0);
$caller = isset($backtrace[1]['class']) ? $backtrace[1]['class'] : '(unknown)';
@ -242,18 +285,30 @@ class Deprecation
$caller = false;
}
// Then raise the notice
if (substr($string, -1) != '.') {
$string .= ".";
}
$string .= " Called from " . self::get_called_method_from_trace($backtrace, 2) . '.';
$level = self::$insideWithNoReplacement ? 4 : 2;
$string .= " Called from " . self::get_called_method_from_trace($backtrace, $level) . '.';
if ($caller) {
user_error($caller . ' is deprecated.' . ($string ? ' ' . $string : ''), E_USER_DEPRECATED);
} else {
user_error($string, E_USER_DEPRECATED);
$string = $caller . ' is deprecated.' . ($string ? ' ' . $string : '');
}
self::$userErrorMessageBuffer[] = [
'message' => $string,
'calledInsideWithNoReplacement' => self::$insideWithNoReplacement
];
}
if (!self::$haveSetShutdownFunction && self::isEnabled()) {
// Use a shutdown function rather than immediately calling user_error() so that notices
// do not interfere with setting session varibles i.e. headers already sent error
// it also means the deprecation notices appear below all phpunit output in CI
// which is far nicer than having it spliced between phpunit output
register_shutdown_function(function () {
self::outputNotices();
});
self::$haveSetShutdownFunction = true;
}
} catch (BadMethodCallException $e) {
if ($e->getMessage() === InjectorLoader::NO_MANIFESTS_AVAILABLE) {
@ -264,7 +319,7 @@ class Deprecation
throw $e;
}
} finally {
static::$inside_notice = false;
static::$insideNotice = false;
}
}

View File

@ -11,6 +11,7 @@ use SilverStripe\Security\BasicAuth;
use SilverStripe\Security\SecurityToken;
use SilverStripe\View\SSViewer;
use SimpleXMLElement;
use SilverStripe\Dev\Deprecation;
/**
* SilverStripe-specific testing object designed to support functional testing of your web app. It simulates get/post
@ -94,7 +95,7 @@ abstract class FunctionalTest extends SapphireTest implements TestOnly
// Disable theme, if necessary
if (static::get_disable_themes()) {
SSViewer::config()->update('theme_enabled', false);
SSViewer::config()->set('theme_enabled', false);
}
// Flush user
@ -102,9 +103,11 @@ abstract class FunctionalTest extends SapphireTest implements TestOnly
// Switch to draft site, if necessary
// If you rely on this you should be crafting stage-specific urls instead though.
if (static::get_use_draft_site()) {
$this->useDraftSite();
}
Deprecation::withNoReplacement(function () {
if (static::get_use_draft_site()) {
$this->useDraftSite();
}
});
// Unprotect the site, tests are running with the assumption it's off. They will enable it on a case-by-case
// basis.

View File

@ -41,7 +41,6 @@ use SilverStripe\View\SSViewer;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mailer\Transport\NullTransport;
use Symfony\Component\Messenger\MessageBusInterface;
/**
* Test case class for the Silverstripe framework.
@ -290,7 +289,7 @@ abstract class SapphireTest extends TestCase implements TestOnly
}
if (class_exists(Cookie::class)) {
Cookie::config()->update('report_errors', false);
Cookie::config()->set('report_errors', false);
}
if (class_exists(RootURLController::class)) {
@ -317,7 +316,7 @@ abstract class SapphireTest extends TestCase implements TestOnly
// turn off template debugging
if (class_exists(SSViewer::class)) {
SSViewer::config()->update('source_file_comments', false);
SSViewer::config()->set('source_file_comments', false);
}
// Set up the test mailer and register it as a service
@ -1162,7 +1161,7 @@ abstract class SapphireTest extends TestCase implements TestOnly
if (strpos($themeBaseDir ?? '', BASE_PATH) === 0) {
$themeBaseDir = substr($themeBaseDir ?? '', strlen(BASE_PATH));
}
SSViewer::config()->update('theme_enabled', true);
SSViewer::config()->set('theme_enabled', true);
SSViewer::set_themes([$themeBaseDir . '/themes/' . $theme, '$default']);
try {

View File

@ -21,9 +21,12 @@ use SilverStripe\Dev\BuildTask;
use SilverStripe\Assets\Dev\Tasks\SecureAssetsMigrationHelper;
use SilverStripe\UserForms\Task\RecoverUploadLocationsHelper;
use \Bramus\Monolog\Formatter\ColoredLineFormatter;
use SilverStripe\Dev\Deprecation;
/**
* Migrates all 3.x file dataobjects to use the new DBFile field.
*
* @deprected 4.12.0 Will be removed without equivalent functionality to replace it
*/
class MigrateFileTask extends BuildTask
{
@ -52,6 +55,12 @@ class MigrateFileTask extends BuildTask
/** @var Logger */
private $logger;
public function __construct()
{
Deprecation::notice('4.12.0', 'Will be removed without equivalent functionality to replace it', Deprecation::SCOPE_CLASS);
parent::__construct();
}
public function run($request)
{
$this->addLogHandlers();

View File

@ -262,7 +262,7 @@ class GridFieldAddExistingAutocompleter extends AbstractGridFieldComponent imple
$json = [];
Config::nest();
SSViewer::config()->update('source_file_comments', false);
SSViewer::config()->set('source_file_comments', false);
$viewer = SSViewer::fromString($this->resultsFormat);
foreach ($results as $result) {
$title = Convert::html2raw($viewer->process($result));

View File

@ -8,6 +8,7 @@ use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Config\Config;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ArrayList;
/**
* Adds an "Export list" button to the bottom of a {@link GridField}.
@ -221,6 +222,7 @@ class GridFieldExportButton extends AbstractGridFieldComponent implements GridFi
? $gridFieldColumnsComponent->getColumnsHandled($gridField)
: [];
/** @var ArrayList|DataList $items */
// Remove limit as the list may be paginated, we want the full list for the export
$items = $items->limit(null);

View File

@ -102,7 +102,10 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
callable $updateSearchContext = null,
callable $updateSearchForm = null
) {
$this->useLegacyFilterHeader = Config::inst()->get(self::class, 'force_legacy') || $useLegacy;
$forceLegacy = Deprecation::withNoReplacement(function () {
return Config::inst()->get(self::class, 'force_legacy');
});
$this->useLegacyFilterHeader = $forceLegacy || $useLegacy;
$this->updateSearchContextCallback = $updateSearchContext;
$this->updateSearchFormCallback = $updateSearchForm;
}
@ -523,7 +526,9 @@ class GridFieldFilterHeader extends AbstractGridFieldComponent implements GridFi
}
if ($this->useLegacyFilterHeader) {
$fieldsList = $this->getLegacyFilterHeader($gridField);
$fieldsList = Deprecation::withNoReplacement(function () use ($gridField) {
return $this->getLegacyFilterHeader($gridField);
});
$forTemplate->Fields = $fieldsList;
$filterTemplates = SSViewer::get_templates_by_class($this, '_Row', __CLASS__);
return ['header' => $forTemplate->renderWith($filterTemplates)];

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Forms;
use SilverStripe\Dev\Deprecation;
use Exception;
use InvalidArgumentException;
use SilverStripe\Assets\Folder;
@ -622,13 +621,11 @@ class TreeDropdownField extends FormField
/**
* HTML-encoded label for this node, including css classes and other markup.
*
* @deprecated 4.0.1 Use setTitleField() instead
* @param string $field
* @return $this
*/
public function setLabelField($field)
{
Deprecation::notice('4.0.1', 'Use setTitleField() instead');
$this->labelField = $field;
return $this;
}
@ -636,12 +633,10 @@ class TreeDropdownField extends FormField
/**
* HTML-encoded label for this node, including css classes and other markup.
*
* @deprecated 4.0.1 Use getTitleField() instead
* @return string
*/
public function getLabelField()
{
Deprecation::notice('4.0.1', 'Use getTitleField() instead');
return $this->labelField;
}

View File

@ -6,6 +6,7 @@ namespace SilverStripe\Forms;
use SilverStripe\Assets\File;
use SilverStripe\Assets\Upload;
use SilverStripe\Assets\Upload_Validator;
use SilverStripe\Core\Convert;
/**
* Represents a form field which has an Upload() instance and can upload to a folder
@ -47,8 +48,8 @@ trait UploadReceiver
);
// get the lower max size
$maxUpload = File::ini2bytes(ini_get('upload_max_filesize'));
$maxPost = File::ini2bytes(ini_get('post_max_size'));
$maxUpload = Convert::memstring2bytes(ini_get('upload_max_filesize'));
$maxPost = Convert::memstring2bytes(ini_get('post_max_size'));
$this->getValidator()->setAllowedMaxFileSize(min($maxUpload, $maxPost));
}

View File

@ -178,18 +178,20 @@ class ArrayList extends ViewableData implements SS_List, Filterable, Sortable, L
/**
* Get a sub-range of this dataobjectset as an array
* Pass null to "remove the limit" - this is for consistency with DataList::limit(null) which itself will
* call SQLSelect::setLimit(null)
*
* @param int $length
* @param int|null $length
* @param int $offset
* @return static
*/
public function limit($length, $offset = 0)
{
// Type checking: designed for consistency with DataList::limit()
if (!is_numeric($length) || !is_numeric($offset)) {
if ((!is_numeric($length) || !is_numeric($offset)) && !is_null($length)) {
Deprecation::notice(
'4.3',
'Arguments to ArrayList::limit() should be numeric'
'Arguments to ArrayList::limit() should be numeric or null'
);
}

View File

@ -2,7 +2,6 @@
namespace SilverStripe\ORM\Connect;
use SilverStripe\Dev\Deprecation;
use Exception;
use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Config;
@ -60,12 +59,9 @@ abstract class DBSchemaManager
/**
* @param string $table
* @param string $class
*
* @deprecated 4.0.1 Will be removed without equivalent functionality
*/
public static function showTableNameWarning($table, $class)
{
Deprecation::notice('4.0.1', 'Will be removed without equivalent functionality');
static::$table_name_warnings[$table] = $class;
}

View File

@ -20,13 +20,6 @@ class MySQLTransactionManager implements TransactionManager
public function transactionStart($transactionMode = false, $sessionCharacteristics = false)
{
if ($transactionMode || $sessionCharacteristics) {
Deprecation::notice(
'4.4',
'$transactionMode and $sessionCharacteristics are deprecated and will be removed in SS5'
);
}
if ($this->inTransaction) {
throw new DatabaseException(
"Already in transaction, can't start another. Consider decorating with NestedTransactionManager."

View File

@ -2604,11 +2604,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
// Support for the old method during the deprecation period
if ($this->hasMethod('getCMSValidator')) {
Deprecation::notice(
'4.6',
'getCMSValidator() is removed in 5.0 in favour of getCMSCompositeValidator()'
);
$compositeValidator->addValidator($this->getCMSValidator());
}

View File

@ -187,7 +187,7 @@ PHP
$backURLs = [
$this->getRequest()->requestVar('BackURL'),
$this->getRequest()->getSession()->get('BackURL'),
Director::absoluteURL(AdminRootController::config()->get('url_base'), true),
Director::absoluteURL(AdminRootController::config()->get('url_base')),
];
$backURL = null;
foreach ($backURLs as $backURL) {

View File

@ -287,8 +287,11 @@ class SSViewer implements Flushable
return $themes;
}
// Support legacy behaviour
if ($theme = SSViewer::config()->uninherited('theme')) {
// Support @deprecated legacy behaviour
$theme = Deprecation::withNoReplacement(function () {
return SSViewer::config()->uninherited('theme');
});
if ($theme) {
return [self::PUBLIC_THEME, $theme, self::DEFAULT_THEME];
}

View File

@ -178,7 +178,6 @@ class i18n implements TemplateGlobalProvider
// inject the variables from injectionArray (if present)
$sprintfArgs = [];
if ($default && !preg_match('/\{[\w\d]*\}/i', $default ?? '') && preg_match('/%[s,d]/', $default ?? '')) {
Deprecation::notice('5.0', 'sprintf style localisation variables are deprecated');
$sprintfArgs = array_values($injection ?? []);
$injection = [];
}

View File

@ -6,7 +6,7 @@
<td colspan="$GridField.ExtraColumnsCount" class="ss-gridfield-last"></td>
<% else %>
<% loop $Fields %>
<td <% if FirstLast %>class="ss-gridfield-{$FirstLast}"<% end_if %>>$Value</td>
<td <% if $FirstLast %>class="ss-gridfield-{$FirstLast}"<% end_if %>>$Value</td>
<% end_loop %>
<% end_if %>
</tr>

View File

@ -45,7 +45,7 @@ class ControllerTest extends FunctionalTest
protected function setUp(): void
{
parent::setUp();
Director::config()->update('alternate_base_url', '/');
Director::config()->set('alternate_base_url', '/');
// Add test theme
$themeDir = substr(__DIR__, strlen(FRAMEWORK_DIR)) . '/ControllerTest/';

View File

@ -16,6 +16,7 @@ use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Environment;
use SilverStripe\Core\Kernel;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
/**
@ -856,6 +857,9 @@ class DirectorTest extends SapphireTest
public function testRequestFilterInDirectorTest()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$filter = new DirectorTest\TestRequestFilter;
$processor = new RequestProcessor([$filter]);

View File

@ -334,7 +334,7 @@ class EmailTest extends SapphireTest
public function testAdminEmailApplied()
{
Email::config()->update('admin_email', 'admin@example.com');
Email::config()->set('admin_email', 'admin@example.com');
$email = new Email();
$this->assertCount(1, $email->getFrom());
$this->assertSame('admin@example.com', $email->getFrom()[0]->getAddress());

View File

@ -6,6 +6,7 @@ use ReflectionMethod;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Middleware\TrustedProxyMiddleware;
use SilverStripe\Control\Session;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
class HTTPRequestTest extends SapphireTest
@ -155,12 +156,18 @@ class HTTPRequestTest extends SapphireTest
*/
public function testDetectMethod($realMethod, $post, $expected)
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$actual = HTTPRequest::detect_method($realMethod, $post);
$this->assertEquals($expected, $actual);
}
public function testBadDetectMethod()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$this->expectException(\InvalidArgumentException::class);
HTTPRequest::detect_method('POST', ['_method' => 'Boom']);
}

View File

@ -11,6 +11,7 @@ use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
use SilverStripe\Control\Session;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\Dev\Deprecation;
/**
* Tests the {@link HTTP} class
@ -115,6 +116,9 @@ class HTTPTest extends FunctionalTest
public function testDeprecatedVaryHandling()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
/** @var Config */
Config::modify()->set(
HTTP::class,
@ -129,6 +133,9 @@ class HTTPTest extends FunctionalTest
public function testDeprecatedCacheControlHandling()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
HTTPCacheControlMiddleware::singleton()->publicCache();
/** @var Config */
@ -149,6 +156,9 @@ class HTTPTest extends FunctionalTest
public function testDeprecatedCacheControlHandlingOnMaxAge()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
HTTPCacheControlMiddleware::singleton()->publicCache();
/** @var Config */
@ -169,6 +179,9 @@ class HTTPTest extends FunctionalTest
public function testDeprecatedCacheControlHandlingThrowsWithUnknownDirectives()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$this->expectException(\LogicException::class);
$this->expectExceptionMessageMatches('/Found unsupported legacy directives in HTTP\.cache_control: unknown/');
/** @var Config */

View File

@ -107,7 +107,7 @@ class SessionTest extends SapphireTest
->setScheme('https');
Cookie::set(session_name(), '1234');
$session = new Session(null); // unstarted session
$session->config()->update('cookie_secure', true);
$session->config()->set('cookie_secure', true);
$session->start($req);
$this->assertEquals(session_name(), $session->config()->get('cookie_name_secure'));
}
@ -270,7 +270,7 @@ class SessionTest extends SapphireTest
->setScheme('https');
$session = new Session(null); // unstarted session
Cookie::set($session->config()->get('cookie_name_secure'), '1234');
$session->config()->update('cookie_secure', true);
$session->config()->set('cookie_secure', true);
$this->assertTrue($session->requestContainsSessionId($req));
}

View File

@ -5,6 +5,7 @@ namespace SilverStripe\Core\Tests;
use Exception;
use InvalidArgumentException;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\View\Parsers\URLSegmentFilter;
use stdClass;
@ -217,6 +218,9 @@ PHP
*/
public function testArray2JSON()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$val = [
'Joe' => 'Bloggs',
'Tom' => 'Jones',
@ -237,6 +241,9 @@ PHP
*/
public function testJSON2Array()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$val = '{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}';
$decoded = Convert::json2array($val);
$this->assertEquals(3, count($decoded ?? []), '3 items in the decoded array');
@ -250,6 +257,9 @@ PHP
*/
public function testJSON2Obj()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$val = '{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}';
$obj = Convert::json2obj($val);
$this->assertEquals('Bloggs', $obj->Joe);
@ -264,7 +274,7 @@ PHP
*/
public function testRaw2URL()
{
URLSegmentFilter::config()->update('default_allow_multibyte', false);
URLSegmentFilter::config()->set('default_allow_multibyte', false);
$this->assertEquals('foo', Convert::raw2url('foo'));
$this->assertEquals('foo-and-bar', Convert::raw2url('foo & bar'));
$this->assertEquals('foo-and-bar', Convert::raw2url('foo &amp; bar!'));
@ -359,6 +369,9 @@ PHP
*/
public function testRaw2JSON()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
// Test object
$input = new stdClass();
@ -390,6 +403,9 @@ PHP
*/
public function testRaw2JsonWithContext()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$data = ['foo' => 'b"ar'];
$expected = '{"foo":"b\u0022ar"}';
$result = Convert::raw2json($data, JSON_HEX_QUOT);

View File

@ -19,6 +19,7 @@ use SilverStripe\Core\Tests\ObjectTest\ExtensionTest3;
use SilverStripe\Core\Tests\ObjectTest\MyObject;
use SilverStripe\Core\Tests\ObjectTest\MySubObject;
use SilverStripe\Core\Tests\ObjectTest\TestExtension;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Versioned\Versioned;
@ -110,6 +111,9 @@ class ObjectTest extends SapphireTest
public function testStaticGetterMethod()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$obj = singleton(MyObject::class);
$this->assertEquals(
'MyObject',
@ -120,6 +124,9 @@ class ObjectTest extends SapphireTest
public function testStaticInheritanceGetters()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$subObj = singleton(MyObject::class);
$this->assertEquals(
$subObj->stat('mystaticProperty'),
@ -130,6 +137,9 @@ class ObjectTest extends SapphireTest
public function testStaticSettingOnSingletons()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$singleton1 = singleton(MyObject::class);
$singleton2 = singleton(MyObject::class);
$singleton1->set_stat('mystaticProperty', 'changed');
@ -142,6 +152,9 @@ class ObjectTest extends SapphireTest
public function testStaticSettingOnInstances()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$instance1 = new ObjectTest\MyObject();
$instance2 = new ObjectTest\MyObject();
$instance1->set_stat('mystaticProperty', 'changed');

View File

@ -59,7 +59,7 @@ class BacktraceTest extends SapphireTest
'args' => ['myarg' => 'myval']
]
];
Backtrace::config()->update(
Backtrace::config()->merge(
'ignore_function_args',
[
['MyClass', 'myIgnoredClassFunction'],
@ -101,7 +101,7 @@ class BacktraceTest extends SapphireTest
'args' => ['myarg' => 'myval']
]
];
Backtrace::config()->update(
Backtrace::config()->merge(
'ignore_function_args',
[
['*', 'myIgnoredClassFunction'],

View File

@ -7,6 +7,7 @@ use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Dev\Tests\DeprecationTest\DeprecationTestObject;
use SilverStripe\Core\Injector\Injector;
class DeprecationTest extends SapphireTest
{
@ -16,6 +17,8 @@ class DeprecationTest extends SapphireTest
private $oldHandler = null;
private bool $noticesWereEnabled = false;
protected function setup(): void
{
// Use custom error handler for two reasons:
@ -23,6 +26,7 @@ class DeprecationTest extends SapphireTest
// - Allow the use of expectDeprecation(), which doesn't work with E_USER_DEPRECATION by default
// https://github.com/laminas/laminas-di/pull/30#issuecomment-927585210
parent::setup();
$this->noticesWereEnabled = Deprecation::isEnabled();
$this->oldHandler = set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) {
if ($errno === E_USER_DEPRECATED) {
if (str_contains($errstr, 'SilverStripe\\Dev\\Tests\\DeprecationTest')) {
@ -42,23 +46,140 @@ class DeprecationTest extends SapphireTest
protected function tearDown(): void
{
Deprecation::disable();
if (!$this->noticesWereEnabled) {
Deprecation::disable();
}
restore_error_handler();
$this->oldHandler = null;
parent::tearDown();
}
private function myDeprecatedMethod(): string
{
Deprecation::notice('1.2.3', 'My message');
return 'abc';
}
public function testNotice()
{
$message = implode(' ', [
'SilverStripe\Dev\Tests\DeprecationTest->testNotice is deprecated.',
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
'My message.',
'Called from PHPUnit\Framework\TestCase->runTest.'
'Called from SilverStripe\Dev\Tests\DeprecationTest->testNotice.'
]);
$this->expectDeprecation();
$this->expectDeprecationMessage($message);
Deprecation::enable();
Deprecation::notice('1.2.3', 'My message');
$ret = $this->myDeprecatedMethod();
$this->assertSame('abc', $ret);
// call outputNotices() directly because the regular shutdown function that emits
// the notices within Deprecation won't be called until after this unit-test has finished
Deprecation::outputNotices();
}
public function testCallUserFunc()
{
$message = implode(' ', [
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
'My message.',
'Called from SilverStripe\Dev\Tests\DeprecationTest->testCallUserFunc.'
]);
$this->expectDeprecation();
$this->expectDeprecationMessage($message);
Deprecation::enable();
$ret = call_user_func([$this, 'myDeprecatedMethod']);
$this->assertSame('abc', $ret);
Deprecation::outputNotices();
}
public function testCallUserFuncArray()
{
$message = implode(' ', [
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
'My message.',
'Called from SilverStripe\Dev\Tests\DeprecationTest->testCallUserFuncArray.'
]);
$this->expectDeprecation();
$this->expectDeprecationMessage($message);
Deprecation::enable();
$ret = call_user_func_array([$this, 'myDeprecatedMethod'], []);
$this->assertSame('abc', $ret);
Deprecation::outputNotices();
}
public function testWithNoReplacementDefault()
{
Deprecation::enable();
$ret = Deprecation::withNoReplacement(function () {
return $this->myDeprecatedMethod();
});
$this->assertSame('abc', $ret);
Deprecation::outputNotices();
}
public function testWithNoReplacementTrue()
{
$message = implode(' ', [
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
'My message.',
'Called from SilverStripe\Dev\Tests\DeprecationTest->testWithNoReplacementTrue.'
]);
$this->expectDeprecation();
$this->expectDeprecationMessage($message);
Deprecation::enable(true);
$ret = Deprecation::withNoReplacement(function () {
return $this->myDeprecatedMethod();
});
$this->assertSame('abc', $ret);
Deprecation::outputNotices();
}
public function testWithNoReplacementTrueCallUserFunc()
{
$message = implode(' ', [
'SilverStripe\Dev\Tests\DeprecationTest->myDeprecatedMethod is deprecated.',
'My message.',
'Called from SilverStripe\Dev\Tests\DeprecationTest->testWithNoReplacementTrueCallUserFunc.'
]);
$this->expectDeprecation();
$this->expectDeprecationMessage($message);
Deprecation::enable(true);
$ret = Deprecation::withNoReplacement(function () {
return call_user_func([$this, 'myDeprecatedMethod']);
});
$this->assertSame('abc', $ret);
Deprecation::outputNotices();
}
public function testClassWithNoReplacement()
{
$message = implode(' ', [
'SilverStripe\Dev\Tests\DeprecationTest\DeprecationTestObject is deprecated.',
'Some class message.',
'Called from SilverStripe\Dev\Tests\DeprecationTest->testClassWithNoReplacement.'
]);
$this->expectDeprecation();
$this->expectDeprecationMessage($message);
Deprecation::enable(true);
// using this syntax because my IDE was complaining about DeprecationTestObject not existing
// when trying to use `new DeprecationTestObject();`
$class = DeprecationTestObject::class;
new $class();
Deprecation::outputNotices();
}
public function testClassWithInjectorWithNoReplacement()
{
$message = implode(' ', [
'SilverStripe\Dev\Tests\DeprecationTest\DeprecationTestObject is deprecated.',
'Some class message.',
'Called from SilverStripe\Dev\Tests\DeprecationTest->testClassWithInjectorWithNoReplacement.'
]);
$this->expectDeprecation();
$this->expectDeprecationMessage($message);
Deprecation::enable(true);
Injector::inst()->get(DeprecationTestObject::class);
Deprecation::outputNotices();
}
/**
@ -66,8 +187,12 @@ class DeprecationTest extends SapphireTest
*/
public function testDisabled()
{
if ($this->noticesWereEnabled) {
$this->markTestSkipped('Notices are enabled for this project outside of this unit test');
}
// test that no error error is raised because by default Deprecation is disabled
Deprecation::notice('4.5.6', 'My message');
$this->myDeprecatedMethod();
Deprecation::outputNotices();
}
// The following tests would be better to put in the silverstripe/config module, however this is not
@ -76,7 +201,6 @@ class DeprecationTest extends SapphireTest
// Adding a _config.php file will break existing unit-tests within silverstripe/config
// It is possible to put DeprecationTestObject in framework and the unit tests in config, however
// that's probably messier then just having everything within framework
public function testConfigGetFirst()
{
$message = implode(' ', [
@ -87,6 +211,7 @@ class DeprecationTest extends SapphireTest
$this->expectDeprecationMessage($message);
Deprecation::enable();
Config::inst()->get(DeprecationTestObject::class, 'first_config');
Deprecation::outputNotices();
}
public function testConfigGetSecond()
@ -99,6 +224,7 @@ class DeprecationTest extends SapphireTest
$this->expectDeprecationMessage($message);
Deprecation::enable();
Config::inst()->get(DeprecationTestObject::class, 'second_config');
Deprecation::outputNotices();
}
public function testConfigGetThird()
@ -108,6 +234,7 @@ class DeprecationTest extends SapphireTest
$this->expectDeprecationMessage($message);
Deprecation::enable();
Config::inst()->get(DeprecationTestObject::class, 'third_config');
Deprecation::outputNotices();
}
public function testConfigSet()
@ -120,6 +247,7 @@ class DeprecationTest extends SapphireTest
$this->expectDeprecationMessage($message);
Deprecation::enable();
Config::modify()->set(DeprecationTestObject::class, 'first_config', 'abc');
Deprecation::outputNotices();
}
public function testConfigMerge()
@ -132,5 +260,6 @@ class DeprecationTest extends SapphireTest
$this->expectDeprecationMessage($message);
Deprecation::enable();
Config::modify()->merge(DeprecationTestObject::class, 'array_config', ['abc']);
Deprecation::outputNotices();
}
}

View File

@ -4,9 +4,22 @@ namespace SilverStripe\Dev\Tests\DeprecationTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
use SilverStripe\Dev\Deprecation;
class DeprecationTestObject extends DataObject implements TestOnly
{
public function __construct()
{
parent::__construct();
Deprecation::withNoReplacement(function () {
Deprecation::notice(
'1.2.3',
'Some class message',
Deprecation::SCOPE_CLASS
);
});
}
private static $db = [
"Name" => "Varchar"
];

View File

@ -18,7 +18,7 @@ class DevAdminControllerTest extends FunctionalTest
{
parent::setUp();
DevelopmentAdmin::config()->update(
DevelopmentAdmin::config()->merge(
'registered_controllers',
[
'x1' => [

View File

@ -200,7 +200,7 @@ class ConfirmedPasswordFieldTest extends SapphireTest
$this->assertSame($expectValid, $result, 'Validate method should return its result');
$this->assertSame($expectValid, $validator->getResult()->isValid());
if ($expectedMessage) {
$this->assertStringContainsString($expectedMessage, $validator->getResult()->serialize());
$this->assertStringContainsString($expectedMessage, json_encode($validator->getResult()->__serialize()));
}
}
@ -235,7 +235,7 @@ class ConfirmedPasswordFieldTest extends SapphireTest
$this->assertFalse($validator->getResult()->isValid());
$this->assertStringContainsString(
'Passwords must have at least one digit and one alphanumeric character',
$validator->getResult()->serialize()
json_encode($validator->getResult()->__serialize())
);
}
@ -254,7 +254,7 @@ class ConfirmedPasswordFieldTest extends SapphireTest
$this->assertFalse($validator->getResult()->isValid());
$this->assertStringContainsString(
'You must enter your current password',
$validator->getResult()->serialize()
json_encode($validator->getResult()->__serialize())
);
}
@ -276,7 +276,7 @@ class ConfirmedPasswordFieldTest extends SapphireTest
$this->assertFalse($validator->getResult()->isValid());
$this->assertStringContainsString(
'You must be logged in to change your password',
$validator->getResult()->serialize()
json_encode($validator->getResult()->__serialize())
);
}
@ -302,7 +302,7 @@ class ConfirmedPasswordFieldTest extends SapphireTest
$this->assertFalse($validator->getResult()->isValid());
$this->assertStringContainsString(
'The current password you have entered is not correct',
$validator->getResult()->serialize()
json_encode($validator->getResult()->__serialize())
);
}

View File

@ -23,7 +23,7 @@ class CurrencyFieldDisabledTest extends SapphireTest
*/
public function testFieldWithCustomisedCurrencySymbol()
{
DBCurrency::config()->update('currency_symbol', '€');
DBCurrency::config()->set('currency_symbol', '€');
$field = new CurrencyField_Disabled('Test', '', '€5.00');
$result = $field->Field();

View File

@ -28,7 +28,7 @@ class CurrencyFieldReadonlyTest extends SapphireTest
public function testFieldWithOutValue()
{
DBCurrency::config()->update('currency_symbol', 'AUD');
DBCurrency::config()->set('currency_symbol', 'AUD');
$field = new CurrencyField_Readonly('Test', '', null);
$result = $field->Field();
@ -42,7 +42,7 @@ class CurrencyFieldReadonlyTest extends SapphireTest
*/
public function testFieldWithCustomisedCurrencySymbol()
{
DBCurrency::config()->update('currency_symbol', '€');
DBCurrency::config()->set('currency_symbol', '€');
$field = new CurrencyField_Readonly('Test', '', '€5.00');
$result = $field->Field();

View File

@ -67,7 +67,7 @@ class CurrencyFieldTest extends SapphireTest
);
//tests with updated currency symbol setting
DBCurrency::config()->update('currency_symbol', '€');
DBCurrency::config()->set('currency_symbol', '€');
$f->setValue('123.45');
$this->assertTrue(
@ -180,7 +180,7 @@ class CurrencyFieldTest extends SapphireTest
);
//update currency symbol via config
DBCurrency::config()->update('currency_symbol', '€');
DBCurrency::config()->set('currency_symbol', '€');
$f->setValue('123.45');
$this->assertEquals(
@ -263,7 +263,7 @@ class CurrencyFieldTest extends SapphireTest
);
//tests with updated currency symbol setting
DBCurrency::config()->update('currency_symbol', '€');
DBCurrency::config()->set('currency_symbol', '€');
$f->setValue('€123.45');
$this->assertEquals(
@ -302,11 +302,14 @@ class CurrencyFieldTest extends SapphireTest
$field = new CurrencyField('Test', '', '$5.00');
$validator = new RequiredFields();
DBCurrency::config()->update('currency_symbol', '€');
DBCurrency::config()->set('currency_symbol', '€');
$result = $field->validate($validator);
$this->assertFalse($result, 'Validation should fail since wrong currency was used');
$this->assertFalse($validator->getResult()->isValid(), 'Validator should receive failed state');
$this->assertStringContainsString('Please enter a valid currency', $validator->getResult()->serialize());
$this->assertStringContainsString(
'Please enter a valid currency',
json_encode($validator->getResult()->__serialize())
);
}
}

View File

@ -31,7 +31,7 @@ class FormFieldTest extends SapphireTest
{
Config::nest();
FormField::config()->update(
FormField::config()->merge(
'default_classes',
[
'class1',
@ -42,7 +42,7 @@ class FormFieldTest extends SapphireTest
$this->assertStringContainsString('class1', $field->extraClass(), 'Class list does not contain expected class');
FormField::config()->update(
FormField::config()->merge(
'default_classes',
[
'class1',
@ -54,7 +54,7 @@ class FormFieldTest extends SapphireTest
$this->assertStringContainsString('class1 class2', $field->extraClass(), 'Class list does not contain expected class');
FormField::config()->update(
FormField::config()->merge(
'default_classes',
[
'class3',
@ -69,7 +69,7 @@ class FormFieldTest extends SapphireTest
$this->assertStringNotContainsString('class3', $field->extraClass(), 'Class list contains unexpected class');
TextField::config()->update(
TextField::config()->merge(
'default_classes',
[
'textfield-class',

View File

@ -792,7 +792,7 @@ class FormTest extends FunctionalTest
public function testDefaultClasses()
{
Form::config()->update(
Form::config()->merge(
'default_classes',
[
'class1',
@ -803,7 +803,7 @@ class FormTest extends FunctionalTest
$this->assertStringContainsString('class1', $form->extraClass(), 'Class list does not contain expected class');
Form::config()->update(
Form::config()->merge(
'default_classes',
[
'class1',
@ -815,7 +815,7 @@ class FormTest extends FunctionalTest
$this->assertStringContainsString('class1 class2', $form->extraClass(), 'Class list does not contain expected class');
Form::config()->update(
Form::config()->merge(
'default_classes',
[
'class3',

View File

@ -4,6 +4,7 @@ namespace SilverStripe\Logging\Tests;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Logging\MonologErrorHandler;
@ -26,8 +27,10 @@ class MonologErrorHandlerTest extends SapphireTest
$handler->pushLogger($logger)->pushLogger($logger);
$this->assertCount(2, $handler->getLoggers(), 'Loggers are pushed to the stack');
$handler->setLogger($logger);
$this->assertCount(1, $handler->getLoggers(), 'setLogger resets stack and pushes');
if (!Deprecation::isEnabled()) {
$handler->setLogger($logger);
$this->assertCount(1, $handler->getLoggers(), 'setLogger resets stack and pushes');
}
$handler->setLoggers([]);
$this->assertCount(0, $handler->getLoggers(), 'setLoggers overwrites all configured loggers');

View File

@ -133,6 +133,21 @@ class ArrayListTest extends SapphireTest
);
}
public function testLimitNull()
{
$list = new ArrayList(
[
['Key' => 1], ['Key' => 2], ['Key' => 3]
]
);
$this->assertEquals(
$list->limit(null, 0)->toArray(),
[
['Key' => 1], ['Key' => 2], ['Key' => 3]
]
);
}
public function testAddRemove()
{
$list = new ArrayList(

View File

@ -101,7 +101,7 @@ class DataObjectSchemaGenerationTest extends SapphireTest
// Table will have been initially created by the $extraDataObjects setting
// Let's insert a new field here
TestObject::config()->update(
TestObject::config()->merge(
'db',
[
'SecretField' => 'Varchar(100)'
@ -170,7 +170,7 @@ class DataObjectSchemaGenerationTest extends SapphireTest
// Table will have been initially created by the $extraDataObjects setting
// Update the SearchFields index here
TestIndexObject::config()->update(
TestIndexObject::config()->merge(
'indexes',
[
'SearchFields' => [
@ -265,35 +265,35 @@ class DataObjectSchemaGenerationTest extends SapphireTest
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', 'Sort ASC');
Config::inst()->set(SortedObject::class, 'default_sort', 'Sort ASC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', 'Sort DESC');
Config::inst()->set(SortedObject::class, 'default_sort', 'Sort DESC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', '"Sort" DESC');
Config::inst()->set(SortedObject::class, 'default_sort', '"Sort" DESC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', '"DataObjectSchemaGenerationTest_SortedObject"."Sort" ASC');
Config::inst()->set(SortedObject::class, 'default_sort', '"DataObjectSchemaGenerationTest_SortedObject"."Sort" ASC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', '"Sort" DESC, "Title" ASC');
Config::inst()->set(SortedObject::class, 'default_sort', '"Sort" DESC, "Title" ASC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
@ -305,7 +305,7 @@ class DataObjectSchemaGenerationTest extends SapphireTest
], $indexes);
DataObject::getSchema()->reset();
// make sure that specific indexes aren't overwritten
Config::inst()->update(SortedObject::class, 'indexes', [
Config::inst()->merge(SortedObject::class, 'indexes', [
'Sort' => [
'type' => 'unique',
'columns' => ['Sort'],

View File

@ -37,7 +37,7 @@ class HierachyCacheTest extends SapphireTest
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
HideTestObject::config()->update(
HideTestObject::config()->merge(
'hide_from_hierarchy',
[ HideTestSubObject::class ]
);

View File

@ -273,7 +273,7 @@ class HierarchyTest extends SapphireTest
public function testHideFromHierarchy()
{
HierarchyTest\HideTestObject::config()->update(
HierarchyTest\HideTestObject::config()->merge(
'hide_from_hierarchy',
[ HierarchyTest\HideTestSubObject::class ]
);

View File

@ -423,7 +423,7 @@ class ManyManyListTest extends SapphireTest
$obj->Clients()->add($obj2, ['Worth' => $money, 'Reference' => 'B']);
// Set the default sort for this relation
Config::inst()->update('ManyManyListTest_ExtraFields_Clients', 'default_sort', 'Reference ASC');
Config::inst()->set('ManyManyListTest_ExtraFields_Clients', 'default_sort', 'Reference ASC');
$clients = $obj->Clients();
$this->assertCount(2, $clients);
@ -432,7 +432,7 @@ class ManyManyListTest extends SapphireTest
$this->assertEquals('B', $second->Reference);
// Now we ensure the default sort is being respected by reversing its order
Config::inst()->update('ManyManyListTest_ExtraFields_Clients', 'default_sort', 'Reference DESC');
Config::inst()->set('ManyManyListTest_ExtraFields_Clients', 'default_sort', 'Reference DESC');
$reverseClients = $obj->Clients();
$this->assertCount(2, $reverseClients);

View File

@ -268,7 +268,7 @@ class ManyManyThroughListTest extends SapphireTest
{
$this->expectException(\InvalidArgumentException::class);
DataObject::reset();
ManyManyThroughListTest\Item::config()->update(
ManyManyThroughListTest\Item::config()->merge(
'db',
[
ManyManyThroughListTest\JoinObject::class => 'Text'
@ -416,7 +416,7 @@ class ManyManyThroughListTest extends SapphireTest
$this->assertSame('International', $second->Title);
// Ensure that we're respecting the default sort by reversing it
Config::inst()->update(FallbackLocale::class, 'default_sort', '"ManyManyThroughTest_FallbackLocale"."Sort" DESC');
Config::inst()->set(FallbackLocale::class, 'default_sort', '"ManyManyThroughTest_FallbackLocale"."Sort" DESC');
$reverse = $mexico->Fallbacks();
list($firstReverse, $secondReverse) = $reverse;

View File

@ -8,7 +8,6 @@ use SilverStripe\ORM\Connect\MySQLDatabase;
use SilverStripe\ORM\Queries\SQLSelect;
use SilverStripe\SQLite\SQLite3Database;
use SilverStripe\PostgreSQL\PostgreSQLDatabase;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
class SQLSelectTest extends SapphireTest
@ -24,18 +23,6 @@ class SQLSelectTest extends SapphireTest
protected $oldDeprecation = null;
protected function setUp(): void
{
parent::setUp();
$this->oldDeprecation = Deprecation::dump_settings();
}
protected function tearDown(): void
{
Deprecation::restore_settings($this->oldDeprecation);
parent::tearDown();
}
public function testCount()
{

View File

@ -5,7 +5,6 @@ namespace SilverStripe\ORM\Tests;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\DataObject;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Dev\Deprecation;
use SilverStripe\ORM\Tests\TransactionTest\TestObject;
class TransactionTest extends SapphireTest
@ -20,18 +19,6 @@ class TransactionTest extends SapphireTest
private static $originalVersionInfo;
protected function setUp(): void
{
parent::setUp();
self::$originalVersionInfo = Deprecation::dump_settings();
}
protected function tearDown(): void
{
Deprecation::restore_settings(self::$originalVersionInfo);
parent::tearDown();
}
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
@ -166,9 +153,6 @@ class TransactionTest extends SapphireTest
return;
}
// This feature is deprecated in 4.4, but we're still testing it.
Deprecation::notification_version('4.3.0');
$page = new TestObject();
$page->Title = 'Read only success';
$page->write();

View File

@ -15,10 +15,6 @@ class SessionAuthenticationHandlerTest extends SapphireTest
protected $usesDatabase = true;
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testAuthenticateRequestDefersSessionStartWithoutSessionIdentifier()
{
$member = new Member(['Email' => 'test@example.com']);
@ -36,10 +32,6 @@ class SessionAuthenticationHandlerTest extends SapphireTest
$this->assertNull($matchedMember);
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testAuthenticateRequestStartsSessionWithSessionIdentifier()
{
$member = new Member(['Email' => 'test@example.com']);
@ -49,12 +41,13 @@ class SessionAuthenticationHandlerTest extends SapphireTest
$session = new Session(null); // unstarted
$session->set($handler->getSessionVariable(), $member->ID);
$session = new Session($session); // started
$req = new HTTPRequest('GET', '/');
$req->setSession($session);
// simulate detection of session cookie
Cookie::set(session_name(), '1234');
$session->start($req); // simulate detection of session cookie
$matchedMember = $handler->authenticateRequest($req);
$this->assertNotNull($matchedMember);

View File

@ -9,6 +9,7 @@ use SilverStripe\Security\Member;
use SilverStripe\Security\PasswordValidator;
use SilverStripe\Security\Security;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
class MemberCsvBulkLoaderTest extends SapphireTest
{
@ -105,7 +106,8 @@ class MemberCsvBulkLoaderTest extends SapphireTest
// TODO Direct getter doesn't work, wtf!
$this->assertEquals(Security::config()->password_encryption_algorithm, $member->getField('PasswordEncryption'));
$result = $member->checkPassword('mypassword');
$auth = new MemberAuthenticator();
$result = $auth->checkPassword($member, 'mypassword');
$this->assertTrue($result->isValid());
}
}

View File

@ -219,7 +219,7 @@ class MemberTest extends FunctionalTest
*/
public function testChangedPasswordEmaling()
{
Member::config()->update('notify_password_change', true);
Member::config()->set('notify_password_change', true);
$this->clearEmails();
@ -1187,7 +1187,7 @@ class MemberTest extends FunctionalTest
$this->assertStringContainsString($message, $response->getBody());
// Logging out from the second device - only one device being logged out
RememberLoginHash::config()->update('logout_across_devices', false);
RememberLoginHash::config()->set('logout_across_devices', false);
$this->get(
'Security/logout',
$this->session(),
@ -1205,7 +1205,7 @@ class MemberTest extends FunctionalTest
// If session-manager module is installed then logout_across_devices is modified so skip
if (!class_exists(LoginSession::class)) {
// Logging out from any device when all login hashes should be removed
RememberLoginHash::config()->update('logout_across_devices', true);
RememberLoginHash::config()->set('logout_across_devices', true);
Injector::inst()->get(IdentityStore::class)->logIn($m1, true);
$this->get('Security/logout', $this->session());
$this->assertEquals(
@ -1248,7 +1248,7 @@ class MemberTest extends FunctionalTest
{
$maxFailedLoginsAllowed = 3;
//set up the config variables to enable login lockouts
Member::config()->update('lock_out_after_incorrect_logins', $maxFailedLoginsAllowed);
Member::config()->set('lock_out_after_incorrect_logins', $maxFailedLoginsAllowed);
/** @var Member $member */
$member = $this->objFromFixture(Member::class, 'test');
@ -1282,7 +1282,7 @@ class MemberTest extends FunctionalTest
public function testMemberValidator()
{
// clear custom requirements for this test
Member_Validator::config()->update('customRequired', null);
Member_Validator::config()->set('customRequired', null);
/** @var Member $memberA */
$memberA = $this->objFromFixture(Member::class, 'admin');
/** @var Member $memberB */
@ -1358,7 +1358,7 @@ class MemberTest extends FunctionalTest
public function testMemberValidatorWithExtensions()
{
// clear custom requirements for this test
Member_Validator::config()->update('customRequired', null);
Member_Validator::config()->set('customRequired', null);
// create a blank form
$form = new MemberTest\ValidatorForm();
@ -1422,7 +1422,7 @@ class MemberTest extends FunctionalTest
public function testCustomMemberValidator()
{
// clear custom requirements for this test
Member_Validator::config()->update('customRequired', null);
Member_Validator::config()->set('customRequired', null);
$member = $this->objFromFixture(Member::class, 'admin');

View File

@ -3,6 +3,7 @@
namespace SilverStripe\Security\Tests;
use SilverStripe\Security\RandomGenerator;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
/**
@ -13,6 +14,9 @@ class RandomGeneratorTest extends SapphireTest
public function testGenerateEntropy()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$r = new RandomGenerator();
$this->assertNotNull($r->generateEntropy());
$this->assertNotEquals($r->generateEntropy(), $r->generateEntropy());

View File

@ -4,7 +4,6 @@ namespace SilverStripe\View\Tests;
use SilverStripe\ORM\ArrayLib;
use SilverStripe\ORM\FieldType\DBVarchar;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\View\ArrayData;
use stdClass;
@ -67,9 +66,6 @@ class ArrayDataTest extends SapphireTest
public function testGetArray()
{
$originalDeprecation = Deprecation::dump_settings();
Deprecation::notification_version('2.4');
$array = [
'Foo' => 'Foo',
'Bar' => 'Bar',
@ -79,8 +75,6 @@ class ArrayDataTest extends SapphireTest
$arrayData = new ArrayData($array);
$this->assertEquals($arrayData->toMap(), $array);
Deprecation::restore_settings($originalDeprecation);
}
public function testArrayToObject()

View File

@ -516,7 +516,7 @@ class RequirementsTest extends SapphireTest
$combinedFileName = '/_combinedfiles/RequirementsTest_bc-2a55d56.js';
$combinedFilePath = TestAssetStore::base_path() . $combinedFileName;
$html = $backend->includeInHTML(false, self::$html_template);
$html = $backend->includeInHTML(self::$html_template);
/* ASYNC IS INCLUDED IN SCRIPT TAG */
$this->assertMatchesRegularExpression(

View File

@ -34,6 +34,7 @@ use SilverStripe\View\Tests\SSViewerTest\SSViewerTestModel;
use SilverStripe\View\Tests\SSViewerTest\SSViewerTestModelController;
use SilverStripe\View\Tests\SSViewerTest\TestViewableData;
use SilverStripe\View\ViewableData;
use SilverStripe\Dev\Deprecation;
/**
* @skipUpgrade
@ -55,8 +56,8 @@ class SSViewerTest extends SapphireTest
protected function setUp(): void
{
parent::setUp();
SSViewer::config()->update('source_file_comments', false);
SSViewer_FromString::config()->update('cache_template', false);
SSViewer::config()->set('source_file_comments', false);
SSViewer_FromString::config()->set('cache_template', false);
TestAssetStore::activate('SSViewerTest');
$this->oldServer = $_SERVER;
}
@ -75,7 +76,10 @@ class SSViewerTest extends SapphireTest
*/
public function testCurrentTheme()
{
SSViewer::config()->update('theme', 'mytheme');
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
SSViewer::config()->set('theme', 'mytheme');
$this->assertEquals(
'mytheme',
SSViewer::config()->uninherited('theme'),
@ -1368,39 +1372,39 @@ after'
$this->assertEquals("12345678910", $result, "Numbers rendered in order");
//test First
$result = $this->render('<% loop Set %><% if First %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $IsFirst %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("1", $result, "Only the first number is rendered");
//test Last
$result = $this->render('<% loop Set %><% if Last %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $IsLast %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("10", $result, "Only the last number is rendered");
//test Even
$result = $this->render('<% loop Set %><% if Even() %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $Even() %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("246810", $result, "Even numbers rendered in order");
//test Even with quotes
$result = $this->render('<% loop Set %><% if Even("1") %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $Even("1") %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("246810", $result, "Even numbers rendered in order");
//test Even without quotes
$result = $this->render('<% loop Set %><% if Even(1) %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $Even(1) %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("246810", $result, "Even numbers rendered in order");
//test Even with zero-based start index
$result = $this->render('<% loop Set %><% if Even("0") %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $Even("0") %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("13579", $result, "Even (with zero-based index) numbers rendered in order");
//test Odd
$result = $this->render('<% loop Set %><% if Odd %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $Odd %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("13579", $result, "Odd numbers rendered in order");
//test FirstLast
$result = $this->render('<% loop Set %><% if FirstLast %>$Number$FirstLast<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $FirstLast %>$Number$FirstLast<% end_if %><% end_loop %>', $data);
$this->assertEquals("1first10last", $result, "First and last numbers rendered in order");
//test Middle
$result = $this->render('<% loop Set %><% if Middle %>$Number<% end_if %><% end_loop %>', $data);
$result = $this->render('<% loop Set %><% if $Middle %>$Number<% end_if %><% end_loop %>', $data);
$this->assertEquals("23456789", $result, "Middle numbers rendered in order");
//test MiddleString
@ -1729,7 +1733,7 @@ after'
$this->assertEqualIgnoringWhitespace(
'1ab23last',
$this->render(
'<% loop $Foo %>$Name<% loop Children %>$Name<% end_loop %><% if Last %>last<% end_if %>'
'<% loop $Foo %>$Name<% loop Children %>$Name<% end_loop %><% if $IsLast %>last<% end_if %>'
. '<% end_loop %>',
$data
)
@ -1937,7 +1941,7 @@ EOC;
public function testRenderWithSourceFileComments()
{
SSViewer::config()->update('source_file_comments', true);
SSViewer::config()->set('source_file_comments', true);
$i = __DIR__ . '/SSViewerTest/templates/Includes';
$f = __DIR__ . '/SSViewerTest/templates/SSViewerTestComments';
$templates = [
@ -2217,7 +2221,7 @@ EOC;
$this->render($content, null, null);
$this->assertFalse(file_exists($cacheFile ?? ''), 'Cache file was created when caching was off');
SSViewer_FromString::config()->update('cache_template', true);
SSViewer_FromString::config()->set('cache_template', true);
$this->render($content, null, null);
$this->assertTrue(file_exists($cacheFile ?? ''), 'Cache file wasn\'t created when it was meant to');
unlink($cacheFile ?? '');

View File

@ -1 +1 @@
<% if $Title %>$Title<% else %>Untitled<% end_if %> <% if $ArgA %>_ $ArgA <% end_if %>- <% if $First %>First-<% end_if %><% if $Last %>Last-<% end_if %><%if $MultipleOf(2) %>EVEN<% else %>ODD<% end_if %> top:$Top.Title
<% if $Title %>$Title<% else %>Untitled<% end_if %> <% if $ArgA %>_ $ArgA <% end_if %>- <% if $IsFirst %>First-<% end_if %><% if $IsLast %>Last-<% end_if %><%if $MultipleOf(2) %>EVEN<% else %>ODD<% end_if %> top:$Top.Title

View File

@ -1 +1 @@
$Title - <% loop $Items %>$Title<% if not Last %> - <% else %> - {$Top.Title}<% end_if %><% end_loop %>
$Title - <% loop $Items %>$Title<% if not $IsLast %> - <% else %> - {$Top.Title}<% end_if %><% end_loop %>

View File

@ -7,6 +7,7 @@ use SilverStripe\Dev\SapphireTest;
use SilverStripe\View\ArrayData;
use SilverStripe\View\SSViewer;
use SilverStripe\View\ViewableData;
use SilverStripe\Dev\Deprecation;
/**
* See {@link SSViewerTest->testCastingHelpers()} for more tests related to casting and ViewableData behaviour,
@ -208,6 +209,9 @@ class ViewableDataTest extends SapphireTest
public function testThemeDir()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
$themes = [
"silverstripe/framework:/tests/php/View/ViewableDataTest/testtheme",
SSViewer::DEFAULT_THEME

View File

@ -149,7 +149,7 @@ class i18nTest extends SapphireTest
public function testTemplateTranslation()
{
$oldLocale = i18n::get_locale();
i18n::config()->update('missing_default_warning', false);
i18n::config()->set('missing_default_warning', false);
/** @var SymfonyMessageProvider $provider */
$provider = Injector::inst()->get(MessageProvider::class);
@ -311,7 +311,7 @@ class i18nTest extends SapphireTest
* */
public function testNewTemplateTranslation()
{
i18n::config()->update('missing_default_warning', false);
i18n::config()->set('missing_default_warning', false);
/** @var SymfonyMessageProvider $provider */
$provider = Injector::inst()->get(MessageProvider::class);
@ -468,7 +468,7 @@ class i18nTest extends SapphireTest
public function testGetLanguageName()
{
i18n::config()->update(
i18n::config()->merge(
'common_languages',
['de_CGN' => ['name' => 'German (Cologne)', 'native' => 'K&ouml;lsch']]
);

View File

@ -82,7 +82,7 @@ trait i18nTestManifest
// Switch to test manifest
$s = DIRECTORY_SEPARATOR;
$this->alternateBasePath = __DIR__ . $s . 'i18nTest' . $s . "_fakewebroot";
Director::config()->update('alternate_base_folder', $this->alternateBasePath);
Director::config()->set('alternate_base_folder', $this->alternateBasePath);
// New module manifest
$moduleManifest = new ModuleManifest($this->alternateBasePath);

View File

@ -533,8 +533,8 @@ PHP;
public function testCollectFromFilesystemAndWriteMasterTables()
{
i18n::set_locale('en_US'); //set the locale to the US locale expected in the asserts
i18n::config()->update('default_locale', 'en_US');
i18n::config()->update('missing_default_warning', false);
i18n::config()->set('default_locale', 'en_US');
i18n::config()->set('missing_default_warning', false);
$c = i18nTextCollector::create();
$c->setWarnOnEmptyDefault(false);